Skip to content

Commit

Permalink
♻️ Unique fields
Browse files Browse the repository at this point in the history
  • Loading branch information
volterra79 committed Sep 13, 2024
1 parent c946e99 commit 0a66d56
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 168 deletions.
11 changes: 1 addition & 10 deletions components/FormRelation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -721,22 +721,13 @@
const unique_fields = g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').state.uniqueFieldsValues[this._relationLayerId];
//check if relation layer has unique values stored
if (undefined !== unique_fields) {
//get parent layer unique fields
const parent_relation_unique_fields = (
g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').state.uniqueFieldsValues[this.layerId]
&& g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').state.uniqueFieldsValues[this.layerId].__uniqueFieldsValuesRelations
&& g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').state.uniqueFieldsValues[this.layerId].__uniqueFieldsValuesRelations[this._relationLayerId]
)
Object
.keys(relationfeature.getProperties())
.filter(p => undefined !== unique_fields[p])
.forEach(p => {
const values = new Set(unique_fields[p]);
//@TODO Check if we need remove
values.delete(relationfeature.get(p));
//In the case of parent store unique values field of relation, update values of this field
if (parent_relation_unique_fields) {
parent_relation_unique_fields.__uniqueFieldsValuesRelations[this._relationLayerId][p] = values;
}
})
}

