diff --git a/resources/js/bootstrap/components.js b/resources/js/bootstrap/components.js
index 626ef0d368..091fb442b5 100644
--- a/resources/js/bootstrap/components.js
+++ b/resources/js/bootstrap/components.js
@@ -57,6 +57,7 @@ import Modal from '../components/Modal.vue';
import ConfirmationModal from '../components/modals/ConfirmationModal.vue';
import FavoriteCreator from '../components/FavoriteCreator.vue';
import KeyboardShortcutsModal from '../components/modals/KeyboardShortcutsModal.vue';
+import FieldActionModal from '../components/field-actions/FieldActionModal.vue';
import ResourceDeleter from '../components/ResourceDeleter.vue';
import Stack from '../components/stacks/Stack.vue';
import StackTest from '../components/stacks/StackTest.vue';
@@ -142,6 +143,7 @@ Vue.component('confirmation-modal', ConfirmationModal);
Vue.component('favorite-creator', FavoriteCreator);
Vue.component('keyboard-shortcuts-modal', KeyboardShortcutsModal);
Vue.component('resource-deleter', ResourceDeleter);
+Vue.component('field-action-modal', FieldActionModal);
Vue.component('stack', Stack);
Vue.component('stack-test', StackTest);
diff --git a/resources/js/components/field-actions/FieldAction.js b/resources/js/components/field-actions/FieldAction.js
index fce724c9ac..e0578a335f 100644
--- a/resources/js/components/field-actions/FieldAction.js
+++ b/resources/js/components/field-actions/FieldAction.js
@@ -26,7 +26,7 @@ export default class FieldAction {
return typeof this.#icon === 'function' ? this.#icon(this.#payload) : this.#icon;
}
- run() {
+ async run() {
this.#run(this.#payload);
}
}
diff --git a/resources/js/components/field-actions/FieldActionModal.vue b/resources/js/components/field-actions/FieldActionModal.vue
new file mode 100644
index 0000000000..658da8092a
--- /dev/null
+++ b/resources/js/components/field-actions/FieldActionModal.vue
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
diff --git a/resources/js/components/field-actions/FieldActions.js b/resources/js/components/field-actions/FieldActions.js
index 1e3b27fbff..68c6d1e8bb 100644
--- a/resources/js/components/field-actions/FieldActions.js
+++ b/resources/js/components/field-actions/FieldActions.js
@@ -16,6 +16,31 @@ class FieldActions {
get(name) {
return this.actions[name] || [];
}
+
+ modal(props) {
+ const name = props.fields ? 'field-action-modal' : 'confirmation-modal';
+ return new Promise((resolve) => {
+ const component = Statamic.$components.append(name, { props });
+ component.on('confirm', (data = {}) => {
+ if (props.keepOpen) {
+ resolve({
+ ...data,
+ confirmed: true,
+ close: () => Statamic.$components.destroy(component.id),
+ });
+ } else {
+ resolve(data);
+ Statamic.$components.destroy(component.id);
+ }
+ });
+ component.on('cancel', () => {
+ resolve({
+ confirmed: false,
+ });
+ Statamic.$components.destroy(component.id);
+ });
+ });
+ }
}
export default FieldActions;
diff --git a/routes/cp.php b/routes/cp.php
index 19f8743826..34dac73184 100644
--- a/routes/cp.php
+++ b/routes/cp.php
@@ -42,6 +42,7 @@
use Statamic\Http\Controllers\CP\CpController;
use Statamic\Http\Controllers\CP\DashboardController;
use Statamic\Http\Controllers\CP\DuplicatesController;
+use Statamic\Http\Controllers\CP\FieldActionModalController;
use Statamic\Http\Controllers\CP\Fields\BlueprintController;
use Statamic\Http\Controllers\CP\Fields\FieldsController;
use Statamic\Http\Controllers\CP\Fields\FieldsetController;
@@ -319,6 +320,11 @@
Route::get('dictionaries/{dictionary}', DictionaryFieldtypeController::class)->name('dictionary-fieldtype');
});
+ Route::group(['prefix' => 'field-action-modal'], function () {
+ Route::post('resolve', [FieldActionModalController::class, 'resolve'])->name('resolve');
+ Route::post('process', [FieldActionModalController::class, 'process'])->name('process');
+ });
+
Route::group(['prefix' => 'api', 'as' => 'api.'], function () {
Route::resource('addons', AddonsApiController::class)->only('index');
Route::resource('templates', TemplatesController::class)->only('index');
diff --git a/src/Http/Controllers/CP/FieldActionModalController.php b/src/Http/Controllers/CP/FieldActionModalController.php
new file mode 100644
index 0000000000..4e5cd97188
--- /dev/null
+++ b/src/Http/Controllers/CP/FieldActionModalController.php
@@ -0,0 +1,48 @@
+getFields($request->fields)
+ ->preProcess();
+
+ return [
+ 'fieldset' => $fields->toPublishArray(),
+ 'values' => $fields->values(),
+ 'meta' => $fields->meta(),
+ ];
+ }
+
+ public function process(Request $request)
+ {
+ $fields = $this->getFields($request->fields)
+ ->addValues($request->values);
+
+ $fields->validate();
+
+ $raw = $fields->process()->values();
+
+ $fields->preProcess();
+
+ return [
+ 'values' => $fields->values(),
+ 'meta' => $fields->meta(),
+ 'raw' => $raw,
+ ];
+ }
+
+ protected function getFields($fieldItems)
+ {
+ $fields = collect($fieldItems)->map(function ($field, $handle) {
+ return compact('handle', 'field');
+ });
+
+ return new Fields($fields);
+ }
+}