Skip to content

Commit

Permalink
Merge pull request #76 from simonhamp/feature/combinator-plus-plus
Browse files Browse the repository at this point in the history
Feature/combinator plus plus
  • Loading branch information
simonhamp committed Aug 15, 2023
2 parents 48c02b7 + 41c1ba4 commit 4d75562
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 9 deletions.
64 changes: 57 additions & 7 deletions resources/js/components/FieldCombinator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
<h4 class="text-base font-bold">Combine multiple columns</h4>

<p>
Select any number of fields from your import file to be combined. Fields are
simply concatenated. Use the <code>separator</code> field to define how they
should be concatenated. If you don't choose a separator, the fields will be
imported as an array.
Select any number of fields from your import file to be combined. Fields are simply concatenated. Use the
<code>separator</code> field to define how they should be concatenated. If you don't choose a separator,
the fields will be imported as an array.
</p>

<SelectControl @change="(value) => rawSeparator = value" :selected="separatorOption">
Expand All @@ -28,10 +27,38 @@
<template #item="{ element, index }">
<div class="flex mb-2 space-x-2 items-start border-rounded bg-gray-100 p-2 handle">
<div>{{ index + 1 }}</div>
<SelectControl @change="(value) => columns[index] = value" :selected="columns[index]">
<SelectControl @change="(value) => changeField(index, value)" :selected="columns[index].name">
<option value="">- Select field -</option>
<option v-for="heading in headings" :value="heading">{{ heading }}</option>
<optgroup label="Imported column">
<option v-for="heading in headings" :value="heading">{{ heading }}</option>
</optgroup>
<optgroup label="Meta data">
<option value="meta.file">File name (with suffix): {{ meta.file }}</option>
<option value="meta.file_name">File name (without suffix): {{ meta.file_name }}</option>
<option value="meta.original_file">Original file name (with suffix): {{ meta.original_file }}</option>
<option value="meta.original_file_name">Original file name (without suffix): {{ meta.original_file_name }}</option>
</optgroup>
<optgroup label="Custom - same value for each row">
<option value="custom">Custom value</option>
</optgroup>
</SelectControl>
<label class="flex items-center space-x-2" v-if="columns[index].name === 'custom'">
<span>Value</span>
<input v-model="columns[index].value"
class="form-control form-input form-input-bordered flex-1">
</label>
<label v-if="! rawSeparator">
as
<input v-model="columns[index].as"
class="form-control form-input form-input-bordered mx-2">
</label>
<button @click="remove(index)">&times;</button>
</div>
</template>
Expand All @@ -56,6 +83,7 @@ export default {
'attribute',
'config',
'headings',
'meta',
],
data() {
Expand Down Expand Up @@ -106,20 +134,42 @@ export default {
methods: {
add() {
this.columns.push('');
if (Array.isArray(this.columns)) {
this.columns.push(this.template());
return;
}
this.columns = [this.template()];
},
remove(index) {
this.columns.splice(index, 1);
},
template() {
return {
name: '',
as: null,
value: null,
};
},
update() {
console.log(`Updating combinators for ${this.attribute}`, this.columns, this.rawSeparator);
this.$emit('update', this.attribute, {
columns: this.columns,
separator: this.rawSeparator,
});
},
changeField(index, value) {
this.columns[index].name = value;
// Reset 'value' when needed
if (value !== 'custom') {
this.columns[index].value = '';
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions resources/js/pages/Configure.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@
:attribute="field.attribute"
:config="combined[field.attribute]"
:headings="headings"
:meta="{
'file': file,
'file_name': file_name,
'original_file': config.original_filename,
'original_file_name': original_file_name,
}"
@update="setFieldCombinators">
</FieldCombinator>

Expand All @@ -109,6 +115,7 @@
class="form-control form-input form-input-bordered flex-1">
</label>

<!-- Random string length -->
<label class="flex items-center space-x-2" v-if="mappings[field.attribute] === 'random'">
<span>Length</span>
<input v-model="random[field.attribute]"
Expand Down
19 changes: 17 additions & 2 deletions src/Importer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace SimonHamp\LaravelNovaCsvImport;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Laravel\Nova\Resource;
Expand Down Expand Up @@ -155,8 +156,22 @@ public function getCombinedValues($key = null, $row = null)
$outputs = [];
$config = $this->combined_values[$key];

foreach ($config['columns'] as $field) {
$outputs[] = $this->getFieldValue($row, $field, $key);
foreach ($config['columns'] as $index => $field) {
$value = $field['value'] ?? false ?: $this->getFieldValue($row, $field['name'], $key);

// If some part of the value looks like a field name (e.g. `{{ name }}`), then replace that part for
// the actual value of that field
if (is_string($value) && preg_match_all('/{{\s*([a-z0-9_\.]+)\s*}}/i', $value, $matches)) {
foreach ($matches[1] as $match) {
$value = preg_replace('/{{\s*'.$match.'\s*}}/', $this->getFieldValue($row, $match, $key), $value);
}
}

if ($field['as'] ?? false) {
Arr::set($outputs, $field['as'], $value);
} else {
$outputs[$field['name'].'_'.$index] = $value;
}
}

if ($config['separator']) {
Expand Down

0 comments on commit 4d75562

Please sign in to comment.