Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slim down QueryResultsService.setActionsForLayers() function #59

Closed
Raruto opened this issue Jul 12, 2022 · 1 comment · Fixed by #317
Closed

Slim down QueryResultsService.setActionsForLayers() function #59

Raruto opened this issue Jul 12, 2022 · 1 comment · Fixed by #317
Labels
refactoring Anything which could result in a API change

Comments

@Raruto
Copy link
Collaborator

Raruto commented Jul 12, 2022

The following function is nearly 250 lines long:

proto.setActionsForLayers = function(layers, options={add: false}) {
const {add} = options;
if (!add) {
this.unlistenerlayeractionevents = [];
layers.forEach(layer => {
/**
* set eventually layer action tool and need to be reactive
* @type {{}}
*/
this.state.layeractiontool[layer.id] = Vue.observable({
component: null,
config: null
});
const currentactiontoolslayer = {};
const currentationfeaturelayer = {};
layer.features.forEach((feature, index)=> {
currentactiontoolslayer[index] = null;
currentationfeaturelayer[index] = null;
});
this.state.currentactiontools[layer.id] = Vue.observable(currentactiontoolslayer);
this.state.currentactionfeaturelayer[layer.id] = Vue.observable(currentationfeaturelayer);
const is_external_layer_or_wms = layer.external || (layer.source ? layer.source.type === 'wms' : false);
if (!this.state.layersactions[layer.id]) this.state.layersactions[layer.id] = [];
/**
* An action is an object contains
* {
* id: Unique action Id => required True
download: if is action download or not => required False
class: calss fontawsome to show icon => required True,
state: need to be reactive. Used for example to toggled state of action icon => required False
hint: Tooltip text => required False
init: Method called when action is loaded => required False
clear: Method called before clear the service. Used for example to clear unwatch => require False
change: Method called when feature of layer is changed
cbk: Method called when action is cliccked => required True
}
*
* }
*/
//in case of geometry
if (layer.hasgeometry) {
this.state.layersactions[layer.id].push({
id: 'gotogeometry',
download: false,
mouseover: true,
class: GUI.getFontClass('marker'),
hint: 'sdk.mapcontrols.query.actions.zoom_to_feature.hint',
cbk: throttle(this.goToGeometry.bind(this))
});
}
// in case of relations
if (this._relations) {
const relations = this._relations[layer.id] && this._relations[layer.id].filter(relation =>{
return relation.type === 'MANY';
});
if (relations && relations.length) {
const chartRelationIds = [];
relations.forEach(relation => {
const id = this.plotLayerIds.find(id => id === relation.referencingLayer);
id && chartRelationIds.push(id);
});
this.state.layersactions[layer.id].push({
id: 'show-query-relations',
download: false,
class: GUI.getFontClass('relation'),
hint: 'sdk.mapcontrols.query.actions.relations.hint',
cbk: this.showQueryRelations,
relations,
chartRelationIds
});
const state = this.createActionState({
layer
});
chartRelationIds.length && this.state.layersactions[layer.id].push({
id: 'show-plots-relations',
download: false,
opened: true,
class: GUI.getFontClass('chart'),
state,
hint: 'sdk.mapcontrols.query.actions.relations_charts.hint',
cbk: throttle(this.showRelationsChart.bind(this, chartRelationIds))
});
}
}
/**
*
* Check if layer has atlas
*/
this.getAtlasByLayerId(layer.id).length && this.state.layersactions[layer.id].push({
id: `printatlas`,
download: true,
class: GUI.getFontClass('print'),
hint: `sdk.tooltips.atlas`,
cbk: this.printAtlas.bind(this)
});
const state = this.createActionState({
layer
});
if (layer.downloads.length === 1) {
const [format] = layer.downloads;
const cbk = this.downloadFeatures.bind(this, format);
layer[format] = Vue.observable({
active: false
});
this.state.layersactions[layer.id].push({
id: `download_${format}_feature`,
download: true,
state,
class: GUI.getFontClass('download'),
hint: `sdk.tooltips.download_${format}`,
cbk: (layer, feature, action, index)=>{
action.state.toggled[index] = !action.state.toggled[index];
if (action.state.toggled[index]) cbk(layer, feature, action, index);
else this.setCurrentActionLayerFeatureTool({
index,
action,
layer
})
}
});
} else if (layer.downloads.length > 1 ){
// SET CONSTANT TO AVOID TO CHANGE ALL THINGS
const ACTIONTOOLSDOWNLOADFORMATS = DownloadFormats.name;
const downloads = [];
layer.downloads.forEach(format => {
downloads.push({
id: `download_${format}_feature`,
download: true,
format,
class: GUI.getFontClass(format),
hint: `sdk.tooltips.download_${format}`,
cbk: (layer, feature, action, index)=> {
//used to untoggle downloads action
this.downloadFeatures(format, layer, feature, action, index);
const downloadsaction = this.state.layersactions[layer.id].find(action => action.id === 'downloads');
if (this.state.query.type !== 'polygon') downloadsaction.cbk(layer, feature, downloadsaction, index);
}
});
});
this.state.actiontools[ACTIONTOOLSDOWNLOADFORMATS] = this.state.actiontools[ACTIONTOOLSDOWNLOADFORMATS] || {};
// set config of actionstools
this.state.actiontools[ACTIONTOOLSDOWNLOADFORMATS][layer.id] = {
downloads // ARE DOWNLOAD ACTIONS,
};
// used to
//check if has download actions
this.state.layersactions[layer.id].push({
id: `downloads`,
download: true,
class: GUI.getFontClass('download'),
state,
toggleable: true,
hint: `Downloads`,
change({features}) {
features.forEach((feature, index) =>{
if (this.state.toggled[index] === undefined) VM.$set(this.state.toggled, index, false);
else this.state.toggled[index] = false;
});
},
cbk: (layer, feature, action, index) => {
action.state.toggled[index] = !action.state.toggled[index];
this.setCurrentActionLayerFeatureTool({
layer,
index,
action,
component: action.state.toggled[index] ? DownloadFormats : null
});
}
});
}
/*
Check if si external layer or wms
*/
!is_external_layer_or_wms && this.state.layersactions[layer.id].push({
id: 'removefeaturefromresult',
download: false,
mouseover: true,
class: GUI.getFontClass('minus-square'),
style: {
color: 'red'
},
hint: 'sdk.mapcontrols.query.actions.remove_feature_from_results.hint',
cbk: this.removeFeatureLayerFromResult.bind(this)
});
/**
* check if selection is active
*/
if (layer.selection.active !== undefined) {
// selection action
const state = this.createActionState({
layer
});
this.state.layersactions[layer.id].push({
id: 'selection',
download: false,
class: GUI.getFontClass('success'),
hint: 'sdk.mapcontrols.query.actions.add_selection.hint',
state,
init: ({feature, index, action}={})=>{
layer.selection.active !== void 0 && this.checkFeatureSelection({
layerId: layer.id,
index,
feature,
action
})
},
cbk: throttle(this.addToSelection.bind(this))
});
this.listenClearSelection(layer, 'selection');
//end selection action
}
/*
If not wms of external layer show copy link to feature
*/
!is_external_layer_or_wms && layer.hasgeometry && this.state.layersactions[layer.id].push({
id: 'link_zoom_to_fid',
download: false,
class: GUI.getFontClass('link'),
hint: 'sdk.mapcontrols.query.actions.copy_zoom_to_fid_url.hint',
hint_change: {
hint: 'sdk.mapcontrols.query.actions.copy_zoom_to_fid_url.hint_change',
duration: 1000
},
cbk: this.copyZoomToFidUrl.bind(this)
});
layer.editable && this.state.layersactions[layer.id].push({
id: 'editing',
class: GUI.getFontClass('pencil'),
hint: 'Editing',
cbk: (layer, feature) => {
const layerId = layer.id;
const featureId = feature.attributes[G3W_FID];
feature.geometry && this.mapService.zoomToGeometry(feature.geometry);
setTimeout(()=>{
this.editFeature({
layerId,
featureId
});
}, 300)
}
});
});
this.addActionsForLayers(this.state.layersactions, this.state.layers);
}
};