Expand Down
6 changes: 6 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ new (class extends Plugin {

this.state.editableLayers[layer.getId()] = layer;

//set default empty object
this.state.uniqueFieldsValues[layer.getId()] = {}

/**
* attach layer widgets event: get data from api when a field of a layer
* is related to a wgis form widget (ex. relation reference, value map, etc..)
Expand Down Expand Up @@ -851,6 +854,9 @@ new (class extends Plugin {
this.state.toolboxselected = null;
this.state.message = null;

//reset unique values
Object.keys(this.state.uniqueFieldsValues).forEach(id => this.state.uniqueFieldsValue[id] = {});

GUI.getService('map').refreshMap();
}

Expand Down
63 changes: 15 additions & 48 deletions toolboxes/toolbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,6 @@ export class ToolBox extends G3WObject {

this._start = false;

const uniqueFields = layer.getEditingFields()
.filter(f => f.input && 'unique' === f.input.type)
.reduce((fields, f) => { fields[f.name] = f; return fields; }, {});

/**
* unique fields type
*/
this.uniqueFields = Object.keys(uniqueFields).length ? uniqueFields : null;

/** constraint loading features to a filter set */
this.constraints = { filter: null, show: null, tools: [] };

Expand Down Expand Up @@ -1216,12 +1207,6 @@ export class ToolBox extends G3WObject {
// BACKOMP v3.x
this.originalState = this.state.originalState;

// get informed when save on server
if (this.uniqueFields) {
this.getFieldUniqueValuesFromServer();
this._resetOnSaveChangesOnServer = true;
}

//event features
this._getFeaturesEvent = { event: null, fnc: null };

Expand Down Expand Up @@ -1308,30 +1293,6 @@ export class ToolBox extends G3WObject {
return this.state.editing.dependencies.length > 0;
}

/**
* Set unique value to filed unique
* @param reset
*/
getFieldUniqueValuesFromServer({
reset = false
} = {}) {
this.state.layer.getWidgetData({
type: 'unique',
fields: Object.values(this.uniqueFields).map(field => field.name).join()
})
.then((response) => {
Object
.entries(response.data || [])
.forEach(([fieldName, values]) => {
if (reset) {
this.uniqueFields[fieldName].input.options.values.splice(0);
}
values.forEach(value => this.uniqueFields[fieldName].input.options.values.push(value));
})
})
.fail(console.warn)
}

/**
* Create getFeatures options
*
Expand Down Expand Up @@ -1690,10 +1651,6 @@ export class ToolBox extends G3WObject {
response: new_relations[id],
result: true
});

//@since 3.9.0
toolbox._session.saveChangesOnServer(); // dispatch setter event.

}

this.__clearHistory();
Expand All @@ -1702,7 +1659,7 @@ export class ToolBox extends G3WObject {
* @since v3.9.0
* After commit get new unique values
*/
this._session.saveChangesOnServer();
this._session.saveChangesOnServer(commit);


// ES6 promises only accept a single response
Expand Down Expand Up @@ -2853,11 +2810,21 @@ export class ToolBox extends G3WObject {

/**
* Hook to get informed that are saved on server
*/
__saveChangesOnServer() {
if (this._resetOnSaveChangesOnServer) {
this.getFieldUniqueValuesFromServer({ reset: true });
* Get unique id for each commited layer/relation
*/
async __saveChangesOnServer(commit) {
const promises = [ setLayerUniqueFieldValues(this.getId()) ];
const relationsId = [];
const addRelationId = (relations = {}) => {
Object.entries(relations).forEach(([id, commit]) => {
relationsId.push(id);
addRelationId(commit.relations);
})
}
addRelationId(commit.relations);
relationsId.forEach(id => promises.push(setLayerUniqueFieldValues(id)));

await Promise.allSettled(promises);
}

/**
Expand Down
98 changes: 13 additions & 85 deletions utils/getFormFields.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Workflow } from '../g3wsdk/workflow/workflow';

const {sortAlphabeticallyArray, sortNumericArray} = g3wsdk.core.utils;
/**
* ORIGINAL SOURCE: g3w-client-plugin-editing/workflows/tasks/[email protected]
*
Expand All @@ -18,14 +17,11 @@ export function getFormFields({
inputs,
context,
feature, //current feature
isChild = false, //true -> relation form
multi, // true -> multi features (e.g edit multi features attributes form)
} = {}) {

//editing service
const service = g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing');
// root layerId (in case of child edit relation)
const relationLayerId = Workflow.Stack.getFirst().getInputs().layer.getId();
// current form layerId// unique values by feature field
const layerId = inputs.layer.getId();

Expand All @@ -39,55 +35,27 @@ export function getFormFields({

//Loop through fields
const unique_values = fields
//check if field is a unique widget type
.filter(f => f.validate.unique && f.editable)
//check if field is a unique field. Exclude pk not edittable
.filter(f => !(f.pk && false === f.editable) && ('unique' === f.input.type || f.validate.unique))
.map(field => ({
field, // feature field
_value: feature.get(field.name), // feature current field value
}))

//Loop through uniq value field
//Loop through unique fields
unique_values.forEach(({ _value, field }) => {
// current editing feature adds to
let current_values;
//get relations
const relations = isChild && (
service.state.uniqueFieldsValues[relationLayerId]
&& service.state.uniqueFieldsValues[relationLayerId].__uniqueFieldsValuesRelations
&& service.state.uniqueFieldsValues[relationLayerId].__uniqueFieldsValuesRelations[layerId]
);

//check if relation field has values
const has_values = relations && (undefined !== (relations[layerId] || {})[field.name]);

// child form --> belongs to relation (get child layer unique field values)
if (isChild && has_values) {
current_values = relations[layerId][field.name];
}
//get current stored unique values for field
const current_values = service.state.uniqueFieldsValues[layerId][field.name] || new Set([]);

// root layer --> get current values of unique field
if (!isChild || !has_values) {
current_values = (service.state.uniqueFieldsValues[layerId] || {})[field.name] || [];
//check if temporary value is not added to values
// @since 3.9.0
if (!field.input.options.values.includes(field.value)) {
field.input.options.values.push(field.value);
}
}
//NEED TO ADD ALWAYS CURRENT VALUE
field.input.options.values = (['integer', 'float', 'bigint'].includes(field.type) ? sortNumericArray: sortAlphabeticallyArray)(Array.from(current_values));

// convert "current" values to string (when not null or undefined)
current_values.forEach(v => field.validate.exclude_values.add(![null, undefined].includes(v)? `${v}` : v ) );

// convert "inputs" values to string (when not null or undefined)
inputs.features.forEach(f => {
const value = f.get(field.name);
if (![null, undefined].includes(value)) {
field.validate.exclude_values.add(`${value}`);
}
});

// remove current value from exclude_values
field.validate.exclude_values.delete(_value);
field.validate.exclude_values.delete(`${_value}`);
});

// skip when no fields are unique in multi features change form attribute
Expand All @@ -100,53 +68,17 @@ export function getFormFields({
unique_values.forEach(({ _value, field }) => {
// initial value is the same that current field vale (no changed)
if (_value === field.value) { return }
//get
const layer = isChild && service.state.uniqueFieldsValues[relationLayerId];

// relation form
if (layer) {
// change relation layer unique field values
layer.__uniqueFieldsValuesRelations = layer.__uniqueFieldsValuesRelations || {};
layer.__uniqueFieldsValuesRelations[layerId] = layer.__uniqueFieldsValuesRelations[layerId] || {};
const values = new Set(layer.__uniqueFieldsValuesRelations[layerId][field.name]);
values.delete(_value);
values.add(field.value);
layer.__uniqueFieldsValuesRelations[layerId][field.name] = values;
}

// root layer form (no relation)
if (!layer && service.state.uniqueFieldsValues[layerId] && service.state.uniqueFieldsValues[layerId][field.name]) {
// layer form
if (service.state.uniqueFieldsValues[layerId][field.name]) {
// change layer unique field values
const values = service.state.uniqueFieldsValues[layerId][field.name];
//If changed, delete it from _value
values.delete(_value);
//aff new one to value list unique field
values.add(field.value);
}

});

// Save temporary relation feature changes on father (root) layer feature
const relations = false === isChild && (
service.state.uniqueFieldsValues[layerId]
&& service.state.uniqueFieldsValues[layerId].__uniqueFieldsValuesRelations
);

// skip when no relation unique fields values is stored
if (relations) {
Object
.keys(relations)
.forEach(id => {
Object
.entries(relations[id])
.forEach(([name, values]) => {
service.state.uniqueFieldsValues[id][name] = values;
})
});
// clear temporary relations unique fields values
if (service.state.uniqueFieldsValues[layerId]) {
delete service.state.uniqueFieldsValues[layerId].__uniqueFieldsValuesRelations;
}
}

return { once: true };
};

Expand All @@ -156,10 +88,6 @@ export function getFormFields({
service.subscribe(`closeform_${layerId}`, () => {
//unsubscribe event
service.unsubscribe(`savedfeature_${layerId}`, savedfeatureFnc);
// clear temporary relations unique fields values
if (service.state.uniqueFieldsValues[layerId] && service.state.uniqueFieldsValues[layerId].__uniqueFieldsValuesRelations) {
delete service.state.uniqueFieldsValues[layerId].__uniqueFieldsValuesRelations;
}
return { once: true };
});

Expand Down
47 changes: 22 additions & 25 deletions utils/setLayerUniqueFieldValues.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const { CatalogLayersStoresRegistry } = g3wsdk.core.catalog;
* ORIGINAL SOURCE: g3w-client-plugin-editing/services/[email protected]
* Method to get unique values of unique input values from server
* It's called
* - When toolbox start
* - Open a relation from OpenFormStep
* - When toolbox start (parent layer and relation)
* - After commit to server (to get fresh new data)
*
* @param { string } layerId
*
Expand All @@ -15,29 +15,26 @@ const { CatalogLayersStoresRegistry } = g3wsdk.core.catalog;
*/
export async function setLayerUniqueFieldValues(layerId) {
const service = g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing'); //get editing service

const promises = [];
const layer = CatalogLayersStoresRegistry.getLayerById(layerId);
layer
.getEditingFields()
//filter field that is unique and not yet set unique values
.filter(field => field.validate.unique && undefined === (service.state.uniqueFieldsValues[layerId] && service.state.uniqueFieldsValues[layerId][field.name]))
.forEach((field => {
promises.push(new Promise((resolve, reject) => {
layer
.getFilterData({ unique: field.name })
.then((values = []) => {
//check if not yet create
if (undefined === service.state.uniqueFieldsValues[layerId]) {
service.state.uniqueFieldsValues[layerId] = {};
}
//set unique values for the field
service.state.uniqueFieldsValues[layerId][field.name] = new Set(values);
resolve();
await new Promise((resolve, reject) => {
const layer = g3wsdk.core.plugin.PluginsRegistry.getPlugin('editing').getLayerById(layerId);
//get all values for unique field
layer.getWidgetData({
type: 'unique',
fields: Object.values(layer
.getEditingFields()
//filter field that is unique and not yet set unique values
.filter(f => !(f.pk && false === f.editable) && ('unique' === f.input.type || f.validate.unique)))
.map(f => f.name).join()
}).then((response) => {
Object
.entries(response.data || [])
.forEach(([name, values]) => {
service.state.uniqueFieldsValues[layerId][name] = new Set(values)
})
.fail(e => { console.warn(e); reject(e); })
}))
}))
await Promise.allSettled(promises);

resolve(service.state.uniqueFieldsValues[layerId][name])
})
.fail(e => { console.warn(e); reject(e); })
})
return service.state.uniqueFieldsValues[layerId];
}

0 comments on commit 0a66d56

Please sign in to comment.