',
90 | '
{name}
',
91 | 'ID: {id}',
92 | ''
93 | );
94 |
95 | return Ext.create('Ext.form.ComboBox', {
96 | store: store,
97 | name: 'notifyRoles',
98 | displayField: 'name',
99 | valueField: 'name',
100 | loadingText: t('searching'),
101 | fieldLabel: t('workflow_transition_notification_notify_roles'),
102 | minChars: 1,
103 | tpl: resultTpl,
104 | triggerAction: 'all',
105 | multiSelect: true,
106 | value: value,
107 | listeners: {
108 | afterrender: function () {
109 | this.focus(true, 500);
110 | }
111 | }
112 | });
113 | },
114 |
115 | getSettings: function (notification) {
116 | this.settingsForm = new Ext.form.Panel({
117 | bodyStyle: 'padding:20px 5px 20px 5px;',
118 | border: false,
119 | autoScroll: true,
120 | forceLayout: true,
121 | defaults: {
122 | width: '100%',
123 | labelWidth: 200
124 | },
125 | items: [
126 | {
127 | xtype: 'textfield',
128 | name: 'condition',
129 | value: notification.get('condition'),
130 | fieldLabel: t('workflow_transition_notification_condition'),
131 | },
132 | this.getUserCombobox(notification.get('notifyUsers')),
133 | this.getRolesCombobox(notification.get('notifyRoles')),
134 | {
135 | xtype: 'multiselect',
136 | fieldLabel: t('workflow_transition_notification_channel_types'),
137 | name: 'channelType',
138 | store: Ext.data.ArrayStore({
139 | fields: ['type'],
140 | data: [
141 | ['mail'],
142 | ['pimcore_notification'],
143 | ]
144 | }),
145 | value: notification.get('channelType') ? notification.get('channelType') : 'mail',
146 | displayField: 'type',
147 | valueField: 'type',
148 | allowBlank: false
149 | },
150 | {
151 | xtype: 'combobox',
152 | fieldLabel: t('workflow_transition_notification_mail_type'),
153 | name: 'mailType',
154 | store: Ext.data.ArrayStore({
155 | fields: ['type'],
156 | data: [
157 | ['template'],
158 | ['pimcore_document'],
159 | ]
160 | }),
161 | value: notification.get('mailType') ? notification.get('mailType') : 'template',
162 | displayField: 'type',
163 | valueField: 'type',
164 | allowBlank: false
165 | },
166 | {
167 | xtype: 'textfield',
168 | fieldLabel: t('workflow_transition_notification_mail_path'),
169 | name: 'mailPath',
170 | value: notification.get('mailPath'),
171 | }
172 | ],
173 | buttons: [
174 | {
175 | text: t('save'),
176 | handler: function (btn) {
177 | if (this.settingsForm.isValid()) {
178 | var formValues = this.settingsForm.getForm().getFieldValues();
179 |
180 | notification.set(formValues);
181 | notification.commit();
182 |
183 | this.notificationStore.add(notification);
184 |
185 | this.window.close();
186 | }
187 | }.bind(this),
188 | iconCls: 'pimcore_icon_apply'
189 | }
190 | ],
191 | });
192 |
193 | return this.settingsForm;
194 | }
195 | });
196 |
--------------------------------------------------------------------------------
/src/WorkflowGui/Resources/public/js/pimcore/workflow/additional_field.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Workflow Pimcore Plugin
3 | *
4 | * LICENSE
5 | *
6 | * This source file is subject to the GNU General Public License version 3 (GPLv3)
7 | * For the full copyright and license information, please view the LICENSE.md and gpl-3.0.txt
8 | * files that are distributed with this source code.
9 | *
10 | * @copyright Copyright (c) 2018-2019 Youwe (https://www.youwe.nl)
11 | * @license https://github.com/YouweGit/pimcore-workflow-gui/blob/master/LICENSE.md GNU General Public License version 3 (GPLv3)
12 | */
13 |
14 | pimcore.registerNS('pimcore.plugin.workflow.additional_field');
15 | pimcore.plugin.workflow.additional_field = Class.create({
16 | initialize: function (store, field) {
17 | this.store = store;
18 |
19 | this.window = new Ext.window.Window({
20 | title: t('workflow_additional_field') + ': ' + field.getId(),
21 | items: this.getSettings(field),
22 | modal: true,
23 | resizeable: false,
24 | layout: 'fit',
25 | width: 600,
26 | height: 500
27 | });
28 |
29 | this.window.show();
30 | },
31 |
32 | getFieldTypeDialog: function (type, name, settings) {
33 | this.fieldTypeSettingsData = new pimcore.object.classes.data[type](null, settings);
34 | this.fieldTypeSettingsData.datax.name = name;
35 |
36 | var layout = this.fieldTypeSettingsData.getLayout();
37 | layout.setTitle(null);
38 | layout.setBodyStyle('border-top:none;');
39 |
40 | this.fieldTypeSettingsData.specificPanel.setTitle(null);
41 |
42 | this.fieldTypeSettingsData.standardSettingsForm.hide();
43 | this.fieldTypeSettingsData.layoutSettingsForm.hide();
44 |
45 | this.fieldTypeSettings.add(layout);
46 | },
47 |
48 | getSettings: function (field) {
49 | this.fieldTypeSettings = new Ext.Panel({});
50 |
51 | this.settingsForm = new Ext.form.Panel({
52 | defaults: {
53 | width: '100%',
54 | labelWidth: 200
55 | },
56 | items: [
57 | {
58 | xtype: 'textfield',
59 | name: 'name',
60 | value: field.get('name'),
61 | fieldLabel: t('workflow_additional_field_name'),
62 | allowBlank: false,
63 | listeners: {
64 | change: function (input, value) {
65 | if (this.fieldTypeSettingsData) {
66 | this.fieldTypeSettingsData.datax.name = value;
67 | }
68 | }.bind(this)
69 | }
70 | },
71 | {
72 | xtype: 'combobox',
73 | itemId: 'markingStoreType',
74 | fieldLabel: t('workflow_additional_field_type'),
75 | name: 'fieldType',
76 | store: Ext.data.ArrayStore({
77 | fields: ['type'],
78 | data: [
79 | ['input'],
80 | ['textarea'],
81 | ['select'],
82 | ['datetime'],
83 | ['date'],
84 | ['user'],
85 | ['checkbox']
86 | ]
87 | }),
88 | value: field.get("fieldType"),
89 | displayField: 'type',
90 | valueField: 'type',
91 | allowBlank: false,
92 | listeners: {
93 | change: function (cmb, value) {
94 | this.fieldTypeSettings.removeAll();
95 |
96 | if (value) {
97 | this.getFieldTypeDialog(value, cmb.up('form').down('[name="name"]').getValue(), field.get('fieldTypeSettings'));
98 | }
99 | }.bind(this),
100 | afterrender: function (cmb) {
101 | if (cmb.getValue()) {
102 | this.getFieldTypeDialog(cmb.getValue(), cmb.up('form').down('[name="name"]').getValue(), field.get('fieldTypeSettings'));
103 | }
104 | }.bind(this)
105 | }
106 | },
107 | {
108 | xtype: 'textfield',
109 | name: 'title',
110 | value: field.get('title'),
111 | fieldLabel: t('workflow_additional_field_title'),
112 | },
113 | {
114 | xtype: 'checkbox',
115 | name: 'required',
116 | value: field.get('required'),
117 | fieldLabel: t('workflow_additional_field_required'),
118 | },
119 | {
120 | xtype: 'textfield',
121 | name: 'setterFn',
122 | value: field.get('setterFn'),
123 | fieldLabel: t('workflow_additional_field_setter_function'),
124 | },
125 | ]
126 | });
127 |
128 | this.settingsPanel = new Ext.Panel({
129 | border: false,
130 | autoScroll: true,
131 | padding: 10,
132 | defaults: {
133 | width: '100%',
134 | labelWidth: 200
135 | },
136 | items: [
137 | {
138 | xtype: 'fieldset',
139 | title: t('workflow_additional_field_settings'),
140 | defaults: {
141 | width: '100%',
142 | labelWidth: 200
143 | },
144 | items: this.settingsForm
145 | },
146 | {
147 | xtype: 'fieldset',
148 | title: t('workflow_additional_field_type_settings'),
149 | defaults: {
150 | width: '100%',
151 | labelWidth: 200
152 | },
153 | items: this.fieldTypeSettings
154 | },
155 | ],
156 | buttons: [
157 | {
158 | text: t('save'),
159 | handler: function (btn) {
160 | if (this.settingsForm.isValid()) {
161 | if (!this.fieldTypeSettingsData) {
162 | return;
163 | }
164 |
165 | this.fieldTypeSettingsData.applyData();
166 |
167 | var fieldTypeSettings = this.fieldTypeSettingsData.getData();
168 |
169 | console.log(fieldTypeSettings);
170 |
171 | var formValues = this.settingsForm.getForm().getFieldValues();
172 | var storeRecord = this.store.getById(formValues['id']);
173 |
174 | if (storeRecord && storeRecord !== field) {
175 | Ext.Msg.alert(t('workflow_additional_field_name'), t('workflow_additional_field_with_name_already_exists'));
176 | return;
177 | }
178 |
179 | this.store.remove(field);
180 |
181 | field.data = {};
182 | field.set(formValues);
183 | field.set('fieldTypeSettings', fieldTypeSettings);
184 | field.commit();
185 |
186 | this.store.add(field);
187 |
188 | this.window.close();
189 | }
190 | }.bind(this),
191 | iconCls: 'pimcore_icon_apply'
192 | }
193 | ],
194 | });
195 |
196 | return this.settingsPanel;
197 | }
198 | });
199 |
--------------------------------------------------------------------------------
/src/WorkflowGui/Resources/public/js/pimcore/workflow/place.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Workflow Pimcore Plugin
3 | *
4 | * LICENSE
5 | *
6 | * This source file is subject to the GNU General Public License version 3 (GPLv3)
7 | * For the full copyright and license information, please view the LICENSE.md and gpl-3.0.txt
8 | * files that are distributed with this source code.
9 | *
10 | * @copyright Copyright (c) 2018-2019 Youwe (https://www.youwe.nl)
11 | * @license https://github.com/YouweGit/pimcore-workflow-gui/blob/master/LICENSE.md GNU General Public License version 3 (GPLv3)
12 | */
13 |
14 | pimcore.registerNS('pimcore.plugin.workflow.place');
15 | pimcore.plugin.workflow.place = Class.create({
16 | initialize: function (store, place) {
17 | this.store = store;
18 |
19 | this.permissionsStore = new Ext.data.ArrayStore({
20 | model: 'WorkflowGUI.Place.Permission',
21 | });
22 |
23 | this.permissionsStore.setData(place.get('permissions') ? place.get('permissions') : []);
24 |
25 | this.window = new Ext.window.Window({
26 | title: t('workflow_place') + ': ' + place.getId(),
27 | items: this.getSettings(place),
28 | modal: true,
29 | resizeable: false,
30 | layout: 'fit',
31 | width: 600,
32 | height: 500
33 | });
34 |
35 | this.window.show();
36 | },
37 |
38 | getSettings: function (place) {
39 | this.permissionSettings = new Ext.Panel({
40 | defaults: {
41 | width: '100%',
42 | labelWidth: 200
43 | },
44 | items: [
45 | {
46 | xtype: 'grid',
47 | margin: '0 0 15 0',
48 | store: this.permissionsStore,
49 | columns: [
50 | {
51 | xtype: 'gridcolumn',
52 | dataIndex: 'condition',
53 | text: t('workflow_place_permission_condition'),
54 | flex: 1
55 | },
56 | {
57 | menuDisabled: true,
58 | sortable: false,
59 | xtype: 'actioncolumn',
60 | width: 60,
61 | items: [{
62 | iconCls: 'pimcore_icon_edit',
63 | tooltip: t('edit'),
64 | handler: function (grid, rowIndex, colIndex) {
65 | new pimcore.plugin.workflow.place_permission(this.permissionsStore, grid.store.getAt(rowIndex));
66 | }.bind(this)
67 | }, {
68 | iconCls: 'pimcore_icon_delete',
69 | tooltip: t('delete'),
70 | handler: function (grid, rowIndex, colIndex) {
71 | grid.store.removeAt(rowIndex);
72 | }.bind(this)
73 | }]
74 | },
75 | ],
76 | tbar: [
77 | {
78 | text: t('add'),
79 | handler: function (btn) {
80 | var record = new WorkflowGUI.Place.Permission();
81 |
82 | new pimcore.plugin.workflow.place_permission(this.permissionsStore, record);
83 | }.bind(this),
84 | iconCls: 'pimcore_icon_add'
85 | }
86 | ]
87 | }
88 | ]
89 | });
90 |
91 | this.settingsForm = new Ext.form.Panel({
92 | bodyStyle: 'padding:20px 5px 20px 5px;',
93 | border: false,
94 | autoScroll: true,
95 | forceLayout: true,
96 | fieldDefaults: {
97 | labelWidth: 150
98 | },
99 | items: [
100 | {
101 | xtype: 'textfield',
102 | name: 'id',
103 | value: place.getId(),
104 | fieldLabel: t('workflow_place_id'),
105 | allowBlank: false,
106 | regex: /^[a-zA-Z_]+$/
107 | },
108 | {
109 | xtype: 'textfield',
110 | name: 'label',
111 | value: place.get('label'),
112 | fieldLabel: t('workflow_place_label'),
113 | },
114 | {
115 | xtype: 'textfield',
116 | name: 'title',
117 | value: place.get('title'),
118 | fieldLabel: t('workflow_place_title'),
119 | },
120 | {
121 | xtype: 'colorfield',
122 | name: 'color',
123 | value: (place.get('color')) ? place.get('color') : 'CCCCCC',
124 | fieldLabel: t('workflow_place_color'),
125 | },
126 | {
127 | xtype: 'checkbox',
128 | name: 'colorInverted',
129 | value: place.get('colorInverted'),
130 | fieldLabel: t('workflow_place_color_inverted'),
131 | },
132 | {
133 | xtype: 'checkbox',
134 | name: 'visibleInHeader',
135 | value: place.get('visibleInHeader'),
136 | fieldLabel: t('workflow_place_visible_in_header'),
137 | },
138 | this.permissionSettings
139 | ]
140 | });
141 |
142 |
143 | this.settingsPanel = new Ext.Panel({
144 | border: false,
145 | autoScroll: true,
146 | padding: 10,
147 | defaults: {
148 | width: '100%',
149 | labelWidth: 200
150 | },
151 | items: [
152 | {
153 | xtype: 'fieldset',
154 | title: t('workflow_place_settings'),
155 | defaults: {
156 | width: '100%',
157 | labelWidth: 200
158 | },
159 | items: this.settingsForm
160 | },
161 | {
162 | xtype: 'fieldset',
163 | title: t('workflow_place_permissions'),
164 | defaults: {
165 | width: '100%',
166 | labelWidth: 200
167 | },
168 | items: this.permissionSettings
169 | }
170 | ],
171 | buttons: [
172 | {
173 | text: t('save'),
174 | handler: function (btn) {
175 | if (this.settingsForm.isValid()) {
176 | var formValues = this.settingsForm.getForm().getFieldValues();
177 | var storeRecord = this.store.getById(formValues['id']);
178 | var permissions = this.permissionsStore.getRange();
179 |
180 | if (storeRecord && storeRecord !== place) {
181 | Ext.Msg.alert(t('workflow_place_id'), t('workflow_place_with_id_already_exists'));
182 | return;
183 | }
184 |
185 | permissions = permissions.map(function (record) {
186 | var data = record.data;
187 |
188 | delete data['id'];
189 |
190 | return data;
191 | });
192 |
193 | if (formValues.color) {
194 | formValues.color = '#' + formValues.color;
195 | }
196 |
197 | place.set('permissions', permissions);
198 | place.set(formValues);
199 | place.commit();
200 |
201 | this.window.close();
202 | }
203 | }.bind(this),
204 | iconCls: 'pimcore_icon_apply'
205 | }
206 | ],
207 | });
208 |
209 | return this.settingsPanel;
210 | }
211 | });
212 |
--------------------------------------------------------------------------------
/config/pimcore/customviews.example.php:
--------------------------------------------------------------------------------
1 | [
5 | [
6 | 'treetype' => 'object', // element type is "object"
7 | 'name' => 'Articles', // display name
8 | 'icon' => '/bundles/pimcoreadmin/img/flat-color-icons/reading.svg', // tree icon
9 | 'id' => 1, // unique (!!!) custom view ID
10 | 'rootfolder' => '/blog', // root node
11 | 'showroot' => false, // show root node or just children?
12 | 'classes' => '', // allowed classes to add; use class ids; comma-separated
13 | 'position' => 'right', // left or right accordion
14 | 'sort' => '1', // sort priority. lower values are shown first (prio for standard trees is -3 docs,-2 assets,-1 objects)
15 | 'expanded' => true, // tree is expanded by default (there can be only one expanded tree on each side)
16 | 'having' => "o_type = \"folder\" || o5.title NOT LIKE '%magnis%'", // SQL having clause
17 | 'joins' => [ // Joins in Zend_DB_Select-like syntax
18 | [
19 | 'type' => 'left',
20 | 'name' => ['o5' => 'object_localized_5_en'],
21 | 'condition' => 'objects.o_id = o5.oo_id',
22 | 'columns' => ['o5' => 'title']
23 | ]
24 | ],
25 | 'where' => '', // SQL where condition
26 | 'treeContextMenu' => [
27 | 'object' => [
28 | 'items' => [
29 | 'add' => 0, // hide "Add Object" , "Add Variant"
30 | 'addFolder' => 0, // hide "Add Folder"
31 | 'importCsv' => 0, // hide "Import From CSV"
32 | 'paste' => 0, // hide "Paste"
33 | 'copy' => 0, // hide "Copy"
34 | 'cut' => 0, // hide "Cut"
35 | 'publish' => 0, // hide "Publish"
36 | 'unpublish' => 0, // hide "Unpublish"
37 | 'delete' => 1, // show "Delete" (redundant as this is the default)
38 | 'rename' => 0, // hide "Rename"
39 | 'searchAndMove' => 0, // hide "Search And Move"
40 | 'lock' => 0, // hide "Lock"
41 | 'unlock' => 0, // hide "Unlock"
42 | 'lockAndPropagate' => 0, // hide "Lock and Propagate"
43 | 'unlockAndPropagete' => 0, // hide "Unlock and Propagate"
44 | 'reload' => 0, // hide reload
45 | 'changeChildrenSortBy' => 0 // hide "Sort Children By"
46 | ]
47 | ]
48 | ]
49 | ],
50 | [
51 | 'treetype' => 'document', // document view
52 | 'name' => 'Basic Examples',
53 | 'icon' => '/bundles/pimcoreadmin/img/flat-color-icons/text.svg',
54 | 'id' => 2, // again, unique ID
55 | 'rootfolder' => '/en/basic-examples',
56 | 'showroot' => true,
57 | 'position' => 'right', // show it in the right accordion
58 | 'sort' => '-10',
59 | 'expanded' => true, // expand the tree panel
60 | 'treeContextMenu' => [
61 | 'document' => [
62 | 'items' => [
63 | 'add' => 0, // hide all the "Add *" stuff
64 | 'addSnippet' => 0, // hide "Add Snippet"
65 | 'addLink' => 0, // hide "Add Link"
66 | 'addEmail' => 0, // hide "Add Email"
67 | 'addNewsletter' => 0, // hide "Add Newsletter"
68 | 'addHardlink' => 0, // hide "Add Hardlink"
69 | 'addFolder' => 0, // hide "Add Folder"
70 | 'paste' => 0, // hide all the "Paste" options
71 | 'pasteCut' => 0, // hide "Paste Cut element"
72 | 'copy' => 0, // hide "Copy"
73 | 'cut' => 0, // hide "Cut"
74 | 'rename' => 0, // hide "Rename"
75 | 'unpublish' => 0, // hide "Unpublish"
76 | 'publish' => 0, // hide "Publish"
77 | 'delete' => 0, // hide "Delete"
78 | 'open' => 0, // hide "Open"
79 | 'convert' => 0, // hide "Convert"
80 | 'searchAndMove' => 0, // hide "Search And Move"
81 | 'useAsSite' => 0, // hide "Use As Site"
82 | 'editSite' => 0, // hide "Edit Site"
83 | 'removeSite' => 0, // hide "Remove Site"
84 | 'lock' => 0, // hide "Lock"
85 | 'unlock' => 0, // hide "Unlock"
86 | 'lockAndPropagate' => 0, // hide "UnlockAndPropagate"
87 | 'unlockAndPropagate' => 0, // hide "Lock And Propagate"
88 | 'reload' => 1 // show "Reload" (redundant, visible by default anyway)
89 | ]
90 | ]
91 | ]
92 | ],
93 | [
94 | 'treetype' => 'asset', // asset view
95 | 'name' => 'Panama',
96 | 'icon' => '/bundles/pimcoreadmin/img/flat-color-icons/stack_of_photos.svg',
97 | 'id' => 3,
98 | 'rootfolder' => '/examples/panama',
99 | 'showroot' => true,
100 | 'position' => 'right',
101 | 'sort' => '-15', // show in on the top
102 | 'expanded' => false,
103 | 'treeContextMenu' => [
104 | 'asset' => [
105 | 'items' => [
106 | 'add' => [
107 | // "hidden" => 1, // hide "Add asset" menu (including subentries)
108 | 'items' => [
109 | 'upload' => 0, // hide "Upload"
110 | // "uploadCompatibility" => 0, // hide "Upload Compatibility Mode"
111 | // "uploadZip" => 0, // hide "Upload ZIP Archive"
112 | // "importFromServer" => 0, // don't show "Import from Server"
113 | 'uploadFromUrl' => 0 // hide "Upload From URL"
114 | ]
115 | ],
116 | 'addFolder' => 1, // show (!) "Add Folder" (shown by default anyway)
117 | 'rename' => 0, // hide "Rename"
118 | // "copy" => 0, // hide "Copy"
119 | // "cut" => 0, // hide "Cut"
120 | 'paste' => 0, // hide "Paste"
121 | 'pasteCut' => 0, // hide "Paste cut element"
122 | 'delete' => 0, // hide "Delete"
123 | 'searchAndMove' => 0, // hide "Search And Move"
124 | 'lock' => 0, // hide "Lock"
125 | 'unlock' => 0, // hide "Unlock"
126 | 'lockAndPropagate' => 0, // hide "Lock and propagate"
127 | 'unlockAndPropagate' => 0, // hide "Unlock and propagate"
128 | 'reload' => [ // show reload (shown by default anyway)
129 | 'hidden' => false
130 | ]
131 | ]
132 | ]
133 | ]
134 | ]
135 | ]
136 | ];
137 |
--------------------------------------------------------------------------------
/src/WorkflowGui/Resources/public/js/pimcore/workflow/global_action.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Workflow Pimcore Plugin
3 | *
4 | * LICENSE
5 | *
6 | * This source file is subject to the GNU General Public License version 3 (GPLv3)
7 | * For the full copyright and license information, please view the LICENSE.md and gpl-3.0.txt
8 | * files that are distributed with this source code.
9 | *
10 | * @copyright Copyright (c) 2018-2019 Youwe (https://www.youwe.nl)
11 | * @license https://github.com/YouweGit/pimcore-workflow-gui/blob/master/LICENSE.md GNU General Public License version 3 (GPLv3)
12 | */
13 |
14 | pimcore.registerNS('pimcore.plugin.workflow.global_action');
15 | pimcore.plugin.workflow.global_action = Class.create({
16 | initialize: function (store, placesStore, globalAction) {
17 | this.store = store;
18 | this.placesStore = placesStore;
19 |
20 | this.additionalFieldsStore = new Ext.data.ArrayStore({
21 | model: 'WorkflowGUI.AdditionalField',
22 | });
23 |
24 | this.additionalFieldsStore.setData(globalAction.get('additionalFields'));
25 |
26 | this.window = new Ext.window.Window({
27 | title: t('workflow_global_action') + ': ' + globalAction.getId(),
28 | items: this.getSettings(globalAction),
29 | modal: true,
30 | resizeable: false,
31 | layout: 'fit',
32 | width: 600,
33 | height: 500
34 | });
35 |
36 | this.window.show();
37 | },
38 |
39 | getSettings: function (globalAction) {
40 | var notes = globalAction.get('notes') ? globalAction.get('notes') : {};
41 |
42 | this.additionalFieldsSettings = new Ext.Panel({
43 | defaults: {
44 | width: '100%',
45 | labelWidth: 200
46 | },
47 | items: [
48 | {
49 | xtype: 'grid',
50 | margin: '0 0 15 0',
51 | title: t('workflow_additional_fields'),
52 | store: this.additionalFieldsStore,
53 | columns: [
54 | {
55 | xtype: 'gridcolumn',
56 | dataIndex: 'name',
57 | text: t('workflow_additional_field_name'),
58 | flex: 1
59 | },
60 | {
61 | menuDisabled: true,
62 | sortable: false,
63 | xtype: 'actioncolumn',
64 | width: 60,
65 | items: [{
66 | iconCls: 'pimcore_icon_edit',
67 | tooltip: t('edit'),
68 | handler: function (grid, rowIndex, colIndex) {
69 | new pimcore.plugin.workflow.additional_field(this.additionalFieldsStore, grid.store.getAt(rowIndex));
70 | }.bind(this)
71 | }, {
72 | iconCls: 'pimcore_icon_delete',
73 | tooltip: t('delete'),
74 | handler: function (grid, rowIndex, colIndex) {
75 | grid.store.removeAt(rowIndex);
76 | }.bind(this)
77 | }]
78 | },
79 | ],
80 | tbar: [
81 | {
82 | text: t('add'),
83 | handler: function (btn) {
84 | var record = new WorkflowGUI.AdditionalField();
85 |
86 | new pimcore.plugin.workflow.additional_field(this.additionalFieldsStore, record);
87 | }.bind(this),
88 | iconCls: 'pimcore_icon_add'
89 | }
90 | ]
91 | }
92 | ]
93 | });
94 |
95 | this.notesForm = new Ext.form.Panel({
96 | defaults: {
97 | width: '100%',
98 | labelWidth: 200
99 | },
100 | items: [
101 | {
102 | xtype: 'checkbox',
103 | name: 'commentEnabled',
104 | value: notes.hasOwnProperty('commentEnabled') ? notes.commentEnabled : false,
105 | fieldLabel: t('workflow_global_action_note_comment_enabled'),
106 | allowBlank: false,
107 | listeners: {
108 | change: function (checkbox, newValue) {
109 | if (newValue) {
110 | this.notesForm.down('#innerNotes').show();
111 | this.notesForm.down('#innerNotes').enable();
112 | } else {
113 | this.notesForm.down('#innerNotes').hide();
114 | this.notesForm.down('#innerNotes').disable();
115 | }
116 | }.bind(this)
117 | }
118 | },
119 | {
120 | xtype: 'container',
121 | itemId: 'innerNotes',
122 | defaults: {
123 | width: '100%',
124 | labelWidth: 200
125 | },
126 | hidden: !(notes.hasOwnProperty('commentEnabled') ? notes.commentEnabled : false),
127 | disabled: !(notes.hasOwnProperty('commentEnabled') ? notes.commentEnabled : false),
128 | items: [
129 | {
130 | xtype: 'checkbox',
131 | name: 'commentRequired',
132 | value: notes.hasOwnProperty('commentRequired') ? notes.commentRequired : false,
133 | fieldLabel: t('workflow_global_action_note_comment_required'),
134 | allowBlank: false,
135 | },
136 | {
137 | xtype: 'textfield',
138 | name: 'commentSetterFn',
139 | value: notes.hasOwnProperty('commentSetterFn') ? notes.commentSetterFn : '',
140 | fieldLabel: t('workflow_global_action_note_comment_setter')
141 | },
142 | {
143 | xtype: 'textfield',
144 | name: 'commentGetterFn',
145 | value: notes.hasOwnProperty('commentGetterFn') ? notes.commentGetterFn : '',
146 | fieldLabel: t('workflow_global_action_note_comment_getter')
147 | },
148 | {
149 | xtype: 'textfield',
150 | name: 'type',
151 | value: notes.hasOwnProperty('type') ? notes.type : '',
152 | fieldLabel: t('workflow_global_action_note_type')
153 | },
154 | {
155 | xtype: 'textfield',
156 | name: 'title',
157 | value: notes.hasOwnProperty('title') ? notes.title : '',
158 | fieldLabel: t('workflow_global_action_note_title')
159 | },
160 | this.additionalFieldsSettings
161 | ]
162 | }
163 | ]
164 | });
165 |
166 | this.settingsForm = new Ext.form.Panel({
167 | defaults: {
168 | width: '100%',
169 | labelWidth: 200
170 | },
171 | items: [
172 | {
173 | xtype: 'textfield',
174 | name: 'id',
175 | value: globalAction.getId(),
176 | fieldLabel: t('workflow_global_action_id'),
177 | allowBlank: false,
178 | regex: /^[a-zA-Z_]+$/
179 | },
180 | {
181 | xtype: 'textfield',
182 | name: 'iconClass',
183 | value: globalAction.get('iconClass'),
184 | fieldLabel: t('workflow_global_action_icon_class'),
185 | },
186 | {
187 | xtype: 'textfield',
188 | name: 'guard',
189 | value: globalAction.get('guard'),
190 | fieldLabel: t('workflow_global_action_guard'),
191 | },
192 | {
193 | xtype: 'combobox',
194 | name: 'to',
195 | fieldLabel: t('workflow_global_action_to'),
196 | store: this.placesStore,
197 | value: globalAction.get('to'),
198 | displayField: 'label',
199 | valueField: 'id',
200 | multiSelect: true,
201 | queryMode: 'local',
202 | },
203 | ]
204 | });
205 |
206 | this.settingsPanel = new Ext.Panel({
207 | border: false,
208 | autoScroll: true,
209 | padding: 10,
210 | defaults: {
211 | width: '100%',
212 | labelWidth: 200
213 | },
214 | items: [
215 | {
216 | xtype: 'fieldset',
217 | title: t('workflow_global_action_settings'),
218 | defaults: {
219 | width: '100%',
220 | labelWidth: 200
221 | },
222 | items: this.settingsForm
223 | },
224 | {
225 | xtype: 'fieldset',
226 | title: t('workflow_global_action_notes'),
227 | defaults: {
228 | width: '100%',
229 | labelWidth: 200
230 | },
231 | items: this.notesForm
232 | },
233 | ],
234 | buttons: [
235 | {
236 | text: t('save'),
237 | handler: function (btn) {
238 | if (this.settingsForm.isValid()) {
239 | var formValues = this.settingsForm.getForm().getFieldValues();
240 | var notesValues = this.notesForm.getForm().getFieldValues();
241 | var storeRecord = this.store.getById(formValues['id']);
242 | var additionalFields = this.additionalFieldsStore.getRange();
243 |
244 | if (storeRecord && storeRecord !== globalAction) {
245 | Ext.Msg.alert(t('workflow_global_action_id'), t('workflow_global_action_with_id_already_exists'));
246 | return;
247 | }
248 |
249 | additionalFields = additionalFields.map(function(record) {
250 | var data = record.data;
251 |
252 | delete data['id'];
253 |
254 | return data;
255 | });
256 |
257 | this.store.remove(globalAction);
258 |
259 | if (!formValues['guard']) {
260 | delete formValues['guard'];
261 | }
262 |
263 | notesValues['additionalFields'] = additionalFields;
264 |
265 | globalAction.data = {};
266 | globalAction.set(formValues);
267 | globalAction.set('notes', notesValues);
268 | globalAction.commit();
269 |
270 | this.store.add(globalAction);
271 |
272 | this.window.close();
273 | }
274 | }.bind(this),
275 | iconCls: 'pimcore_icon_apply'
276 | }
277 | ],
278 | });
279 |
280 | return this.settingsPanel;
281 | }
282 | });
283 |
--------------------------------------------------------------------------------
/src/WorkflowGui/Controller/WorkflowController.php:
--------------------------------------------------------------------------------
1 | isGrantedOr403();
52 |
53 | $workflows = $this->repository->findAll();
54 |
55 | $results = [];
56 | foreach ($workflows as $id => $workflow) {
57 | $results[] = [
58 | 'id' => $id,
59 | 'label' => $workflow['label'],
60 | ];
61 | }
62 |
63 | return $this->json($results);
64 | }
65 |
66 | public function getAction(Request $request): JsonResponse
67 | {
68 | $this->isGrantedOr403();
69 |
70 | $id = $request->get('id');
71 | $workflow = $this->repository->find($id);
72 |
73 | if (!$workflow) {
74 | throw new NotFoundHttpException();
75 | }
76 |
77 | return $this->json(['success' => true, 'data' => $workflow]);
78 | }
79 |
80 | public function cloneAction(Request $request): JsonResponse
81 | {
82 | $this->isGrantedOr403();
83 |
84 | $id = $request->get('id');
85 | $name = $request->get('name');
86 | $workflow = $this->repository->find($id);
87 | $workflowByName = $this->repository->find($name);
88 |
89 | if (!$workflow) {
90 | throw new NotFoundHttpException();
91 | }
92 |
93 | if ($workflowByName) {
94 | return $this->json([
95 | 'success' => false,
96 | 'message' => $this->translator->trans('workflow_gui_workflow_with_name_already_exists'),
97 | ]);
98 | }
99 |
100 | $this->repository->updateConfig(function (array $workflows) use ($id, $name): array {
101 | $workflows[$name] = $workflows[$id];
102 | return $workflows;
103 | });
104 | $this->cacheClearer->clear($this->kernel->getEnvironment());
105 |
106 | return $this->json(['success' => true, 'id' => $name]);
107 | }
108 |
109 | public function saveAction(Request $request): JsonResponse
110 | {
111 | $this->isGrantedOr403();
112 |
113 | $id = $request->get('id');
114 | $newId = $request->get('newId');
115 | $newConfiguration = $this->decodeJson($request->get('data'));
116 |
117 | $newConfiguration = $this->sanitizeConfiguration($newConfiguration);
118 | $testConfig = $newConfiguration;
119 |
120 | //Test Configuration
121 | $configuration = new Configuration();
122 | $processor = new Processor();
123 |
124 | try {
125 | $processor->processConfiguration($configuration, [
126 | 'pimcore' =>
127 | [
128 | 'workflows' => [
129 | $newId => $testConfig,
130 | ],
131 | ],
132 | ]
133 | );
134 | } catch (\Throwable $ex) {
135 | return $this->json(['success' => false, 'message' => $ex->getMessage()]);
136 | }
137 |
138 | $this->repository->updateConfig(function (array $workflows) use ($id, $newId, $newConfiguration): array {
139 | if (isset($workflows[$id])) {
140 | unset($workflows[$id]);
141 | }
142 |
143 | $workflows[$newId] = $newConfiguration;
144 | return $workflows;
145 | });
146 | $this->cacheClearer->clear($this->kernel->getEnvironment());
147 |
148 | $workflow = $this->repository->find($id);
149 |
150 | return $this->json(['success' => true, 'data' => $workflow]);
151 | }
152 |
153 | public function deleteAction(Request $request): JsonResponse
154 | {
155 | $this->isGrantedOr403();
156 |
157 | $id = $request->get('id');
158 |
159 | $this->repository->updateConfig(function (array $workflows) use ($id): array {
160 | if (isset($workflows[$id])) {
161 | unset($workflows[$id]);
162 | }
163 | return $workflows;
164 | });
165 | $this->cacheClearer->clear($this->kernel->getEnvironment());
166 |
167 | return $this->json(['success' => true]);
168 | }
169 |
170 | public function searchRolesAction(Request $request): JsonResponse
171 | {
172 | $this->isGrantedOr403();
173 |
174 | $q = '%'.$request->get('query').'%';
175 |
176 | $list = new User\Role\Listing();
177 | $list->setCondition('name LIKE ?', [$q]);
178 | $list->setOrder('ASC');
179 | $list->setOrderKey('name');
180 | $list->load();
181 |
182 | $roles = [];
183 | if (is_array($list->getRoles())) {
184 |
185 | /** @var User\Role $role */
186 | foreach ($list->getRoles() as $role) {
187 | if ($role instanceof User\Role && $role->getId()) {
188 | $roles[] = [
189 | 'id' => $role->getId(),
190 | 'name' => $role->getName(),
191 | ];
192 | }
193 | }
194 | }
195 |
196 | return $this->jsonResponse([
197 | 'success' => true,
198 | 'roles' => $roles,
199 | ]);
200 | }
201 |
202 | protected function isGrantedOr403(): void
203 | {
204 | $user = $this->getPimcoreUser();
205 |
206 | if (null === $user) {
207 | throw new AccessDeniedException();
208 | }
209 |
210 | if ($user->isAllowed('workflow_gui')) {
211 | return;
212 | }
213 |
214 | throw new AccessDeniedException();
215 | }
216 |
217 | protected function sanitizeConfiguration($configuration): array
218 | {
219 | if (isset($configuration['places'])) {
220 | foreach ($configuration['places'] as $placeKey => &$placeConfig) {
221 | if (isset($placeConfig['color'])) {
222 | if (substr($placeConfig['color'], 0, 1) !== '#') {
223 | $placeConfig['color'] = '#'.$placeConfig['color'];
224 | }
225 | }
226 | foreach ($placeConfig as $placeConfigKey => $value) {
227 | if (!$value) {
228 | unset($placeConfig[$placeConfigKey]);
229 | }
230 | }
231 |
232 | if (isset($placeConfig['permissions'])) {
233 | foreach ($placeConfig['permissions'] as $permissionIndex => &$permissionConfig) {
234 | foreach ($permissionConfig as $permissionKey => $permissionValue) {
235 | if ($permissionValue === null || ($permissionKey === 'condition' && !$permissionValue)) {
236 | unset($permissionConfig[$permissionKey]);
237 | }
238 | }
239 |
240 | if (count($permissionConfig) === 0) {
241 | unset ($placeConfig['permissions'][$permissionIndex]);
242 | }
243 | }
244 |
245 | if (count($placeConfig['permissions']) === 0) {
246 | unset($placeConfig['permissions']);
247 | }
248 | }
249 | }
250 | }
251 |
252 | if (isset($configuration['transitions'])) {
253 | foreach ($configuration['transitions'] as $transitionKey => &$transitionConfig) {
254 | if (isset($transitionConfig['options'])) {
255 | foreach ($transitionConfig['options'] as $transitionOptionConfigKey => $value) {
256 | if (!$value) {
257 | unset($transitionConfig['options'][$transitionOptionConfigKey]);
258 | }
259 | }
260 |
261 | if (isset($transitionConfig['options']['notes']['additionalFields'])) {
262 | foreach ($transitionConfig['options']['notes']['additionalFields'] as &$additionalField) {
263 | if (!$additionalField['setterFn']) {
264 | unset ($additionalField['setterFn']);
265 | }
266 |
267 | if (!$additionalField['title']) {
268 | unset ($additionalField['title']);
269 | }
270 |
271 | if (!$additionalField['required']) {
272 | unset ($additionalField['required']);
273 | }
274 | }
275 | }
276 | }
277 | }
278 | }
279 |
280 | return $configuration;
281 | }
282 |
283 | public function visualizeAction(Request $request): Response
284 | {
285 | $this->isGrantedOr403();
286 |
287 | try {
288 | return $this->render(
289 | '@WorkflowGui/Workflow/visualize.html.twig',
290 | [
291 | 'image' => $this->getVisualization($request->get('workflow'), 'svg'),
292 | ]
293 | );
294 | } catch (\Throwable $e) {
295 | return new Response($e->getMessage());
296 | }
297 | }
298 |
299 | public function visualizeImageAction(Request $request): Response
300 | {
301 | $this->isGrantedOr403();
302 |
303 | try {
304 | $image = $this->getVisualization($request->get('workflow'), 'png');
305 |
306 | $response = new Response();
307 |
308 | // Set headers
309 | $response->headers->set('Cache-Control', 'private');
310 | $response->headers->set('Content-type', 'image/png');
311 | $response->headers->set('Content-length', strlen($image));
312 |
313 | // Send headers before outputting anything
314 | $response->sendHeaders();
315 |
316 | $response->setContent($image);
317 |
318 | return $response;
319 | } catch (\Throwable $e) {
320 | return new Response($e->getMessage());
321 | }
322 | }
323 |
324 | private function getVisualization($workflow, $format): string
325 | {
326 | $php = Console::getExecutable('php');
327 | $dot = Console::getExecutable('dot');
328 |
329 | if (!$php) {
330 | throw new \InvalidArgumentException($this->translator->trans('workflow_cmd_not_found', ['php'], 'admin'));
331 | }
332 |
333 | if (!$dot) {
334 | throw new \InvalidArgumentException($this->translator->trans('workflow_cmd_not_found', ['dot'], 'admin'));
335 | }
336 |
337 | $workflowRepository = $this->repository->find($workflow);
338 |
339 | if ($workflowRepository === null) {
340 | throw new \InvalidArgumentException($this->translator->trans('workflow_gui_not_found', [], 'admin'));
341 | }
342 |
343 | if (!$workflowRepository['enabled'] ?? false) {
344 | throw new \InvalidArgumentException($this->translator->trans('workflow_gui_enable_message', [], 'admin'));
345 | }
346 |
347 | $cmd = $php.' '.PIMCORE_PROJECT_ROOT.'/bin/console --env="${:arg_environment}" pimcore:workflow:dump "${:arg_workflow}" | '.$dot.' -T"${:arg_format}"';
348 |
349 | $process = Process::fromShellCommandline($cmd);
350 | $process->run(null, [
351 | 'arg_environment' => $this->kernel->getEnvironment(),
352 | 'arg_workflow' => $workflow,
353 | 'arg_format' => $format,
354 | ]);
355 |
356 | return $process->getOutput();
357 | }
358 | }
359 |
--------------------------------------------------------------------------------
/src/WorkflowGui/Resources/public/js/pimcore/workflow/transition.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Workflow Pimcore Plugin
3 | *
4 | * LICENSE
5 | *
6 | * This source file is subject to the GNU General Public License version 3 (GPLv3)
7 | * For the full copyright and license information, please view the LICENSE.md and gpl-3.0.txt
8 | * files that are distributed with this source code.
9 | *
10 | * @copyright Copyright (c) 2018-2019 Youwe (https://www.youwe.nl)
11 | * @license https://github.com/YouweGit/pimcore-workflow-gui/blob/master/LICENSE.md GNU General Public License version 3 (GPLv3)
12 | */
13 |
14 | pimcore.registerNS('pimcore.plugin.workflow.transition');
15 | pimcore.plugin.workflow.transition = Class.create({
16 | initialize: function (store, placesStore, transition) {
17 | var options = transition.get('options') ? transition.get('options') : {};
18 |
19 | this.store = store;
20 | this.placesStore = placesStore;
21 |
22 | this.notificationStore = new Ext.data.ArrayStore({
23 | model: 'WorkflowGUI.Transition.Notification',
24 | });
25 |
26 | this.notificationStore.setData(options.hasOwnProperty('notificationSettings') ? options.notificationSettings : []);
27 |
28 | this.additionalFieldsStore = new Ext.data.ArrayStore({
29 | model: 'WorkflowGUI.AdditionalField',
30 | });
31 |
32 | this.additionalFieldsStore.setData(options.hasOwnProperty('notes') && options.notes.hasOwnProperty('additionalFields') ? options.notes.additionalFields : []);
33 |
34 | this.window = new Ext.window.Window({
35 | title: t('workflow_transition') + ': ' + transition.getId(),
36 | items: this.getSettings(transition),
37 | modal: true,
38 | resizeable: false,
39 | layout: 'fit',
40 | width: 600,
41 | height: 500
42 | });
43 |
44 | this.window.show();
45 | },
46 |
47 | getSettings: function (transition) {
48 | var options = transition.get('options') ? transition.get('options') : {};
49 | var optionNotes = options.hasOwnProperty('notes') ? options.notes : {};
50 |
51 | this.optionsForm = new Ext.form.Panel({
52 | defaults: {
53 | width: '100%',
54 | labelWidth: 200
55 | },
56 | items: [
57 | {
58 | xtype: 'textfield',
59 | name: 'label',
60 | value: options.hasOwnProperty('label') ? options.label : '',
61 | fieldLabel: t('workflow_transition_label'),
62 | allowBlank: false,
63 | },
64 | {
65 | xtype: 'textfield',
66 | name: 'iconClass',
67 | value: options.hasOwnProperty('iconClass') ? options.iconClass : '',
68 | fieldLabel: t('workflow_transition_icon_class'),
69 | },
70 | {
71 | xtype: 'combobox',
72 | fieldLabel: t('workflow_transition_change_publish_state'),
73 | name: 'changePublishedState',
74 | store: Ext.data.ArrayStore({
75 | fields: ['type'],
76 | data: [
77 | ['no_change'],
78 | ['save_version'],
79 | ['force_unpublished'],
80 | ['force_published'],
81 | ]
82 | }),
83 | value: options.hasOwnProperty('changePublishedState') ? options.changePublishedState : 'no_change',
84 | displayField: 'type',
85 | valueField: 'type',
86 | allowBlank: false
87 | },
88 | ]
89 | });
90 |
91 |
92 | this.additionalFieldsSettings = new Ext.Panel({
93 | defaults: {
94 | width: '100%',
95 | labelWidth: 200
96 | },
97 | items: [
98 | {
99 | xtype: 'grid',
100 | margin: '0 0 15 0',
101 | title: t('workflow_additional_fields'),
102 | store: this.additionalFieldsStore,
103 | columns: [
104 | {
105 | xtype: 'gridcolumn',
106 | dataIndex: 'name',
107 | text: t('workflow_additional_field_name'),
108 | flex: 1,
109 | regex: /[^A-Za-z0-9_]+/,
110 | },
111 | {
112 | menuDisabled: true,
113 | sortable: false,
114 | xtype: 'actioncolumn',
115 | width: 60,
116 | items: [{
117 | iconCls: 'pimcore_icon_edit',
118 | tooltip: t('edit'),
119 | handler: function (grid, rowIndex, colIndex) {
120 | new pimcore.plugin.workflow.additional_field(this.additionalFieldsStore, grid.store.getAt(rowIndex));
121 | }.bind(this)
122 | }, {
123 | iconCls: 'pimcore_icon_delete',
124 | tooltip: t('delete'),
125 | handler: function (grid, rowIndex, colIndex) {
126 | grid.store.removeAt(rowIndex);
127 | }.bind(this)
128 | }]
129 | },
130 | ],
131 | tbar: [
132 | {
133 | text: t('add'),
134 | handler: function (btn) {
135 | var record = new WorkflowGUI.AdditionalField();
136 |
137 | new pimcore.plugin.workflow.additional_field(this.additionalFieldsStore, record);
138 | }.bind(this),
139 | iconCls: 'pimcore_icon_add'
140 | }
141 | ]
142 | }
143 | ]
144 | });
145 |
146 | this.notesForm = new Ext.form.Panel({
147 | defaults: {
148 | width: '100%',
149 | labelWidth: 200
150 | },
151 | items: [
152 | {
153 | xtype: 'checkbox',
154 | name: 'commentEnabled',
155 | value: optionNotes.hasOwnProperty('commentEnabled') ? optionNotes.commentEnabled : false,
156 | fieldLabel: t('workflow_transition_note_comment_enabled'),
157 | allowBlank: false,
158 | listeners: {
159 | change: function (checkbox, newValue) {
160 | if (newValue) {
161 | this.notesForm.down('#innerNotes').show();
162 | this.notesForm.down('#innerNotes').enable();
163 | } else {
164 | this.notesForm.down('#innerNotes').hide();
165 | this.notesForm.down('#innerNotes').disable();
166 | }
167 | }.bind(this)
168 | }
169 | },
170 | {
171 | xtype: 'container',
172 | itemId: 'innerNotes',
173 | defaults: {
174 | width: '100%',
175 | labelWidth: 200
176 | },
177 | hidden: !(optionNotes.hasOwnProperty('commentEnabled') ? optionNotes.commentEnabled : false),
178 | disabled: !(optionNotes.hasOwnProperty('commentEnabled') ? optionNotes.commentEnabled : false),
179 | items: [
180 | {
181 | xtype: 'checkbox',
182 | name: 'commentRequired',
183 | value: optionNotes.hasOwnProperty('commentRequired') ? optionNotes.commentRequired : false,
184 | fieldLabel: t('workflow_transition_note_comment_required'),
185 | allowBlank: false,
186 | },
187 | {
188 | xtype: 'textfield',
189 | name: 'commentSetterFn',
190 | value: optionNotes.hasOwnProperty('commentSetterFn') ? optionNotes.commentSetterFn : '',
191 | fieldLabel: t('workflow_transition_note_comment_setter')
192 | },
193 | {
194 | xtype: 'textfield',
195 | name: 'commentGetterFn',
196 | value: optionNotes.hasOwnProperty('commentGetterFn') ? optionNotes.commentGetterFn : '',
197 | fieldLabel: t('workflow_transition_note_comment_getter')
198 | },
199 | {
200 | xtype: 'textfield',
201 | name: 'type',
202 | value: optionNotes.hasOwnProperty('type') ? optionNotes.type : '',
203 | fieldLabel: t('workflow_transition_note_type')
204 | },
205 | {
206 | xtype: 'textfield',
207 | name: 'title',
208 | value: optionNotes.hasOwnProperty('title') ? optionNotes.title : '',
209 | fieldLabel: t('workflow_transition_note_title')
210 | },
211 | this.additionalFieldsSettings
212 | ]
213 | }
214 | ]
215 | });
216 |
217 | this.settingsForm = new Ext.form.Panel({
218 | defaults: {
219 | width: '100%',
220 | labelWidth: 200
221 | },
222 | items: [
223 | {
224 | xtype: 'textfield',
225 | name: 'id',
226 | value: transition.getId(),
227 | fieldLabel: t('workflow_transition_id'),
228 | allowBlank: false,
229 | regex: /^[a-zA-Z_]+$/
230 | },
231 |
232 | {
233 | xtype: 'textfield',
234 | name: 'guard',
235 | value: transition.get('guard'),
236 | fieldLabel: t('workflow_transition_guard'),
237 | },
238 | {
239 | xtype: 'combobox',
240 | name: 'from',
241 | fieldLabel: t('workflow_transition_from'),
242 | store: this.placesStore,
243 | value: transition.get('from'),
244 | displayField: 'label',
245 | valueField: 'id',
246 | multiSelect: true,
247 | queryMode: 'local',
248 | },
249 | {
250 | xtype: 'combobox',
251 | name: 'to',
252 | fieldLabel: t('workflow_transition_to'),
253 | store: this.placesStore,
254 | value: transition.get('to'),
255 | displayField: 'label',
256 | valueField: 'id',
257 | multiSelect: true,
258 | queryMode: 'local',
259 | },
260 | ]
261 | });
262 |
263 | this.notificationSettings = new Ext.Panel({
264 | defaults: {
265 | width: '100%',
266 | labelWidth: 200
267 | },
268 | items: [
269 | {
270 | xtype: 'grid',
271 | itemId: 'placesGrid',
272 | margin: '0 0 15 0',
273 | store: this.notificationStore,
274 | columns: [
275 | {
276 | xtype: 'gridcolumn',
277 | dataIndex: 'condition',
278 | text: t('workflow_transition_notification_condition'),
279 | flex: 1
280 | },
281 | {
282 | menuDisabled: true,
283 | sortable: false,
284 | xtype: 'actioncolumn',
285 | width: 60,
286 | items: [{
287 | iconCls: 'pimcore_icon_edit',
288 | tooltip: t('edit'),
289 | handler: function (grid, rowIndex, colIndex) {
290 | new pimcore.plugin.workflow.transition_notification(this.notificationStore, grid.store.getAt(rowIndex));
291 | }.bind(this)
292 | }, {
293 | iconCls: 'pimcore_icon_delete',
294 | tooltip: t('delete'),
295 | handler: function (grid, rowIndex, colIndex) {
296 | grid.store.removeAt(rowIndex);
297 | }.bind(this)
298 | }]
299 | },
300 | ],
301 | tbar: [
302 | {
303 | text: t('add'),
304 | handler: function (btn) {
305 | var record = new WorkflowGUI.Transition.Notification();
306 |
307 | new pimcore.plugin.workflow.transition_notification(this.notificationStore, record);
308 | }.bind(this),
309 | iconCls: 'pimcore_icon_add'
310 | }
311 | ]
312 | }
313 | ]
314 | });
315 |
316 | this.settingsPanel = new Ext.Panel({
317 | border: false,
318 | autoScroll: true,
319 | padding: 10,
320 | defaults: {
321 | width: '100%',
322 | labelWidth: 200
323 | },
324 | items: [
325 | {
326 | xtype: 'fieldset',
327 | title: t('workflow_transition_settings'),
328 | defaults: {
329 | width: '100%',
330 | labelWidth: 200
331 | },
332 | items: this.settingsForm
333 | },
334 | {
335 | xtype: 'fieldset',
336 | title: t('workflow_transition_options'),
337 | defaults: {
338 | width: '100%',
339 | labelWidth: 200
340 | },
341 | items: this.optionsForm
342 | },
343 | {
344 | xtype: 'fieldset',
345 | title: t('workflow_transition_notes'),
346 | defaults: {
347 | width: '100%',
348 | labelWidth: 200
349 | },
350 | items: this.notesForm
351 | },
352 | {
353 | xtype: 'fieldset',
354 | title: t('workflow_transition_notifications'),
355 | defaults: {
356 | width: '100%',
357 | labelWidth: 200
358 | },
359 | items: this.notificationSettings
360 | }
361 | ],
362 | buttons: [
363 | {
364 | text: t('save'),
365 | handler: function (btn) {
366 | if (this.settingsForm.isValid()) {
367 | var formValues = this.settingsForm.getForm().getFieldValues();
368 | var optionsValues = this.optionsForm.getForm().getFieldValues();
369 | var notesValues = this.notesForm.getForm().getFieldValues();
370 | var additionalFields = this.additionalFieldsStore.getRange();
371 | var storeRecord = this.store.getById(formValues['id']);
372 | var notifications = this.notificationStore.getRange();
373 |
374 | if (storeRecord && storeRecord !== transition) {
375 | Ext.Msg.alert(t('workflow_transition_id'), t('workflow_transition_with_id_already_exists'));
376 | return;
377 | }
378 |
379 | notifications = notifications.map(function(record) {
380 | var data = record.data;
381 |
382 | delete data['id'];
383 |
384 | return data;
385 | });
386 |
387 | additionalFields = additionalFields.map(function(record) {
388 | var data = record.data;
389 |
390 | delete data['id'];
391 |
392 | return data;
393 | });
394 |
395 | this.store.remove(transition);
396 |
397 | notesValues['additionalFields'] = additionalFields;
398 |
399 | optionsValues['notes'] = notesValues;
400 | optionsValues['notificationSettings'] = notifications;
401 |
402 | if (!formValues['guard']) {
403 | delete formValues['guard'];
404 | }
405 |
406 | transition.data = {};
407 | transition.set(formValues);
408 | transition.set('options', optionsValues);
409 | transition.commit();
410 |
411 | this.store.add(transition);
412 |
413 | this.window.close();
414 | }
415 | }.bind(this),
416 | iconCls: 'pimcore_icon_apply'
417 | }
418 | ],
419 | });
420 |
421 | return this.settingsPanel;
422 | }
423 | });
424 |
--------------------------------------------------------------------------------
/gpl-3.0.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.