Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into fix/updating-bard-con…
Browse files Browse the repository at this point in the history
…figs-in-fieldsets
  • Loading branch information
duncanmcclean committed Nov 6, 2024
2 parents 7b37259 + d21c014 commit 885eb55
Show file tree
Hide file tree
Showing 42 changed files with 1,395 additions and 792 deletions.
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# Changelog

### 1.1.2 (2024-11-06)

### What's fixed
* Fixed validation error when creating an import in a multi-site #27 by @duncanmcclean



## 1.1.1 (2024-11-04)

### What's fixed
* Fixed error when importing a Gutenberg block without content by @duncanmcclean



## 1.1.0 (2024-11-01)

### What's new
* Multi-site Support #13 by @duncanmcclean
* Entry parents can now be imported #20 by @duncanmcclean
* Import jobs are now processed in batches #16 by @duncanmcclean
* Transformers now have access to the `Import` object by @duncanmcclean
* Added a `messages` translation file for longer strings by @duncanmcclean
* You can now determine whether items should be created or updated when creating an import #11 by @duncanmcclean

### What's fixed
* Fixed `Unexpected data found` error when importing dates by @duncanmcclean
* Fix incorrect namespaces in tests by @duncanmcclean



## 1.0.2 (2024-10-28)

### What's fixed
Expand Down
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"dependencies": {
"axios": "^0.28.0",
"cross-env": "^7.0.2",
"marked": "^14.1.3",
"underscore": "^1.13.7",
"uniqid": "^5.4.0",
"vue": "^2.6.11"
},
"devDependencies": {
Expand Down
2 changes: 0 additions & 2 deletions resources/js/components/CreateImportForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@
<script>
import axios from 'axios';
import HasInputOptions from '../../../vendor/statamic/cms/resources/js/components/fieldtypes/HasInputOptions.js';
import Mappings from "./Mappings.vue";
export default {
components: {Mappings},
mixins: [HasInputOptions],
props: {
Expand Down
127 changes: 88 additions & 39 deletions resources/js/components/EditImportForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,72 @@
<p v-html="__('importer::messages.migrations_needed')"></p>
</div>

<div class="mt-3 card overflow-hidden">
<Mappings
:config="config"
:errors="errors"
:mappings-url="mappingsUrl"
@updated="config = $event"
/>
</div>
<publish-container
v-if="fieldset"
ref="container"
:name="publishContainer"
:blueprint="fieldset"
:values="values"
:meta="meta"
:errors="errors"
:track-dirty-state="trackDirtyState"
@updated="values = $event"
>
<div slot-scope="{ container, setFieldValue, setFieldMeta }">
<publish-tabs
:enable-sidebar="false"
@updated="setFieldValue"
@meta-updated="setFieldMeta"
@focus="container.$emit('focus', $event)"
@blur="container.$emit('blur', $event)"
></publish-tabs>
</div>
</publish-container>
</div>
</template>

<script>
import axios from 'axios';
import Mappings from "./Mappings.vue";
import HasHiddenFields from '../../../vendor/statamic/cms/resources/js/components/publish/HasHiddenFields';
export default {
components: {Mappings},
mixins: [HasHiddenFields],
props: {
publishContainer: String,
initialFieldset: Object,
initialValues: Object,
initialMeta: Object,
initialTitle: String,
action: String,
method: String,
breadcrumbs: Array,
title: String,
initialConfig: Object,
mappingsUrl: String,
batchesTableMissing: Boolean,
},
data() {
return {
fieldset: _.clone(this.initialFieldset),
values: _.clone(this.initialValues),
meta: _.clone(this.initialMeta),
error: null,
errors: {},
title: this.initialTitle,
saving: false,
config: this.initialConfig,
quickSaveKeyBinding: null,
trackDirtyState: true,
}
},
computed: {
hasErrors() {
return this.error || Object.keys(this.errors).length;
},
isDirty() {
return this.$dirty.has(this.publishContainer);
},
},
mounted() {
this.quickSaveKeyBinding = this.$keys.bindGlobal(['mod+s'], e => {
e.preventDefault();
Expand All @@ -70,30 +99,50 @@ export default {
this.saving = true;
this.clearErrors();
axios.patch(this.action, {
mappings: this.config.mappings,
unique_field: this.config.unique_field,
run: shouldRun,
})
.then(response => {
this.saving = false;
if (shouldRun) this.$toast.success(__('Saved & Running'));
if (! shouldRun) this.$toast.success(__('Saved'));
})
.catch(e => {
this.saving = false;
if (e.response && e.response.status === 422) {
const { message, errors } = e.response.data;
this.error = message;
this.errors = errors;
this.$toast.error(message);
return;
}
const message = data_get(e, 'response.data.message');
this.$toast.error(message || e);
});
setTimeout(() => {
this.$refs.container.saving();
this.performSaveRequest(shouldRun);
}, 151); // 150ms is the debounce time for fieldtype updates
},
performSaveRequest(shouldRun = false) {
const payload = _.clone(this.values);
if (shouldRun) {
payload['run'] = true;
}
this.$axios[this.method](this.action, payload).then(response => {
this.saving = false;
if (! response.data.saved) {
return this.$toast.error(__(`Couldn't save import`));
}
this.title = response.data.data.name;
this.$refs.container.saved();
this.$toast.success(__('Saved'));
clearTimeout(this.trackDirtyStateTimeout);
this.trackDirtyState = false;
this.fieldset = response.data.data.blueprint;
this.meta = response.data.data.meta;
this.values = this.resetValuesFromResponse(response.data.data.values);
this.trackDirtyStateTimeout = setTimeout(() => (this.trackDirtyState = true), 500);
this.$nextTick(() => this.$emit('saved', response));
}).catch(error => this.handleAxiosError(error));
},
handleAxiosError(e) {
this.saving = false;
if (e.response && e.response.status === 422) {
const { message, errors } = e.response.data;
this.error = message;
this.errors = errors;
this.$toast.error(message);
this.$reveal.invalid();
} else if (e.response) {
this.$toast.error(e.response.data.message);
} else {
this.$toast.error(e || 'Something went wrong');
}
},
},
}
Expand Down
92 changes: 92 additions & 0 deletions resources/js/components/Fieldtypes/ImportMappingsFieldtype.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<template>
<div>
<table class="grid-table table-auto field-mappings-table">
<thead>
<tr>
<th style="text-align: left">{{ __('Blueprint Field') }}</th>
<th style="text-align: left">{{ __('Data From Import') }}</th>
</tr>
</thead>
<tbody>
<tr v-for="field in meta.fields">
<td class="w-1/3">
<label class="text-sm font-medium" :for="`mappings.${field.handle}.key`">
{{ field.display }}
</label>
<span class="badge rounded-sm text-gray-700 dark:text-dark-100 inline-flex items-center p-0 border border-gray-300 dark:border-dark-300">
<span class="px-1">{{ __('Type') }}</span>
<span class="bg-white rounded-r-sm dark:bg-dark-300 px-1">{{ field.fieldtype_title }}</span>
</span>
</td>
<td>
<publish-container
:name="`mappings.${field.handle}`"
:values="value[field.handle]"
:meta="field.meta"
:errors="errors(field.handle)"
:track-dirty-state="false"
@updated="mappingUpdated(field.handle, $event)"
>
<div slot-scope="{ setFieldValue, setFieldMeta }">
<div class="-mx-4 md:-ml-6">
<publish-fields
:fields="field.fields"
:read-only="isReadOnly"
@updated="setFieldValue"
@meta-updated="setFieldMeta"
/>
</div>
</div>
</publish-container>
</td>
</tr>
</tbody>
</table>
</div>
</template>

<style>
.field-mappings-table .form-group {
padding-top: 16px;
padding-bottom: 16px;
}
.field-mappings-table .form-group:first-child {
padding-top: 0;
}
.field-mappings-table .form-group:last-child {
padding-bottom: 0;
}
</style>

<script>
export default {
mixins: [Fieldtype],
inject: [
'storeName',
],
methods: {
mappingUpdated(fieldHandle, value) {
this.$emit('input', {
...this.value,
[fieldHandle]: value,
});
},
errors(prefix) {
const state = this.$store.state.publish[this.storeName];
if (! state) return [];
return Object.keys(state.errors || [])
.filter(key => key.startsWith(`mappings.${prefix}`))
.reduce((acc, key) => {
acc[key.replace(`mappings.${prefix}.`, '')] = state.errors[key];
return acc;
}, {});
},
},
}
</script>
Loading

0 comments on commit 885eb55

Please sign in to comment.