+sub action_add_empty_mapping_line {
+ my ($self) = @_;
+
+ $self->profile_from_form;
+ $self->setup_help;
+
+ $self->js
+ ->append('#csv_import_mappings', $self->render('csv_import/_mapping_item', { layout => 0, output => 0 }))
+ ->hide('#mapping_empty')
+ ->render;
+}
+
+sub action_add_mapping_from_upload {
+ my ($self) = @_;
+
+ $self->profile_from_form;
+ $self->setup_help;
+
+ my $file = SL::SessionFile->new($self->csv_file_name, mode => '<', encoding => $self->profile->get('charset'));
+ if (!$file->fh) {
+ $self->js
+ ->flash('error', t8('No file has been uploaded yet.'))
+ ->render;
+ return;
+ }
+
+ my $csv = Text::CSV_XS->new({
+ binary => 1,
+ sep_char => $self->profile->get('sep_char'),
+ quote_char => $self->profile->get('quote_char'),
+ escape_char => $self->profile->get('escape_char'),
+ });
+
+ my $header = $csv->getline($file->fh) or do {
+ $self->js
+ ->flash('error', t8('No header found'))
+ ->render;
+ return;
+ };
+
+ for my $field (@$header) {
+ next if $self->mappings_for_profile->{$field};
+ $self->js->append(
+ '#csv_import_mappings',
+ $self->render('csv_import/_mapping_item', { layout => 0, output => 0 }, item => { from => $field }),
+ );
+ }
+
+ $self->js
+ ->hide('#mapping_empty')
+ ->render;
+}
+