Skip to content

Commit 4d75562

Browse files
authored
Merge pull request #76 from simonhamp/feature/combinator-plus-plus
Feature/combinator plus plus
2 parents 48c02b7 + 41c1ba4 commit 4d75562

File tree

3 files changed

+81
-9
lines changed

3 files changed

+81
-9
lines changed

resources/js/components/FieldCombinator.vue

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
<h4 class="text-base font-bold">Combine multiple columns</h4>
44

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

1211
<SelectControl @change="(value) => rawSeparator = value" :selected="separatorOption">
@@ -28,10 +27,38 @@
2827
<template #item="{ element, index }">
2928
<div class="flex mb-2 space-x-2 items-start border-rounded bg-gray-100 p-2 handle">
3029
<div>{{ index + 1 }}</div>
31-
<SelectControl @change="(value) => columns[index] = value" :selected="columns[index]">
30+
31+
<SelectControl @change="(value) => changeField(index, value)" :selected="columns[index].name">
3232
<option value="">- Select field -</option>
33-
<option v-for="heading in headings" :value="heading">{{ heading }}</option>
33+
34+
<optgroup label="Imported column">
35+
<option v-for="heading in headings" :value="heading">{{ heading }}</option>
36+
</optgroup>
37+
38+
<optgroup label="Meta data">
39+
<option value="meta.file">File name (with suffix): {{ meta.file }}</option>
40+
<option value="meta.file_name">File name (without suffix): {{ meta.file_name }}</option>
41+
<option value="meta.original_file">Original file name (with suffix): {{ meta.original_file }}</option>
42+
<option value="meta.original_file_name">Original file name (without suffix): {{ meta.original_file_name }}</option>
43+
</optgroup>
44+
45+
<optgroup label="Custom - same value for each row">
46+
<option value="custom">Custom value</option>
47+
</optgroup>
3448
</SelectControl>
49+
50+
<label class="flex items-center space-x-2" v-if="columns[index].name === 'custom'">
51+
<span>Value</span>
52+
<input v-model="columns[index].value"
53+
class="form-control form-input form-input-bordered flex-1">
54+
</label>
55+
56+
<label v-if="! rawSeparator">
57+
as
58+
<input v-model="columns[index].as"
59+
class="form-control form-input form-input-bordered mx-2">
60+
</label>
61+
3562
<button @click="remove(index)">&times;</button>
3663
</div>
3764
</template>
@@ -56,6 +83,7 @@ export default {
5683
'attribute',
5784
'config',
5885
'headings',
86+
'meta',
5987
],
6088
6189
data() {
@@ -106,20 +134,42 @@ export default {
106134
107135
methods: {
108136
add() {
109-
this.columns.push('');
137+
if (Array.isArray(this.columns)) {
138+
this.columns.push(this.template());
139+
return;
140+
}
141+
142+
this.columns = [this.template()];
110143
},
111144
112145
remove(index) {
113146
this.columns.splice(index, 1);
114147
},
115148
149+
template() {
150+
return {
151+
name: '',
152+
as: null,
153+
value: null,
154+
};
155+
},
156+
116157
update() {
117158
console.log(`Updating combinators for ${this.attribute}`, this.columns, this.rawSeparator);
118159
119160
this.$emit('update', this.attribute, {
120161
columns: this.columns,
121162
separator: this.rawSeparator,
122163
});
164+
},
165+
166+
changeField(index, value) {
167+
this.columns[index].name = value;
168+
169+
// Reset 'value' when needed
170+
if (value !== 'custom') {
171+
this.columns[index].value = '';
172+
}
123173
}
124174
}
125175
}

resources/js/pages/Configure.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@
9999
:attribute="field.attribute"
100100
:config="combined[field.attribute]"
101101
:headings="headings"
102+
:meta="{
103+
'file': file,
104+
'file_name': file_name,
105+
'original_file': config.original_filename,
106+
'original_file_name': original_file_name,
107+
}"
102108
@update="setFieldCombinators">
103109
</FieldCombinator>
104110

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

118+
<!-- Random string length -->
112119
<label class="flex items-center space-x-2" v-if="mappings[field.attribute] === 'random'">
113120
<span>Length</span>
114121
<input v-model="random[field.attribute]"

src/Importer.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace SimonHamp\LaravelNovaCsvImport;
44

55
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Support\Arr;
67
use Illuminate\Support\Facades\Hash;
78
use Illuminate\Support\Str;
89
use Laravel\Nova\Resource;
@@ -155,8 +156,22 @@ public function getCombinedValues($key = null, $row = null)
155156
$outputs = [];
156157
$config = $this->combined_values[$key];
157158

158-
foreach ($config['columns'] as $field) {
159-
$outputs[] = $this->getFieldValue($row, $field, $key);
159+
foreach ($config['columns'] as $index => $field) {
160+
$value = $field['value'] ?? false ?: $this->getFieldValue($row, $field['name'], $key);
161+
162+
// If some part of the value looks like a field name (e.g. `{{ name }}`), then replace that part for
163+
// the actual value of that field
164+
if (is_string($value) && preg_match_all('/{{\s*([a-z0-9_\.]+)\s*}}/i', $value, $matches)) {
165+
foreach ($matches[1] as $match) {
166+
$value = preg_replace('/{{\s*'.$match.'\s*}}/', $this->getFieldValue($row, $match, $key), $value);
167+
}
168+
}
169+
170+
if ($field['as'] ?? false) {
171+
Arr::set($outputs, $field['as'], $value);
172+
} else {
173+
$outputs[$field['name'].'_'.$index] = $value;
174+
}
160175
}
161176

162177
if ($config['separator']) {

0 commit comments

Comments
 (0)