If possible, consider simplifying it by using subroutines.

@volterra79
Copy link
Member

@Raruto agree

@Raruto Raruto added the refactoring Anything which could result in a API change label Aug 5, 2022
Raruto added a commit that referenced this issue Mar 28, 2023
Raruto added a commit that referenced this issue Aug 25, 2023
* refactor `src/app/gui/queryresults/queryresultsservice.js`

- add FIXME comments (eg. please "add function description")
- code cleanup (eg. tons of weird ternary conditions, short-circuiting logic and missing brackets!)
- full function rewrite `QueryResultsService::updateLayerResultFeatures(layer)`
- notable function rewrite `QueryResultsService::_digestFeaturesForLayers (featuresForLayers)`

* Fix misspelling and properties position declaration

* Add comments

* Closes #59

* wrong parameter

* add geometry check within `QueryResultsService::showGeometry(geometry)`

* extract function `QueryResultsService::_handleFeatureForLayer(featuresForLayer)`

* remove undefined action `QueryResultsService.zoomToElement`

* clean up some code

* convert `QueryResultsService` to ES6 class

* update @SInCE tags

* update @param tag

* 🐛 Fix bugs due refactoring

* wrong merge

* 🐛 Fix undefined check and change layer.selection.features to empty array instead empty object

* code readability

