diff --git a/components/Toolbox.vue b/components/Toolbox.vue index 2f1441e9..d2a22fc7 100644 --- a/components/Toolbox.vue +++ b/components/Toolbox.vue @@ -615,7 +615,7 @@ padding: 13px; color: currentColor !important; font-size: 1.1em; - margin: 0px; + margin: 0; } .panel-title { font-weight: bold; @@ -655,7 +655,6 @@ margin-bottom: 5px; font-size: 1.1em; color: #000; - margin-top: 5px; } .snap-tool { display: flex; @@ -671,6 +670,9 @@ .tools-of-tool-snap label span { color: #222d32 !important; } + .panel-body { + padding: 15px; + } .panel-body.disabled { opacity: .7; } diff --git a/g3wsdk/workflow/step.js b/g3wsdk/workflow/step.js index 8485e4dd..58ae21be 100644 --- a/g3wsdk/workflow/step.js +++ b/g3wsdk/workflow/step.js @@ -31,7 +31,9 @@ export class Step extends G3WObject { this._options = options; + //store promise of current running step when call run this._run = (options.run || this.run || (async () => true)).bind(this); + //store promise of current running step when call stop this._stop = (options.stop || this.stop || (async () => true)).bind(this); /** @@ -102,7 +104,7 @@ export class Step extends G3WObject { * @since g3w-client-plugin-editing@v3.8.0 */ if (options.onStop) { - this.on('run', options.onStop); + this.on('stop', options.onStop); } /** @@ -389,7 +391,7 @@ export class Step extends G3WObject { */ registerEscKeyEvent(callback) { if (callback) { - this.on('run', () => this.bindEscKeyUp(callback)); + this.on('run', () => this.bindEscKeyUp(callback)); this.on('stop', () => this.unbindEscKeyUp()); } } @@ -410,10 +412,12 @@ export class Step extends G3WObject { */ __run(inputs, context) { return $promisify(async() => { + //set step inputs this.setInputs(inputs); + //set step context this.setContext(context); - const step = this; + const step = this; const toolsOfTools = { snap: { @@ -471,7 +475,7 @@ export class Step extends G3WObject { try { this.state.running = true; // change state to running return await promisify(this._run(inputs, context)); - } catch (e) { + } catch(e) { console.warn(e); this.state.error = e; return Promise.reject(e); @@ -489,8 +493,8 @@ export class Step extends G3WObject { * * @fires stop */ - __stop() { - this._stop(this._inputs, this._context); // stop task + async __stop() { + await this._stop(this._inputs, this._context); // stop task this.state.running = false; // remove running state if (this._workflow) { this._workflow._toolsoftool.forEach(t => t.options.stop()); diff --git a/g3wsdk/workflow/workflow.js b/g3wsdk/workflow/workflow.js index bd4a9c21..fdebb319 100644 --- a/g3wsdk/workflow/workflow.js +++ b/g3wsdk/workflow/workflow.js @@ -187,16 +187,6 @@ export class Workflow extends G3WObject { } } - /** - * @FIXME add description - */ - removeChild() { - if (this._child) { - Workflow.Stack.removeAt(this._child.getStackIndex()); - } - this._child = null; - } - /** * @param input.key * @param input.value @@ -298,7 +288,7 @@ export class Workflow extends G3WObject { /** * @FIXME add description */ - reject () { + reject() { if (this._promise) { this._promise.reject(); } @@ -314,19 +304,28 @@ export class Workflow extends G3WObject { } } + /** + * Method to run steps of workflow + * @param step + * @param inputs + * @return {Promise} + */ async runStep(step, inputs) { try { + //set step message this.setMessages({ help: step.state.help }); + //run step const outputs = await promisify(step.__run(inputs, this.getContext())); // onDone → check if all step is resolved this._stepIndex++; + //check if is the last of workflow steps if (this._stepIndex === this.getSteps().length) { this._stepIndex = 0; return outputs; } else { return this.runStep(this.getSteps()[this._stepIndex], outputs); } - } catch (e) { + } catch(e) { //In case of reject this._stepIndex = 0; return Promise.reject(e); } @@ -358,13 +357,15 @@ export class Workflow extends G3WObject { ) { Workflow.Stack.getCurrent().addChild(this) } - + + //get stack index this._stackIndex = Workflow.Stack.push(this); + //get steps this._steps = options.steps || this._steps; - + //for each step assign current workflow to _workflow (this._steps || []).forEach(s => s._workflow = this); - const showUserMessage = Object.keys(this._userMessageSteps).length; + const showUserMessage = Object.keys(this._userMessageSteps).length > 0; if (showUserMessage) { GUI.showUserMessage({ @@ -383,19 +384,20 @@ export class Workflow extends G3WObject { } }); } - //emit start + //emit start Workflow this.emit('start'); try { console.assert(0 === this._stepIndex, `reset workflow before restarting: ${this._stepIndex}`) //start flow of workflow const outputs = await this.runStep(this.getSteps()[this._stepIndex], this.getInputs()); + //In case of show user message (tool steps) if (showUserMessage) { setTimeout(() => { this.clearUserMessagesSteps(); resolve(outputs); }, 500); } else { resolve(outputs); } - } catch (e) { + } catch(e) { console.warn(e); if (showUserMessage) { this.clearUserMessagesSteps(); @@ -403,6 +405,7 @@ export class Workflow extends G3WObject { reject(e); } + //in case of worflow that need to run once time, stop workflow if (this.runOnce) { this.stop(); } @@ -414,31 +417,32 @@ export class Workflow extends G3WObject { * * @fires stop */ - stop() { + async stop() { return $promisify(new Promise(async (resolve, reject) => { + this._promise = null; try { // stop child workflow if (this._child) { - await promisify(this._child.stop()); + await promisify(this._child.stop()); } } catch(e) { console.warn(e); } - - // ensure that child is always removed - this.removeChild(); - - Workflow.Stack.removeAt(this.getStackIndex()); + //remove child + this._child = null; // stop flow try { - if (this.getSteps()[this._stepIndex].isRunning()) { + //get current step + const step = this.getSteps()[this._stepIndex]; + //check if it is running + if (step.isRunning()) { //clear messages steps this.clearMessages(); - //stop a current step - this.getSteps()[this._stepIndex].__stop(); + //wait stop run + await step.__stop(); } // reset counter and reject flow if (this._stepIndex > 0) { @@ -448,11 +452,15 @@ export class Workflow extends G3WObject { } else { resolve(); } - } catch (e) { + } catch(e) { console.warn(e); reject(e); } + //remove workflow from stack + Workflow.Stack.removeAt(this.getStackIndex()); + + //emit stop Workflow this.emit('stop'); })); @@ -634,5 +642,5 @@ Workflow.Stack = { removeAt(i) { workflows.splice(i, 1); }, insertAt(i, w) { workflows[i] = w; }, getAt(i) { return workflows[i]; }, - clear() { while (workflows.length) { (workflows.pop()).stop(); } }, + async clear() { workflows.splice(0); } }; \ No newline at end of file diff --git a/toolboxes/toolbox.js b/toolboxes/toolbox.js index 847751a3..a4447c3d 100644 --- a/toolboxes/toolbox.js +++ b/toolboxes/toolbox.js @@ -25,7 +25,6 @@ import { promisify, $promisify } from '../utils/promisify import { unlinkRelation } from '../utils/unlinkRelation'; import { splitFeatures } from '../utils/splitFeatures'; import { isSameBaseGeometryType } from '../utils/isSameBaseGeometryType'; -import { dissolve } from '../utils/dissolve'; import { PickFeaturesInteraction } from '../interactions/pickfeaturesinteraction'; import { @@ -59,7 +58,7 @@ const { const { ProjectsRegistry } = g3wsdk.core.project; const { DataRouterService } = g3wsdk.core.data; const { CatalogLayersStoresRegistry } = g3wsdk.core.catalog; -const { Geometry } = g3wsdk.core.geoutils; +const { Geometry, dissolve } = g3wsdk.core.geoutils; const { removeZValueToOLFeatureGeometry } = g3wsdk.core.geoutils.Geometry; const { tPlugin } = g3wsdk.core.i18n; const { Layer } = g3wsdk.core.layer; @@ -544,7 +543,7 @@ export class ToolBox extends G3WObject { context: { session: Workflow.Stack.getCurrent().getSession(), // get parent workflow excludeFields: fields.ownField, // array of fields to be excluded - isContentChild: false, //@since 3.9.0 force child to flase + isContentChild: false, //@since 3.9.0 force child to false }, inputs: { features: rLayer.readFeatures(), diff --git a/utils/dissolve.js b/utils/dissolve.js deleted file mode 100644 index 98de4a85..00000000 --- a/utils/dissolve.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * ORIGINAL SOURCE: g3w-client/src/utils/dissolve.js@v3.10.2 - * - * @param { Object } opts - * @param { Array } opts.features - * @param { number } opts.index - * @param { boolean } opts.clone - * - * @returns dissolved feature - * - * @since g3w-client-plugin-editing@v3.9.0 - */ -export function dissolve({ - features = [], - index = 0, - clone = false, -} = {}) { - - const parser = new jsts.io.OL3Parser(); - const featuresLength = features.length; - - - /** In case no features to dissolve */ - if (0 === featuresLength) { - return null; - } - - /** In the case of single feature, return feature */ - if (1 === featuresLength) { - return features[0]; - } - - let jstsdissolvedFeatureGeometry; - - const baseFeature = clone ? features[index].clone() : features[index]; - const baseFeatureGeometry = baseFeature.getGeometry(); - const baseFeatureGeometryType = baseFeatureGeometry.getType(); - - // check if it can build a LineString - if ('LineString' === baseFeatureGeometryType) { - const lineMerger = new jsts.operation.linemerge.LineMerger(); - for (let i = 0; i < featuresLength; i++) { - lineMerger.addLineString( - new jsts.geom.GeometryFactory().createLineString(parser.read(features[i].getGeometry()).getCoordinates()) - ); - } - const mergedLineString = lineMerger.getMergedLineStrings(); - jstsdissolvedFeatureGeometry = 1 === mergedLineString.size() ? mergedLineString.toArray()[0] : null; - } - - if ('LineString' !== baseFeatureGeometryType) { - jstsdissolvedFeatureGeometry = parser.read(baseFeatureGeometry); - for (let i = 0; i < featuresLength ; i++) { - if (index !== i) { - jstsdissolvedFeatureGeometry = jstsdissolvedFeatureGeometry.union(parser.read(features[i].getGeometry())) - } - } - } - - /** In case of no dissolved geometry */ - if (!jstsdissolvedFeatureGeometry) { - return null; - } - - const dissolvedFeatureGeometry = parser.write(jstsdissolvedFeatureGeometry); - const dissolvedFeatureGeometryType = dissolvedFeatureGeometry.getType(); - const dissolvedFeatureGeometryCoordinates = dissolvedFeatureGeometryType === baseFeatureGeometryType - ? dissolvedFeatureGeometry.getCoordinates() - : -1 !== baseFeatureGeometryType.indexOf('Multi') && dissolvedFeatureGeometryType === baseFeatureGeometryType.replace('Multi', '') - ? [dissolvedFeatureGeometry.getCoordinates()] - : null; - - /** In case of null feature dissolved coordinates */ - if (null === dissolvedFeatureGeometryCoordinates) { - return null; - } - - baseFeature.getGeometry().setCoordinates(dissolvedFeatureGeometryCoordinates); - - return baseFeature; -} \ No newline at end of file diff --git a/workflows/index.js b/workflows/index.js index ce07a906..3c051823 100644 --- a/workflows/index.js +++ b/workflows/index.js @@ -402,66 +402,78 @@ export class OpenFormStep extends Step { * @returns {*} */ run(inputs, context) { - const promise = new Promise(async (resolve, reject) => { - //@since 3.9.0 can set isContentChild attribute to force it (case edit relation features from multi parent features) - this._isContentChild = undefined === context.isContentChild ? Workflow.Stack.getLength() > 1 : context.isContentChild; - this.layerId = inputs.layer.getId(); + return $promisify(async () => { + //@since 3.9.0 can set isContentChild attribute to force it + // (case edit relation features from multi-parent features) + this._isContentChild = undefined === context.isContentChild ? Workflow.Stack.getLength() > 1 : context.isContentChild; + this.layerId = inputs.layer.getId(); + this._features = this._multi ? inputs.features : [inputs.features[inputs.features.length - 1]]; + this._originalFeatures = this._features.map(f => f.clone()); - GUI.setLoadingContent(false); + //@since 3.9.0 promise + const promise = new Promise((resolve) => { + g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').subscribe(`closeform_${this.layerId}`, () => { + resolve(); + return { once: true }; // once close form, remove subscribing + }) + }) - GUI.getService('map').disableClickMapControls(true); + //set selected features + setAndUnsetSelectedFeaturesStyle({ promise: $promisify(promise), inputs, style: this.selectStyle }); + return new Promise(async (resolve, reject) => { + GUI.setLoadingContent(false); - if (!this._multi && Array.isArray(inputs.features[inputs.features.length - 1])) { - resolve(); - return; - } + GUI.getService('map').disableClickMapControls(true); - g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').setCurrentLayout(); + if (!this._multi && Array.isArray(inputs.features[inputs.features.length - 1])) { + resolve(); + return; + } - const layerName = inputs.layer.getName(); - this._features = this._multi ? inputs.features : [inputs.features[inputs.features.length - 1]]; - this._originalFeatures = this._features.map(f => f.clone()); + g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').setCurrentLayout(); - // create a child relation feature set a father relation field value - if (this._isContentChild) { - context.fatherValue = context.fatherValue || []; // are array - (context.fatherField || []).forEach((field, i) => { - this._features[0].set(field, context.fatherValue[i]); - this._originalFeatures[0].set(field, context.fatherValue[i]); - }); - } + const layerName = inputs.layer.getName(); - const fields = getFormFields({ - inputs, - context, - feature: this._features[0], - isChild: this._isContentChild, - multi: this._multi, - }); + // create a child relation feature set a father relation field value + if (this._isContentChild) { + context.fatherValue = context.fatherValue || []; // are array + (context.fatherField || []).forEach((field, i) => { + this._features[0].set(field, context.fatherValue[i]); + this._originalFeatures[0].set(field, context.fatherValue[i]); + }); + } - // set fields. Useful getParentFormData - Workflow.Stack.getCurrent().setInput({ key: 'fields', value: fields }); - - // whether disable relations editing (ref: "editmultiattributes") - const feature = !this._multi && inputs.features && inputs.features[inputs.features.length - 1]; - const layerId = !this._multi && inputs.layer.getId(); - - // @since g3w-client-plugin-editing@v3.7.2 - // skip relations that don't have a form structure - if (feature && !feature.isNew() && inputs.layer.getLayerEditingFormStructure()) { - await getLayersDependencyFeatures(inputs.layer.getId(), { - // @since g3w-client-plugin-editin@v3.7.0 - relations: inputs.layer.getRelations().getArray().filter(r => - inputs.layer.getId() === r.getFather() && // get only child relation features of current editing layer - getEditingLayerById(r.getChild()) && // child layer is in editing - 'ONE' !== r.getType() // exclude ONE relation (Join 1:1) - ), - feature, - filterType: 'fid', + const fields = getFormFields({ + inputs, + context, + feature: this._features[0], + isChild: this._isContentChild, + multi: this._multi, }); - } + + // set fields. Useful getParentFormData + Workflow.Stack.getCurrent().setInput({ key: 'fields', value: fields }); + + // whether disable relations editing (ref: "editmultiattributes") + const feature = !this._multi && inputs.features && inputs.features[inputs.features.length - 1]; + const layerId = !this._multi && inputs.layer.getId(); + + // @since g3w-client-plugin-editing@v3.7.2 + // skip relations that don't have a form structure + if (feature && !feature.isNew() && inputs.layer.getLayerEditingFormStructure()) { + await getLayersDependencyFeatures(inputs.layer.getId(), { + // @since g3w-client-plugin-editin@v3.7.0 + relations: inputs.layer.getRelations().getArray().filter(r => + inputs.layer.getId() === r.getFather() && // get only child relation features of current editing layer + getEditingLayerById(r.getChild()) && // child layer is in editing + 'ONE' !== r.getType() // exclude ONE relation (Join 1:1) + ), + feature, + filterType: 'fid', + }); + } /** ORIGINAL SOURCE: g3w-client-plugin-editing/form/editingform.js@v3.7.8 */ /** ORIGINAL SOURCE: g3w-client-plugin-editing/form/editingformservice.js@v3.7.8 */ @@ -484,10 +496,11 @@ export class OpenFormStep extends Step { /** @TODO make it straightforward: `headerComponent` vs `buttons` ? */ headerComponent: this._saveAll && { template: /* html */ ` -
+
+ +
+ + + +
`, - name: 'Saveall', - /** @TODO figure out who populate these props (ie. core client code?) */ - props: { update: { type: Boolean }, valid: { type: Boolean } }, - data() { - return { - enabled: Workflow.Stack._workflows.slice(0, Workflow.Stack.getLength() - 1) - .every(w => { - const valid = ((w.getContext().service instanceof FormService) ? w.getContext().service.getState() : {}).valid; - return valid || undefined === valid; - }), - }; - }, - computed: { - /** @returns {boolean} whether disable save all button (eg. when parent or current form is not valid/ updated) */ - disabled() { - return !this.enabled || !(this.valid && this.update); + name: 'Saveall', + /** @TODO figure out who populate these props (ie. core client code?) */ + props: { update: { type: Boolean }, valid: { type: Boolean } }, + data() { + return { + enabled: Workflow.Stack._workflows.slice(0, Workflow.Stack.getLength() - 1) + .every(w => { + const valid = ((w.getContext().service instanceof FormService) ? w.getContext().service.getState() : {}).valid; + return valid || undefined === valid; + }), + isChild: Workflow.Stack.getLength() > 1 && !(2 === Workflow.Stack.getLength() && Workflow.Stack.getFirst().isType('edittable')) + }; }, - }, - methods: { - async saveAll() { - //Set loading content - GUI.setLoadingContent(true); - //Disable form - GUI.disableContent(true); - await Promise.allSettled( - [...Workflow.Stack._workflows] - .reverse() - .filter(w => "function" === typeof w.getLastStep()._saveAll) // need to filter only workflow that - .map( w => new Promise(async (resolve) => { - const task = w.getLastStep(); - const fields = w.getContext().service.state.fields.filter(f => task._multi ? null !== f.value : true); - // skip when no fields - if (0 === fields.length) { return } - await Workflow.Stack.getCurrent().getContextService().saveDefaultExpressionFieldsNotDependencies(); - task._features.forEach(f => task.getInputs().layer.setFieldsWithValues(f, fields)); - const newFeatures = task._features.map(f => f.clone()); - //Is a relation form - if (task._isContentChild) { - task.getInputs().relationFeatures = { newFeatures, originalFeatures: task._originalFeatures }; - } - await task.fireEvent('saveform', { newFeatures, originalFeatures: task._originalFeatures }); - newFeatures.forEach((f, i) => task.getContext().session.pushUpdate(task.layerId, f, task._originalFeatures[i])); - await handleRelation1_1LayerFields({ layerId: task.layerId, features: newFeatures, fields, task }); - task.fireEvent('savedfeature', newFeatures); // called after saved - task.fireEvent(`savedfeature_${task.layerId}`, newFeatures); // called after saved using layerId - task.getContext().session.save(); - return resolve(); - })) - ) - try { - await promisify(g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').service.commit({ modal: false })); - [...Workflow.Stack._workflows] - .reverse() - .filter(w => "function" === typeof w.getLastStep()._saveAll) - .forEach(w => { - const service = w.getContext().service; //form service - //need to set update form false because already saved on server - service.setUpdate(false, { force: false }); - const feature = service.feature; - // Check if the feature is new. - // In this case, after commit, need to set new to false, and force update to false. - if (feature.isNew()) { - feature.state.new = false; - service.force.update = false; - } - Object.entries( - w.getInputs().layer.getEditingSource().readFeatures() - .find(f => f.getUid() === feature.getUid()) //Find current form editing feature by unique id of feature uid - .getProperties() //get properties - ) - .forEach(([k, v]) => { - const field = service.getFields().find(f => k === f.name); - //if field exists (geometry field is discarded) - if (field) { - field.value = field._value = v; - } - }) - }) - } catch(e) { - console.warn(e); + computed: { + /** @returns {boolean} whether disable save all button (eg. when parent or current form is not valid/ updated) */ + disabled() { + return !this.enabled || !(this.valid && this.update); + }, + }, + methods: { + async saveAll() { + //Set loading content + GUI.setLoadingContent(true); + //Disable form + GUI.disableContent(true); + await Promise.allSettled( + [...Workflow.Stack._workflows] + .reverse() + .filter(w => "function" === typeof w.getLastStep()._saveAll) // need to filter only workflow that + .map( w => new Promise(async (resolve) => { + const task = w.getLastStep(); + const fields = w.getContext().service.state.fields.filter(f => task._multi ? null !== f.value : true); + // skip when no fields + if (0 === fields.length) { return } + await Workflow.Stack.getCurrent().getContextService().saveDefaultExpressionFieldsNotDependencies(); + task._features.forEach(f => task.getInputs().layer.setFieldsWithValues(f, fields)); + const newFeatures = task._features.map(f => f.clone()); + //Is a relation form + if (task._isContentChild) { + task.getInputs().relationFeatures = { newFeatures, originalFeatures: task._originalFeatures }; + } + await task.fireEvent('saveform', { newFeatures, originalFeatures: task._originalFeatures }); + newFeatures.forEach((f, i) => task.getContext().session.pushUpdate(task.layerId, f, task._originalFeatures[i])); + await handleRelation1_1LayerFields({ layerId: task.layerId, features: newFeatures, fields, task }); + task.fireEvent('savedfeature', newFeatures); // called after saved + task.fireEvent(`savedfeature_${task.layerId}`, newFeatures); // called after saved using layerId + task.getContext().session.save(); + return resolve(); + })) + ) + try { + await promisify(g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').service.commit({ modal: false })); + [...Workflow.Stack._workflows] + .reverse() + .filter(w => "function" === typeof w.getLastStep()._saveAll) + .forEach(w => { + const service = w.getContext().service; //form service + //need to set update form false because already saved on server + service.setUpdate(false, { force: false }); + const feature = service.feature; + // Check if the feature is new. + // In this case, after commit, need to set new to false, and force update to false. + if (feature.isNew()) { + feature.state.new = false; + service.force.update = false; + } + Object.entries( + w.getInputs().layer.getEditingSource().readFeatures() + .find(f => f.getUid() === feature.getUid()) //Find current form editing feature by unique id of feature uid + .getProperties() //get properties + ) + .forEach(([k, v]) => { + const field = service.getFields().find(f => k === f.name); + //if field exists (geometry field is discarded) + if (field) { + field.value = field._value = v; + } + }) + }) + } catch(e) { + console.warn(e); + } + //set loading content false + GUI.setLoadingContent(false); + //enable form + GUI.disableContent(false); + }, + /** + * @since 3.9.0 + * Close editing form + */ + async closeForm() { + //get current active tool + const tool = g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').state.toolboxselected.getActiveTool(); + //stop active tool and wait + await promisify(tool.stop()); + //clear all workflow stacks + Workflow.Stack.clear(); + //check if the tool needs to run on time. If not, start again + if (!tool.getOperator().runOnce) { + tool.start(); + } } - //set loading content false - GUI.setLoadingContent(false); - //enable form - GUI.disableContent(false); }, }, - }, - buttons: [ - { - id: 'save', - title: this._isContentChild - ? Workflow.Stack.getParent().getBackButtonLabel() || "plugins.editing.form.buttons.save_and_back" // get custom back label from parent - : "plugins.editing.form.buttons.save", - type: "save", - class: "btn-success", - // save features - cbk: async (fields) => { - fields = this._multi ? fields.filter(f => null !== f.value) : fields; + buttons: [ + { + id: 'save', + title: this._isContentChild + ? Workflow.Stack.getParent().getBackButtonLabel() || "plugins.editing.form.buttons.save_and_back" // get custom back label from parent + : "plugins.editing.form.buttons.save", + type: "save", + class: "btn-success", + // save features + cbk: async (fields) => { + fields = this._multi ? fields.filter(f => null !== f.value) : fields; // skip when no fields if (0 === fields.length) { @@ -608,46 +656,46 @@ export class OpenFormStep extends Step { return; } - const newFeatures = []; + const newFeatures = []; - // @since 3.5.15 - GUI.setLoadingContent(true); - GUI.disableContent(true); + // @since 3.5.15 + GUI.setLoadingContent(true); + GUI.disableContent(true); - await Workflow.Stack.getCurrent().getContextService().saveDefaultExpressionFieldsNotDependencies(); + await Workflow.Stack.getCurrent().getContextService().saveDefaultExpressionFieldsNotDependencies(); - GUI.setLoadingContent(false); - GUI.disableContent(false); + GUI.setLoadingContent(false); + GUI.disableContent(false); - this._features.forEach(f => { - inputs.layer.setFieldsWithValues(f, fields); - newFeatures.push(f.clone()); - }); + this._features.forEach(f => { + inputs.layer.setFieldsWithValues(f, fields); + newFeatures.push(f.clone()); + }); - if (this._isContentChild) { - inputs.relationFeatures = { - newFeatures, - originalFeatures: this._originalFeatures - }; - } + if (this._isContentChild) { + inputs.relationFeatures = { + newFeatures, + originalFeatures: this._originalFeatures + }; + } - await this.fireEvent('saveform', { newFeatures, originalFeatures: this._originalFeatures}); + await this.fireEvent('saveform', { newFeatures, originalFeatures: this._originalFeatures}); - newFeatures.forEach((f, i) => context.session.pushUpdate(this.layerId, f, this._originalFeatures[i])); + newFeatures.forEach((f, i) => context.session.pushUpdate(this.layerId, f, this._originalFeatures[i])); - // check and handle if layer has relation 1:1 - await handleRelation1_1LayerFields({ - layerId: this.layerId, - features: newFeatures, - fields, - task: this, - }); + // check and handle if layer has relation 1:1 + await handleRelation1_1LayerFields({ + layerId: this.layerId, + features: newFeatures, + fields, + task: this, + }); - GUI.setModal(false); + GUI.setModal(false); this.fireEvent('savedfeature', newFeatures); // called after saved this.fireEvent(`savedfeature_${this.layerId}`, newFeatures); // called after saved using layerId - // In case of save of child it means that child is updated so also parent + // In case of save of child, it means that child is updated so also parent if (this._isContentChild) { Workflow.Stack.getParents() //filter only with has getContextService to be sure @@ -675,79 +723,73 @@ export class OpenFormStep extends Step { } }, cbk: () => { - if (!this._isContentChild) { - GUI.setModal(false); - this.fireEvent('cancelform', inputs.features); // fire event cancel form to emit to subscrivers - } + this.fireEvent('cancelform', inputs.features); // fire event cancel form to emit to subscribers reject(inputs); } } ] }); - // Overwrite click on relation. - // Open FormRelation.vue component - formService.handleRelation = async e => { - // Skip when multi editing features - // It is not possible to manage relationss when we edit multi-features - if (this._multi) { - GUI.showUserMessage({ type: 'info', message: 'plugins.editing.errors.editing_multiple_relations', duration: 3000, autoclose: true }); - return; + // Overwrite click on relation. + // Open FormRelation.vue component + formService.handleRelation = async e => { + // Skip when multi editing features + // It is not possible to manage relationss when we edit multi-features + if (this._multi) { + GUI.showUserMessage({ type: 'info', message: 'plugins.editing.errors.editing_multiple_relations', duration: 3000, autoclose: true }); + return; + } + GUI.setLoadingContent(true); + //set unique values for relation layer based on unique fields + //@TODO need a find a way to call once and not every time we open a relation + await setLayerUniqueFieldValues(inputs.layer.getRelationById(e.relation.name).getChild()); + formService.setCurrentComponentById(e.relation.name); + GUI.setLoadingContent(false); } - GUI.setLoadingContent(true); - //set unique values for relation layer based on unique fields - //@TODO need a find a way to call once and not every time we open a relation - await setLayerUniqueFieldValues(inputs.layer.getRelationById(e.relation.name).getChild()); - formService.setCurrentComponentById(e.relation.name); - GUI.setLoadingContent(false); - } - formService.addComponents([ - // custom form components - ...(g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').state.formComponents[layerId] || []), - // relation components (exlcude ONE relation + layer is the father get relation layers that set in editing on g3w-admin) - ...getRelationsInEditingByFeature({ - layerId, - relations: this._multi ? [] : inputs.layer.getRelations().getArray().filter(r => r.getType() !== 'ONE' && r.getFather() === layerId), - feature: this._multi ? false : inputs.features[inputs.features.length - 1], - }).map(({ relation, relations }) => ({ - title: "plugins.editing.edit_relation", - name: relation.name, - id: relation.id, - header: false, // hide a header form - component: Vue.extend({ - mixins: [ require('../components/FormRelation.vue') ], - name: `relation_${Date.now()}`, - data() { - return { layerId, relation, relations }; - }, - }), - })) - ]); + formService.addComponents([ + // custom form components + ...(g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').state.formComponents[layerId] || []), + // relation components (exlcude ONE relation + layer is the father get relation layers that set in editing on g3w-admin) + ...getRelationsInEditingByFeature({ + layerId, + relations: this._multi ? [] : inputs.layer.getRelations().getArray().filter(r => r.getType() !== 'ONE' && r.getFather() === layerId), + feature: this._multi ? false : inputs.features[inputs.features.length - 1], + }).map(({ relation, relations }) => ({ + title: "plugins.editing.edit_relation", + name: relation.name, + id: relation.id, + header: false, // hide a header form + component: Vue.extend({ + mixins: [ require('../components/FormRelation.vue') ], + name: `relation_${Date.now()}`, + data() { + return { layerId, relation, relations }; + }, + }), + })) + ]); + + // fire openform event + this.fireEvent('openform', + { + layerId: this.layerId, + session: context.session, + feature: this._originalFeature, + formService + } + ); - // fire openform event - this.fireEvent('openform', - { - layerId: this.layerId, - session: context.session, - feature: this._originalFeature, - formService + // set context service to form Service in case of a single task (i.e., no workflow) + if (Workflow.Stack.getCurrent()) { + Workflow.Stack.getCurrent().setContextService(formService); } - ); - - // set context service to form Service in case of a single task (i.e., no workflow) - if (Workflow.Stack.getCurrent()) { - Workflow.Stack.getCurrent().setContextService(formService); - } - //listen eventually field relation 1:1 changes value - listenRelation1_1FieldChange({ layerId: this.layerId, fields }).then(d => this._unwatchs = d); + //listen eventually field relation 1:1 changes value + listenRelation1_1FieldChange({ layerId: this.layerId, fields }).then(d => this._unwatchs = d); - this.disableSidebar(true); - }) - return $promisify(async () => { - setAndUnsetSelectedFeaturesStyle({ promise: $promisify(promise), inputs, style: this.selectStyle }); - return promise; + this.disableSidebar(true); + }); }); } @@ -764,12 +806,12 @@ export class OpenFormStep extends Step { 2 === Workflow.Stack.getLength() && //open features table Workflow.Stack.getParent().isType('edittable') ); - // when the last feature of features is Array // and is resolved without setting form service // Ex. copy multiple features from another layer if (is_parent_table) { GUI.getService('map').disableClickMapControls(false); + GUI.setModal(false); } const contextService = is_parent_table && Workflow.Stack.getCurrent().getContextService(); @@ -778,6 +820,7 @@ export class OpenFormStep extends Step { if (contextService && contextService.setUpdate && false === this._isContentChild) { contextService.setUpdate(false, { force: false }); } + //@since 3.9.0 add GUI.getContentLength() in case of edit multi relationfeatures tool GUI.closeForm({ pop: this.push || this._isContentChild && GUI.getContentLength() > 1 }); @@ -789,7 +832,6 @@ export class OpenFormStep extends Step { this.layerId = null; this._unwatchs.forEach(unwatch => unwatch()); this._unwatchs = []; - } }