- slim down function  `updateLayerResultFeatures()`
- alias long variable name `this._addFeaturesLayerResultInteraction`
- slim down function `downloadFeatures()`
- extract function `_handleExternalVectorLayerSelection()`
- extract function `_handleProjectLayerSelection()`

* 🐛 Ensure that find array method return undefined (not found). Add extenal parameter into _getFeaturesIds

* slim down `unRegisterCustomComponent`

* 🐛 Fix add feature to a external layer. fix add settimeout to querycontrol

* code readability

- slim down comments
- alias long variable name `this.state.currentactiontools`
- alias long variable name `this.state.currentactionfeaturelayer`
- alias long variable name ` this.state.layersFeaturesBoxes`
- extract function `_clearActions`
- alias prototype function `QueryResultsService.init`
- alias prototype function `QueryResultsService.reset`

* refactor function `QueryControl.setMap()`

* refactor `_handleFeatureForLayer`

* ♻️ Set right event 'picked' on queryControl

* comments

* 🐛 Fix setCurrentActionLayerFeatureTool

* Check and correct some refactoring code

* ✨ Create common downloadApplicationWrapper to run download

* ♻️ Move downloadApplicationWrapper from queryresultsservice.js to index.prod.js as GUI method

* move application wrapper

* extract `_hasLayerObjGeometry` and `_parseLayerObjFeatures`

* params destrcuturing: `featuresForLayer`

* simplify condition

* refactor `setQueryResponse`

- remove function
 `_digestFeaturesForLayers()`
- rename function
 `_handleFeatureForLayer()` into `_responseToLayer()`
- extract function `_hasLayerObjGeometry()`
- extract function `_hasLayerObjImageField()`
- refactor function `_parseLayerObjFormStructure()`

* alias `_changeLayerResult`

* remove `_orderResponseByProjectLayers`

* apply some fixme and todos

- remove nested if-else in: `getVectorLayerFeaturesFromQueryRequest()`
- incorporate function `_addVectorLayersDataToQueryResponse()` into `*/
  setQueryResponse()` setter
- simplify destructuring assignment within `_printSingleAtlas()` function
- remove function `_addComponent()`

* wrong variable reference

* wrong variable name

* 🐛 Fix case when click to add feature to layer result and no current mapcontrol is active (undefined). Need to be set null to align default value and evaluation.

* `console.warn`

* wrong comments

* 🐛 In case of no features for a specific layer, return undefind, so layer is not add to query results state layers array

* simplify conditions

* 🐛 Need to refer to instance and not to "class"

* 🐛 Handle selection feature action when add new feature to layer result

* 🐛 Add custom drawpolygon type for query by drw polygon otherwise it conflict to download action to get all attributes of polygon query (query by polygon)

* 🐛 fix download action

* boolean logic

---------

Co-authored-by: volterra79 <boccacci.francesco@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
refactoring Anything which could result in a API change
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants