" Ex. "EPSG:4326"
49 | *
50 | * @returns { Promise }
51 | *
52 | * @since v3.8
53 | */
54 | async registerProjection(epsg) {
55 | let p = ol.proj.get(epsg) || undefined;
56 |
57 | // check if already registered
58 | if (!p) {
59 | const { result, data } = await (await fetch(`/crs/${epsg.split(':')[1]}/`)).json();
60 | if (result) {
61 | data.epsg = normalizeEpsg(data.epsg);
62 | p = this.get(data);
63 | ol.proj.proj4.register(proj4);
64 | return p;
65 | }
66 | }
67 |
68 | return p;
69 | }
70 | };
--------------------------------------------------------------------------------
/src/utils/areCoordinatesEqual.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param { Array } coordinates1
3 | * @param { Array } coordinates2
4 | *
5 | * @returns { boolean }
6 | */
7 | export function areCoordinatesEqual(coordinates1 = [], coordinates2 = []) {
8 | return (coordinates1[0] === coordinates2[0] && coordinates1[1] === coordinates2[1]);
9 | }
--------------------------------------------------------------------------------
/src/utils/base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Based on google closure library implementation
3 | */
4 | export function base(target) {
5 |
6 | console.warn('[G3W-CLIENT] g3wsdk.core.utils.base is deprecated');
7 | console.trace();
8 |
9 | // reference to previous function (caller)
10 | const caller = arguments.callee.caller;
11 |
12 | // call superclass constructor (that inherits from superClass_)
13 | if (caller.superClass_) {
14 | if ('Function' === caller.superClass_.constructor.name) {
15 | return caller.superClass_.constructor.apply(target, Array.prototype.slice.call(arguments, 1));
16 | }
17 | return Object.assign(
18 | target,
19 | Reflect.construct(caller.superClass_.constructor, Array.prototype.slice.call(arguments, 1), target.constructor)
20 | );
21 | }
22 |
23 | let foundCaller = false;
24 |
25 | // traverse prototype chain
26 | for (let ctor = target.constructor; ctor; ctor = ctor.superClass_?.constructor) {
27 | if (ctor.prototype[arguments[1]] === caller) {
28 | foundCaller = true;
29 | } else if (foundCaller) {
30 | return ctor.prototype[arguments[1]].apply(target, Array.prototype.slice.call(arguments, 2));
31 | }
32 | }
33 |
34 | // caller is an instance method
35 | if (target[arguments[1]] === caller) {
36 | return target.constructor.prototype[arguments[1]].apply(target, Array.prototype.slice.call(arguments, 2));
37 | }
38 |
39 | // method was called by wrong caller
40 | throw Error('base called from a method of one name to a method of a different name');
41 | }
--------------------------------------------------------------------------------
/src/utils/convertQGISDateTimeFormatToMoment.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Covert datetime format from Qgis format to Moment
3 | *
4 | * @param datetimeformat
5 | *
6 | * @returns {*}
7 | */
8 | export function convertQGISDateTimeFormatToMoment(datetimeformat) {
9 | datetimeformat = datetimeformat.replace(/y/g, 'Y');
10 | const matchDayInDate = datetimeformat.match(/d/g);
11 | if (matchDayInDate && matchDayInDate.length < 3) { datetimeformat = datetimeformat.replace(/d/g, 'D') }
12 | return datetimeformat
13 | }
--------------------------------------------------------------------------------
/src/utils/convertSingleMultiGeometry.js:
--------------------------------------------------------------------------------
1 | import { GEOMETRY_TYPES } from 'g3w-constants';
2 | import { isMultiGeometry } from 'utils/isMultiGeometry';
3 |
4 | /**
5 | * Convert geometry to geometryType (from Single to Multi or viceversa)
6 | *
7 | * @param { ol.geom } geometry current OL geometry
8 | * @param { string } toGeometryType
9 | */
10 | export function convertSingleMultiGeometry(geometry, toGeometryType) {
11 | const from_type = geometry.getType();
12 |
13 | if (!toGeometryType || toGeometryType === from_type) {
14 | return geometry;
15 | }
16 |
17 | const from_multi = isMultiGeometry(from_type);
18 | const to_multi = isMultiGeometry(toGeometryType);
19 |
20 | if (from_multi && !to_multi) {
21 | switch (geometry.getType()) {
22 | case GEOMETRY_TYPES.MULTIPOLYGON: return geometry.getPolygons();
23 | case GEOMETRY_TYPES.MULTILINE: return geometry.getLineStrings();
24 | case GEOMETRY_TYPES.MULTILINESTRING: return geometry.getLineStrings();
25 | case GEOMETRY_TYPES.MULTIPOINT: return geometry.getPoints();
26 | default: console.warn('invalid geometry type', geometry.getType());
27 | }
28 | return [];
29 | }
30 |
31 | if (!from_multi && to_multi) {
32 | return new ol.geom[`Multi${from_type}`]([geometry.getCoordinates()]);
33 | }
34 |
35 | return geometry;
36 | }
--------------------------------------------------------------------------------
/src/utils/copyUrl.js:
--------------------------------------------------------------------------------
1 | export function copyUrl(url) {
2 | const tempinput = document.createElement('input');
3 | document.body.appendChild(tempinput);
4 | tempinput.value = url;
5 | tempinput.select();
6 | document.execCommand('copy');
7 | document.body.removeChild(tempinput);
8 | };
--------------------------------------------------------------------------------
/src/utils/createFilterFormInputs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param layer single layer or an array of layers
3 | * @param inputs
4 | *
5 | * @returns {*}
6 | */
7 | export function createFilterFormInputs({
8 | layer,
9 | inputs = [],
10 | }) {
11 | const filter = inputs.map((input, i) => Array.isArray(input.attribute)
12 | // multi key relation fields
13 | ? input.attribute.map((attr, j) => [].concat(input.value[j]).map(v => `${attr}|${(input.operator || 'eq').toLowerCase()}|${encodeURIComponent(v)}`).join(`|null,`)).join('|AND,')
14 | // input logic operator
15 | : `${i > 0 ? `|${inputs[i-1].logicop},` : ''}${'in' === input.operator
16 | ? `${input.attribute}|${input.operator}|(${[].concat(input.value).map(v => encodeURIComponent(v)).join(',')})`
17 | : [].concat(input.value).map(v => `${input.attribute}|${(input.operator || 'eq').toLowerCase()}|${encodeURIComponent(v)}`).join(`|${undefined !== input.logicop ? input.logicop : 'OR'},`)}`
18 | ).join('') || undefined;
19 |
20 | // check if is a single layer of an array of layers
21 | return Array.isArray(layer) ? layer.map(() => filter) : filter;
22 | }
--------------------------------------------------------------------------------
/src/utils/createFilterFromString.js:
--------------------------------------------------------------------------------
1 | import { FILTER_EXPRESSION_OPERATORS } from 'g3w-constants';
2 |
3 | const operators = Object.entries(FILTER_EXPRESSION_OPERATORS);
4 |
5 | export function createFilterFromString({ filter = '' }) {
6 | filter = operators
7 | .reduce((acc, [_, op]) => acc
8 | .replace(new RegExp(`\\s+${op}\\s+`, 'g'), `${op}`) // remove all blank space between operators
9 | .replace(new RegExp(`'${op}`, 'g'), `${op}`) // leading single quote
10 | .replace(new RegExp(`${op}'`, 'g'), `${op}`) // trailing single quote
11 | , filter)
12 | .replace(/'$/g, '')
13 | .replace(/"/g, '');
14 | filter = operators
15 | .reduce((acc, [k, op]) => acc.replace(new RegExp(op, 'g'), ['AND', 'OR'].includes(op) ? `|${k},` : `|${k}|`), filter)
16 | // encode value
17 | .split('|')
18 | .map((v, i) => (0 === (i+1) % 3) ? encodeURIComponent(v) : v)
19 | .join('|');
20 |
21 | return filter;
22 | }
--------------------------------------------------------------------------------
/src/utils/createRelationsUrl.js:
--------------------------------------------------------------------------------
1 | import ApplicationState from 'store/application'
2 | import { sanitizeFidFeature } from 'utils/sanitizeFidFeature';
3 |
4 | /**
5 | * ORIGINAL SOURCE: src/services/relations.js@v3.10.2
6 | */
7 | export function createRelationsUrl({
8 | layer = {},
9 | relation = {},
10 | fid,
11 | type = 'data', //
12 | }) {
13 | return `${ApplicationState.project.getLayerById(
14 | undefined === relation.father
15 | ? (layer.id === relation.referencedLayer ? relation.referencingLayer : relation.referencedLayer)
16 | : (layer.id === relation.father ? relation.child : relation.father)
17 | ).getUrl(type)}?relationonetomany=${relation.id}|${sanitizeFidFeature(fid)}`;
18 | }
--------------------------------------------------------------------------------
/src/utils/createSelectedStyle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param { Object } style
3 | * @param style.geometryType
4 | * @param style.color
5 | * @param style.fill
6 | *
7 | * @returns { ol.style.Style | null } style
8 | */
9 | export function createSelectedStyle({
10 | geometryType,
11 | color = 'rgb(255,255,0)',
12 | fill = true,
13 | } = {}) {
14 | switch(geometryType) {
15 |
16 | case 'LineString':
17 | case 'MultiLineString':
18 | return new ol.style.Style({
19 | stroke: new ol.style.Stroke({ color, width: 4 })
20 | });
21 |
22 | case 'Point':
23 | case 'MultiPoint':
24 | return new ol.style.Style({
25 | image: new ol.style.Circle({
26 | radius: 6,
27 | fill: fill && new ol.style.Fill({ color }),
28 | stroke: !fill && new ol.style.Stroke({ color, width: 4 }),
29 | }),
30 | zIndex: Infinity,
31 | });
32 |
33 | case 'MultiPolygon':
34 | case 'Polygon':
35 | return new ol.style.Style({
36 | stroke: new ol.style.Stroke({ color, width: 4 }),
37 | fill: fill && new ol.style.Fill({ color: ol.color.asString([...ol.color.asArray(color)].splice(0, 3).concat(.25)) }) // force rgba color transparency (alpha = .25)
38 | });
39 |
40 | default:
41 | console.warn('invalid geometry type', geometryType);
42 | return null;
43 |
44 | }
45 | }
--------------------------------------------------------------------------------
/src/utils/debounce.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * build debounce function
4 | */
5 | export function debounce(func, delay = 500) {
6 | let timeout;
7 | return function (...args) {
8 | clearTimeout(timeout);
9 | timeout = setTimeout(() => func(...args), delay);
10 | };
11 | }
--------------------------------------------------------------------------------
/src/utils/dissolve.js:
--------------------------------------------------------------------------------
1 | import 'jsts/dist/jsts.min.js';
2 |
3 | /**
4 | *
5 | * @param { Object } opts
6 | * @param { Array } opts.features
7 | * @param { number } opts.index
8 | * @param { boolean } opts.clone
9 | *
10 | * @returns dissolved feature
11 | */
12 | export function dissolve({
13 | features = [],
14 | index = 0,
15 | clone = false,
16 | } = {}) {
17 |
18 | const parser = new jsts.io.OL3Parser();
19 | const featuresLength = features.length;
20 |
21 |
22 | /** In case no features to dissolve */
23 | if (0 === featuresLength) {
24 | return null;
25 | }
26 |
27 | /** In the case of single feature, return feature */
28 | if (1 === featuresLength) {
29 | return features[0];
30 | }
31 |
32 | let jstsdissolvedFeatureGeometry;
33 |
34 | const baseFeature = clone ? features[index].clone() : features[index];
35 | const baseFeatureGeometry = baseFeature.getGeometry();
36 | const baseFeatureGeometryType = baseFeatureGeometry.getType();
37 |
38 | // check if it can build a LineString
39 | if ('LineString' === baseFeatureGeometryType) {
40 | const lineMerger = new jsts.operation.linemerge.LineMerger();
41 | for (let i = 0; i < featuresLength; i++) {
42 | lineMerger.addLineString(
43 | new jsts.geom.GeometryFactory().createLineString(parser.read(features[i].getGeometry()).getCoordinates())
44 | );
45 | }
46 | const mergedLineString = lineMerger.getMergedLineStrings();
47 | jstsdissolvedFeatureGeometry = 1 === mergedLineString.size() ? mergedLineString.toArray()[0] : null;
48 | }
49 |
50 | if ('LineString' !== baseFeatureGeometryType) {
51 | jstsdissolvedFeatureGeometry = parser.read(baseFeatureGeometry);
52 | for (let i = 0; i < featuresLength ; i++) {
53 | if (index !== i) {
54 | jstsdissolvedFeatureGeometry = jstsdissolvedFeatureGeometry.union(parser.read(features[i].getGeometry()))
55 | }
56 | }
57 | }
58 |
59 | /** In case of no dissolved geometry */
60 | if (!jstsdissolvedFeatureGeometry) {
61 | return null;
62 | }
63 |
64 | const dissolvedFeatureGeometry = parser.write(jstsdissolvedFeatureGeometry);
65 | const dissolvedFeatureGeometryType = dissolvedFeatureGeometry.getType();
66 | const dissolvedFeatureGeometryCoordinates = dissolvedFeatureGeometryType === baseFeatureGeometryType
67 | ? dissolvedFeatureGeometry.getCoordinates()
68 | : -1 !== baseFeatureGeometryType.indexOf('Multi') && dissolvedFeatureGeometryType === baseFeatureGeometryType.replace('Multi', '')
69 | ? [dissolvedFeatureGeometry.getCoordinates()]
70 | : null;
71 |
72 | /** In the case of null feature dissolved coordinates */
73 | if (null === dissolvedFeatureGeometryCoordinates) {
74 | return null;
75 | }
76 |
77 | baseFeature.getGeometry().setCoordinates(dissolvedFeatureGeometryCoordinates);
78 |
79 | return baseFeature;
80 | }
--------------------------------------------------------------------------------
/src/utils/distance.js:
--------------------------------------------------------------------------------
1 | /**
2 | * core/geometry/geom::distance@v3.4
3 | * core/geometry/geom::squaredDistance@v3.4
4 | */
5 | export function distance(c1, c2) {
6 | return Math.sqrt(
7 | Math.pow(c2[0] - c1[0], 2) +
8 | Math.pow(c2[1] - c1[1], 2)
9 | );
10 | }
--------------------------------------------------------------------------------
/src/utils/flattenObject.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ORIGINAL SOURCE: https://stackoverflow.com/a/56253298
3 | *
4 | * @example
5 | *
6 | * ### Sample Input
7 | *
8 | * ```
9 | * const obj = {
10 | * name: "test",
11 | * address: {
12 | * personal: "abc",
13 | * office: {
14 | * building: 'random',
15 | * street: 'some street'
16 | * }
17 | * }
18 | * }
19 | * ```
20 | *
21 | * ### Expected Output
22 | *
23 | * ```
24 | * {
25 | * name : "test",
26 | * address_personal: "abc"
27 | * address_office_building: "random"
28 | * address_office_street: "some street"
29 | * }
30 | * ```
31 | *
32 | * @since 3.9.0
33 | */
34 | export function flattenObject(obj, parent, res = {}) {
35 | for (let key in obj) {
36 | let propName = parent ? parent + '_' + key : key;
37 | if ('object' === typeof obj[key]) {
38 | flattenObject(obj[key], propName, res);
39 | } else {
40 | res[propName] = obj[key];
41 | }
42 | }
43 | return res;
44 | }
--------------------------------------------------------------------------------
/src/utils/getAlphanumericPropertiesFromFeature.js:
--------------------------------------------------------------------------------
1 | import { GEOMETRY_FIELDS } from 'g3w-constants';
2 |
3 | /**
4 | * @param { Array } properties
5 | *
6 | * @returns { Array }
7 | */
8 | export function getAlphanumericPropertiesFromFeature(properties = []) {
9 | return (Array.isArray(properties) ? properties : Object.keys(properties)).filter(p => !GEOMETRY_FIELDS.includes(p));
10 | }
--------------------------------------------------------------------------------
/src/utils/getCatalogLayerById.js:
--------------------------------------------------------------------------------
1 | import ApplicationState from 'store/application';
2 |
3 | /**
4 | * ORIGINAL SOURCE: src/app/core/layers/layersstoreregistry.js@v3.10.2
5 | */
6 | export function getCatalogLayerById(id) {
7 | return Object.values(ApplicationState.catalog).map(s => s.getLayerById(id)).find(l => l);
8 | }
--------------------------------------------------------------------------------
/src/utils/getCatalogLayers.js:
--------------------------------------------------------------------------------
1 | import ApplicationState from 'store/application';
2 |
3 | /**
4 | * ORIGINAL SOURCE: src/app/core/layers/layersstoreregistry.js@v3.10.2
5 | */
6 | export function getCatalogLayers(filter, options = {}) {
7 | return Object.values(ApplicationState.catalog).flatMap(s => s.getLayers(filter, options));
8 | }
--------------------------------------------------------------------------------
/src/utils/getDataForSearchInput.js:
--------------------------------------------------------------------------------
1 | import { SEARCH_ALLVALUE } from 'g3w-constants';
2 |
3 | /**
4 | * @returns { Array } of unique values from field
5 | */
6 | export async function getDataForSearchInput({ state, field, filter, suggest }) {
7 |
8 | try {
9 | // get unique value from each layers
10 | return (
11 | await Promise.allSettled(state.search_layers.map(l => l.getFilterData({
12 | suggest,
13 | fformatter: field,
14 | ordering: field,
15 | field: filter || getDataForSearchInput.field({
16 | state,
17 | //in the case of suggested parameter set (case autocomplete field), need to use current field
18 | field: suggest ? field : (state.forminputs.find(i => field === i.attribute) || {}).dependance || field,
19 | fields: []
20 | }),
21 | })))
22 | )
23 | .filter(d => 'fulfilled' === d.status)
24 | .reduce((acc, d, i) => 0 === i
25 | ? acc.concat(d.value.data || []) // for first layer get all uninques values
26 | : [...new Set([...(d.value.data || []), ...acc].map(JSON.stringify))].map(JSON.parse), // ensure uniques values (search performed on multiple serach_layers)
27 | []
28 | )
29 | .map(([value, key]) => ({ key, value }));
30 |
31 | } catch(e) { console.warn(e); }
32 |
33 | return [];
34 | }
35 |
36 | /**
37 | * Traverse field dependecies
38 | */
39 | getDataForSearchInput.field = ({ state, field, fields = [] } = {}) => {
40 | field = state.forminputs.find(i => i.attribute === field); // current input
41 | const parent = state.forminputs.find(i => i.attribute === field.dependance); // current input dependance (parent field)
42 | // get all values (un-filtered)
43 | if (!parent || [].concat(parent.value).find(v => v === SEARCH_ALLVALUE)) {
44 | return (fields || []).join() || undefined;
45 | }
46 |
47 | // filter by parent field
48 | if (undefined !== parent.value) {
49 | //Take in account in operator (array values)
50 | fields.unshift(`${parent.attribute}|${parent.operator.toLowerCase()}|${'in' === parent.operator ? `(${[].concat(parent.value).map(v => encodeURIComponent(v)).join(',')})` : `${encodeURIComponent(parent.value)}`}` + (fields.length ? `|${parent.logicop}` : ''));
51 | }
52 |
53 | // recursion step
54 | return getDataForSearchInput.field({ state, fields, field: parent.attribute });
55 | }
--------------------------------------------------------------------------------
/src/utils/getDefaultExpression.js:
--------------------------------------------------------------------------------
1 | import DataRouterService from 'services/data';
2 |
3 | /**
4 | * ORIGINAL SOURCE: src/app/core/expression/inputservice.js@3.8.6
5 | *
6 | * @param expr.field related field
7 | * @param expr.feature feature to transform in form_data
8 | * @param expr.qgs_layer_id layer id owner of the feature data
9 | * @param expr.parentData
10 | *
11 | * @returns { void | Promise }
12 | *
13 | * @since 3.9.0
14 | */
15 | export async function getDefaultExpression({
16 | field,
17 | feature,
18 | qgs_layer_id,
19 | parentData,
20 | } = {}) {
21 |
22 | const {
23 | layer_id = qgs_layer_id,
24 | default_expression,
25 | loading,
26 | default: default_value,
27 | } = field.input.options;
28 |
29 | /**
30 | * @FIXME should return Promise.reject('some error message') ?
31 | */
32 | if (!default_expression) {
33 | return;
34 | }
35 |
36 | loading.state = 'loading';
37 |
38 | // Call `expression:expression_eval` to get value from expression and set it to field
39 | try {
40 |
41 | const value = await DataRouterService.getData('expression:expression_eval', {
42 | inputs: {
43 | field_name: field.name,
44 | layer_id, //
45 | qgs_layer_id, //layer id owner of the data
46 | form_data: (new ol.format.GeoJSON()).writeFeatureObject(feature),
47 | formatter: 0,
48 | expression: default_expression.expression,
49 | parent: parentData && {
50 | form_data: (new ol.format.GeoJSON()).writeFeatureObject(parentData.feature),
51 | qgs_layer_id: parentData.qgs_layer_id,
52 | formatter: 0
53 | }
54 | },
55 | outputs: false
56 | });
57 |
58 | field.value = value;
59 |
60 | return value;
61 |
62 | } catch(e) {
63 | if (undefined !== default_value) {
64 | field.value = default_value
65 | }
66 | console.warn(e);
67 | return Promise.reject(e);
68 | } finally {
69 | loading.state = 'ready';
70 | }
71 |
72 | }
--------------------------------------------------------------------------------
/src/utils/getFilterExpression.js:
--------------------------------------------------------------------------------
1 | import DataRouterService from 'services/data';
2 |
3 | /**
4 | * ORIGINAL SOURCE: src/app/core/expression/inputservice.js@3.8.6
5 | *
6 | * @param expr.field related field
7 | * @param expr.feature feature to transform in form_data
8 | * @param expr.qgs_layer_id layer id owner of the feature data
9 | * @param expr.parentData
10 | *
11 | * @returns { void | Promise }
12 | *
13 | * @since 3.9.0
14 | */
15 | export async function getFilterExpression({
16 | field,
17 | feature,
18 | qgs_layer_id,
19 | parentData,
20 | } = {}) {
21 | let {
22 | key,
23 | value,
24 | layer_id = qgs_layer_id,
25 | filter_expression,
26 | loading,
27 | orderbyvalue
28 | } = field.input.options;
29 |
30 | /**
31 | * @FIXME should return Promise.reject('some error message') ?
32 | */
33 | if (!filter_expression) {
34 | return;
35 | }
36 |
37 | loading.state = 'loading';
38 |
39 | try {
40 |
41 | const features = await DataRouterService.getData('expression:expression', {
42 | inputs: {
43 | field_name: field.name,
44 | layer_id,
45 | qgs_layer_id,
46 | form_data: (new ol.format.GeoJSON()).writeFeatureObject(feature),
47 | parent: parentData && ({
48 | form_data: (new ol.format.GeoJSON()).writeFeatureObject(parentData.feature),
49 | qgs_layer_id: parentData.qgs_layer_id,
50 | formatter: 0,
51 | }),
52 | formatter: 0,
53 | expression: filter_expression.expression,
54 | ordering: [undefined, false].includes(orderbyvalue) ? key : value, //@since 3.11.0
55 | },
56 | outputs: false,
57 | });
58 |
59 | if ('select_autocomplete' === field.input.type) {
60 | field.input.options.values = [];
61 | // temporary array to sort the keys
62 | const values = [];
63 | for (let i = 0; i < features.length; i++) {
64 | values.push({
65 | key: features[i].properties[value],
66 | value: features[i].properties[key]
67 | })
68 | }
69 |
70 | field.input.options.values = values;
71 | }
72 |
73 | return features;
74 |
75 | } catch(e) {
76 | console.warn(e);
77 | return Promise.reject(e);
78 | } finally {
79 | loading.state = 'ready';
80 | }
81 |
82 | }
--------------------------------------------------------------------------------
/src/utils/getListableProjects.js:
--------------------------------------------------------------------------------
1 | import ApplicationState from 'store/application';
2 |
3 | /** used by the following plugins: "iframe", "archiweb" */
4 | export function getListableProjects() {
5 | window.initConfig.projects
6 | return window.initConfig.projects.filter(p => {
7 | if (![null, undefined].includes(p.listable)) {
8 | return p.listable;
9 | }
10 | if (
11 | p.id === ApplicationState.project.getId() ||
12 | (window.initConfig.overviewproject && p.gid === window.initConfig.overviewproject)
13 | ) {
14 | return false;
15 | }
16 | return p;
17 | }).sort((a, b) => (a.title || '').localeCompare(b.title));
18 | }
--------------------------------------------------------------------------------
/src/utils/getMapLayersByFilter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param filter defaults `GEOLAYER: true`
3 | * @param options
4 | *
5 | * @returns { Array } map layers based on filtered properties of layer (eg. `GEOLAYER : true`)
6 | */
7 | export function getMapLayersByFilter(filter = {}, options = {}) {
8 | const { MapLayersStoresRegistry } = require('services/map').default;
9 | return MapLayersStoresRegistry
10 | .getQuerableLayersStores()
11 | .flatMap(s => s.getLayers({
12 | GEOLAYER: true,
13 | /** @TODO check if it could be used to remove the subsequent call to: `store.isQueryable()` */
14 | // QUERYABLE: true,
15 | ...(filter || {})
16 | }, options));
17 | }
--------------------------------------------------------------------------------
/src/utils/getOLGeometry.js:
--------------------------------------------------------------------------------
1 | import { GEOMETRY_TYPES } from 'g3w-constants';
2 |
3 | /**
4 | * core/geometry/geometry::getOLGeometry@v3.4
5 | */
6 | export function getOLGeometry(geometryType) {
7 |
8 | switch (geometryType) {
9 |
10 | case GEOMETRY_TYPES.LINESTRINGZ:
11 | case GEOMETRY_TYPES.LINESTRINGM:
12 | case GEOMETRY_TYPES.LINESTRINGZM:
13 | case GEOMETRY_TYPES.LINESTRING25D:
14 | case GEOMETRY_TYPES.LINE:
15 | case GEOMETRY_TYPES.LINEZ:
16 | case GEOMETRY_TYPES.LINEM:
17 | case GEOMETRY_TYPES.LINEZM:
18 | case GEOMETRY_TYPES.LINE25D:
19 | return 'LineString';
20 |
21 | case GEOMETRY_TYPES.MULTILINESTRINGZ:
22 | case GEOMETRY_TYPES.MULTILINESTRINGM:
23 | case GEOMETRY_TYPES.MULTILINESTRINGZM:
24 | case GEOMETRY_TYPES.MULTILINESTRING25D:
25 | case GEOMETRY_TYPES.MULTILINE:
26 | case GEOMETRY_TYPES.MULTILINEZ:
27 | case GEOMETRY_TYPES.MULTILINEM:
28 | case GEOMETRY_TYPES.MULTILINEZM:
29 | case GEOMETRY_TYPES.MULTILINE25D:
30 | return 'MultiLineString';
31 |
32 | case GEOMETRY_TYPES.POINT:
33 | case GEOMETRY_TYPES.POINTZ:
34 | case GEOMETRY_TYPES.POINTM:
35 | case GEOMETRY_TYPES.POINTZM:
36 | case GEOMETRY_TYPES.POINT25D:
37 | return 'Point';
38 |
39 | case GEOMETRY_TYPES.MULTIPOINT:
40 | case GEOMETRY_TYPES.MULTIPOINTZ:
41 | case GEOMETRY_TYPES.MULTIPOINTM:
42 | case GEOMETRY_TYPES.MULTIPOINTZM:
43 | case GEOMETRY_TYPES.MULTIPOINT25D:
44 | return 'MultiPoint';
45 |
46 | case GEOMETRY_TYPES.POLYGON:
47 | case GEOMETRY_TYPES.POLYGONZ:
48 | case GEOMETRY_TYPES.POLYGONM:
49 | case GEOMETRY_TYPES.POLYGONZM:
50 | case GEOMETRY_TYPES.POLYGON25D:
51 | return 'Polygon';
52 |
53 | case GEOMETRY_TYPES.MULTIPOLYGON:
54 | case GEOMETRY_TYPES.MULTIPOLYGONZ:
55 | case GEOMETRY_TYPES.MULTIPOLYGONM:
56 | case GEOMETRY_TYPES.MULTIPOLYGONZM:
57 | case GEOMETRY_TYPES.MULTIPOLYGON25D:
58 | return 'MultiPolygon';
59 |
60 | default:
61 | console.warn('invalid geometry type: ', geometryType);
62 | return geometryType;
63 | }
64 | }
--------------------------------------------------------------------------------
/src/utils/getPlugin.js:
--------------------------------------------------------------------------------
1 | import ApplicationState from 'store/application';
2 |
3 | /**
4 | * @param name
5 | *
6 | * @returns Plugin instance
7 | */
8 | export function getPlugin(name) {
9 | return ApplicationState._plugins[name];
10 | }
--------------------------------------------------------------------------------
/src/utils/getProjectConfigByGid.js:
--------------------------------------------------------------------------------
1 | /** used by the following plugins: "iframe", "archiweb" */
2 | export function getProjectConfigByGid(gid) {
3 | return window.initConfig.projects.find(p => gid === p.gid);
4 | }
--------------------------------------------------------------------------------
/src/utils/getProjectUrl.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param gid
3 | *
4 | * @returns {string}
5 | */
6 | export function getProjectUrl(gid) {
7 | const project = window.initConfig.projects.find(p => gid === p.gid);
8 | try {
9 | return `${(new URL(window.initConfig.urls.baseurl))}${project.url}`;
10 | } catch(e) {
11 | console.warn(e);
12 | return `${location.origin}${window.initConfig.urls.baseurl}${project.url}`;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/utils/getRelationLayerById.js:
--------------------------------------------------------------------------------
1 | import ApplicationState from 'store/application';
2 |
3 | /**
4 | * @since 3.11.8
5 | */
6 | export function getRelationLayerById(relationid) {
7 | return ApplicationState.project.getLayerById((ApplicationState.project.getRelationById(relationid) || {}).referencedLayer);
8 | }
9 |
--------------------------------------------------------------------------------
/src/utils/getResolutionFromScale.js:
--------------------------------------------------------------------------------
1 | import { INCHES_PER_UNIT, DOTS_PER_INCH } from 'g3w-constants';
2 |
3 | export function getResolutionFromScale(scale, units = 'm') {
4 | // just to prevent that scale is passed as 1:10000 or 0.0001
5 | return 1 / (((scale >= 1.0) ? (1.0 / scale) : scale) * INCHES_PER_UNIT[units] * DOTS_PER_INCH);
6 | }
--------------------------------------------------------------------------------
/src/utils/getScaleFromResolution.js:
--------------------------------------------------------------------------------
1 | import { INCHES_PER_UNIT, DOTS_PER_INCH } from 'g3w-constants';
2 |
3 | export function getScaleFromResolution(resolution, units = 'm') {
4 | return Math.round(resolution * INCHES_PER_UNIT[units] * DOTS_PER_INCH);
5 | }
--------------------------------------------------------------------------------
/src/utils/getUniqueDomId.js:
--------------------------------------------------------------------------------
1 | let _uid = 0;
2 |
3 | export function getUniqueDomId() {
4 | return `${++_uid}_${Date.now()}`;
5 | }
--------------------------------------------------------------------------------
/src/utils/get_legend_params.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param layer
3 | *
4 | * @returns {{ LEGEND_ON: undefined | string, LEGEND_OFF: undefined | string }}
5 | */
6 | export function get_legend_params(layer) {
7 | let LEGEND_ON, LEGEND_OFF;
8 | (layer.getCategories() || [])
9 | .forEach(({
10 | checked, // new Value
11 | _checked, // old Value
12 | ruleKey,
13 | }) => {
14 | // skip when there's no difference from original `checked` status (_checked) and current changed by toc categories (checked)
15 | if (checked === _checked) {
16 | return;
17 | }
18 | if (checked) {
19 | LEGEND_ON = (undefined === LEGEND_ON ? `${layer.getWMSLayerName()}:` : `${LEGEND_ON},`) + ruleKey;
20 | } else {
21 | LEGEND_OFF = (undefined === LEGEND_OFF ? `${layer.getWMSLayerName()}:` : `${LEGEND_OFF},`) + ruleKey;
22 | }
23 | });
24 | return {
25 | LEGEND_ON,
26 | LEGEND_OFF,
27 | };
28 | }
--------------------------------------------------------------------------------
/src/utils/groupBy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Almost the same as lodash@v4.0.0 groupBy
3 | *
4 | * @since 3.10.0
5 | */
6 | export function groupBy(array, keyFn) {
7 | return array.reduce((result, item) => {
8 | const key = keyFn(item);
9 | if (!result[key]) {
10 | result[key] = [];
11 | }
12 | result[key].push(item);
13 | return result;
14 | }, {});
15 | }
--------------------------------------------------------------------------------
/src/utils/inherit.js:
--------------------------------------------------------------------------------
1 | /**
2 | * google closure library impememtation
3 | */
4 | export function inherit(childCtor, parentCtor) {
5 | console.warn('[G3W-CLIENT] g3wsdk.core.utils.inherit is deprecated');
6 | console.trace();
7 |
8 | function tempCtor() {}
9 | tempCtor.prototype = parentCtor.prototype;
10 | childCtor.superClass_ = parentCtor.prototype;
11 | childCtor.prototype = new tempCtor();
12 | childCtor.prototype.constructor = childCtor;
13 | }
--------------------------------------------------------------------------------
/src/utils/intersects.js:
--------------------------------------------------------------------------------
1 | import 'jsts/dist/jsts.min.js';
2 |
3 | /**
4 | * @param {ol.geometry} geometry
5 | * @param {ol.geometry} geometryToCheck
6 | *
7 | * @returns {boolean} whether `geometry` interesects `geometryToCheck`
8 | *
9 | * @since 3.8.0
10 | */
11 | export function intersects(geometry, geometryToCheck) {
12 | const parser = new jsts.io.OL3Parser();
13 | parser.inject(
14 | ol.geom.Point,
15 | ol.geom.LineString,
16 | ol.geom.LinearRing,
17 | ol.geom.Polygon,
18 | ol.geom.MultiPoint,
19 | ol.geom.MultiLineString,
20 | ol.geom.MultiPolygon,
21 | );
22 | return parser.read(geometry).intersects(parser.read(geometryToCheck));
23 | }
--------------------------------------------------------------------------------
/src/utils/is3DGeometry.js:
--------------------------------------------------------------------------------
1 | import { GEOMETRY_TYPES } from 'g3w-constants';
2 |
3 | export function is3DGeometry(geometryType) {
4 | return [
5 | GEOMETRY_TYPES.POINTZ,
6 | GEOMETRY_TYPES.POINTM,
7 | GEOMETRY_TYPES.POINTZM,
8 | GEOMETRY_TYPES.POINT25D,
9 | GEOMETRY_TYPES.MULTIPOINTZ,
10 | GEOMETRY_TYPES.MULTIPOINTM,
11 | GEOMETRY_TYPES.MULTIPOINTZM,
12 | GEOMETRY_TYPES.MULTIPOINT25D,
13 | GEOMETRY_TYPES.LINESTRINGZ,
14 | GEOMETRY_TYPES.LINESTRINGM,
15 | GEOMETRY_TYPES.LINESTRINGZM,
16 | GEOMETRY_TYPES.LINESTRING25D,
17 | GEOMETRY_TYPES.MULTILINESTRINGZ,
18 | GEOMETRY_TYPES.MULTILINESTRINGM,
19 | GEOMETRY_TYPES.MULTILINESTRINGZM,
20 | GEOMETRY_TYPES.MULTILINESTRING25D,
21 | GEOMETRY_TYPES.LINEZ,
22 | GEOMETRY_TYPES.LINEM,
23 | GEOMETRY_TYPES.LINEZM,
24 | GEOMETRY_TYPES.LINE25D,
25 | GEOMETRY_TYPES.MULTILINEZ,
26 | GEOMETRY_TYPES.MULTILINEM,
27 | GEOMETRY_TYPES.MULTILINEZM,
28 | GEOMETRY_TYPES.MULTILINE25D,
29 | GEOMETRY_TYPES.POLYGONZ,
30 | GEOMETRY_TYPES.POLYGONM,
31 | GEOMETRY_TYPES.POLYGONZM,
32 | GEOMETRY_TYPES.POLYGON25D,
33 | GEOMETRY_TYPES.MULTIPOLYGONZ,
34 | GEOMETRY_TYPES.MULTIPOLYGONM,
35 | GEOMETRY_TYPES.MULTIPOLYGONZM,
36 | GEOMETRY_TYPES.MULTIPOLYGON25D
37 | ].find(type3D => type3D === geometryType);
38 | }
--------------------------------------------------------------------------------
/src/utils/isLineGeometryType.js:
--------------------------------------------------------------------------------
1 | import { GEOMETRY_TYPES } from 'g3w-constants';
2 |
3 | /**
4 | * core/geometry/geometry::isLineGeometryType@v3.4
5 | * core/geometry/geometry::getAllLineGeometryTypes@v3.4
6 | */
7 | export function isLineGeometryType(geometryType) {
8 | return [
9 | GEOMETRY_TYPES.LINESTRING,
10 | GEOMETRY_TYPES.LINESTRINGZ,
11 | GEOMETRY_TYPES.LINESTRINGM,
12 | GEOMETRY_TYPES.LINESTRINGZM,
13 | GEOMETRY_TYPES.LINESTRING25D,
14 | GEOMETRY_TYPES.MULTILINESTRING,
15 | GEOMETRY_TYPES.MULTILINESTRINGZ,
16 | GEOMETRY_TYPES.MULTILINESTRINGM,
17 | GEOMETRY_TYPES.MULTILINESTRINGZM,
18 | GEOMETRY_TYPES.MULTILINESTRING25D,
19 | GEOMETRY_TYPES.LINE,
20 | GEOMETRY_TYPES.LINEZ,
21 | GEOMETRY_TYPES.LINEM,
22 | GEOMETRY_TYPES.LINEZM,
23 | GEOMETRY_TYPES.LINE25D,
24 | GEOMETRY_TYPES.MULTILINE,
25 | GEOMETRY_TYPES.MULTILINEZ,
26 | GEOMETRY_TYPES.MULTILINEM,
27 | GEOMETRY_TYPES.MULTILINEZM,
28 | GEOMETRY_TYPES.MULTILINE25D,
29 | ].includes(geometryType);
30 | }
--------------------------------------------------------------------------------
/src/utils/isMultiGeometry.js:
--------------------------------------------------------------------------------
1 | import { GEOMETRY_TYPES } from 'g3w-constants';
2 |
3 | /**
4 | * core/geometry/geometry::isMultiGeometry@v3.4
5 | */
6 | export function isMultiGeometry(geometryType) {
7 | return [
8 | GEOMETRY_TYPES.MULTIPOINT,
9 | GEOMETRY_TYPES.MULTIPOINTZ,
10 | GEOMETRY_TYPES.MULTIPOINTZM,
11 | GEOMETRY_TYPES.MULTIPOINTM,
12 | GEOMETRY_TYPES.MULTIPOINT25D,
13 | GEOMETRY_TYPES.MULTILINESTRING,
14 | GEOMETRY_TYPES.MULTILINESTRINGZ,
15 | GEOMETRY_TYPES.MULTILINESTRINGM,
16 | GEOMETRY_TYPES.MULTILINESTRINGZM,
17 | GEOMETRY_TYPES.MULTILINESTRING25D,
18 | GEOMETRY_TYPES.MULTILINE,
19 | GEOMETRY_TYPES.MULTILINEZ,
20 | GEOMETRY_TYPES.MULTILINEM,
21 | GEOMETRY_TYPES.MULTILINEZM,
22 | GEOMETRY_TYPES.MULTILINE25D,
23 | GEOMETRY_TYPES.MULTIPOLYGON,
24 | GEOMETRY_TYPES.MULTIPOLYGONZ,
25 | GEOMETRY_TYPES.MULTIPOLYGONM,
26 | GEOMETRY_TYPES.MULTIPOLYGONZM,
27 | GEOMETRY_TYPES.MULTIPOLYGON25D,
28 | ].includes(geometryType);
29 | }
--------------------------------------------------------------------------------
/src/utils/isPointGeometryType.js:
--------------------------------------------------------------------------------
1 | import { GEOMETRY_TYPES } from 'g3w-constants';
2 |
3 | /**
4 | * core/geometry/geometry::isPointGeometryType@v3.4
5 | * core/geometry/geometry::getAllPointGeometryTypes@v3.4
6 | */
7 | export function isPointGeometryType(geometryType) {
8 | return [
9 | GEOMETRY_TYPES.POINT,
10 | GEOMETRY_TYPES.POINTZ,
11 | GEOMETRY_TYPES.POINTM,
12 | GEOMETRY_TYPES.POINTZM,
13 | GEOMETRY_TYPES.POINT25D,
14 | GEOMETRY_TYPES.MULTIPOINT,
15 | GEOMETRY_TYPES.MULTIPOINTZ,
16 | GEOMETRY_TYPES.MULTIPOINTM,
17 | GEOMETRY_TYPES.MULTIPOINTZM,
18 | GEOMETRY_TYPES.MULTIPOINT25D,
19 | ].includes(geometryType);
20 | }
--------------------------------------------------------------------------------
/src/utils/isPolygonGeometryType.js:
--------------------------------------------------------------------------------
1 | import { GEOMETRY_TYPES } from 'g3w-constants';
2 |
3 | /**
4 | * core/geometry/geometry::isPolygonGeometryType@v3.4
5 | * core/geometry/geometry::getAllPolygonGeometryTypes@v3.4
6 | */
7 | export function isPolygonGeometryType(geometryType) {
8 | return [
9 | GEOMETRY_TYPES.POLYGON,
10 | GEOMETRY_TYPES.POLYGONZ,
11 | GEOMETRY_TYPES.POLYGONM,
12 | GEOMETRY_TYPES.POLYGONZM,
13 | GEOMETRY_TYPES.POLYGON25D,
14 | GEOMETRY_TYPES.MULTIPOLYGON,
15 | GEOMETRY_TYPES.MULTIPOLYGONZ,
16 | GEOMETRY_TYPES.MULTIPOLYGONM,
17 | GEOMETRY_TYPES.MULTIPOLYGONZM,
18 | GEOMETRY_TYPES.MULTIPOLYGON25D,
19 | ].includes(geometryType);
20 | }
--------------------------------------------------------------------------------
/src/utils/noop.js:
--------------------------------------------------------------------------------
1 | export function noop() {}
--------------------------------------------------------------------------------
/src/utils/normalizeEpsg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param { number | string } epsg
3 | *
4 | * @returns { string | undefined }
5 | */
6 | export function normalizeEpsg(epsg) {
7 | if ('number' === typeof epsg) {
8 | return `EPSG:${epsg}`;
9 | }
10 | epsg = epsg.replace(/[^\d\.\-]/g, "");
11 | if ('' !== epsg) {
12 | return `EPSG:${parseInt(epsg)}`;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/utils/promisify.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Migrate your consumer code away from jQuery promises.
3 | * Covert a jQuery promise into an ES6 Promise
4 | *
5 | * @param promise jquery promise
6 | */
7 | export function promisify(promise) {
8 | if (promise instanceof Promise) {
9 | return promise;
10 | }
11 | if (!promise || !promise.then) {
12 | console.trace(promise);
13 | return Promise.reject('not a promise');
14 | }
15 | return new Promise((resolve, reject) => {
16 | promise.then(resolve).fail(reject);
17 | });
18 | }
19 |
20 | /**
21 | * Migrate your consumer code away from jQuery promises.
22 | * Convert ES6 Promise into jQuery
23 | *
24 | * @param promise async function or ES6 promise
25 | */
26 | export function $promisify(promise) {
27 | if (undefined === promise) {
28 | console.trace();
29 | return $.Deferred(d => d.reject('not a promise')).promise();
30 | }
31 | if (promise.always) {
32 | return promise;
33 | }
34 | return $.Deferred(async d => {
35 | try { d.resolve(await (promise instanceof Promise ? promise : promise())); }
36 | catch (e) { console.trace(e); d.reject(e); }
37 | }).promise();
38 | }
--------------------------------------------------------------------------------
/src/utils/prompt.js:
--------------------------------------------------------------------------------
1 | import GUI from 'services/gui';
2 | import { getUniqueDomId } from 'utils/getUniqueDomId';
3 |
4 | /**
5 | * @TODO make it simpler (native HTML dialogs, Vue SFC components, ..)
6 | *
7 | * Similar to `window.prompt`
8 | *
9 | * @since 3.9.0
10 | */
11 | export async function prompt({
12 | value,
13 | label,
14 | callback,
15 | }) {
16 |
17 | // Reactive vue object (input instance)
18 | let data = {
19 | value,
20 | id: getUniqueDomId()
21 | };
22 |
23 | let vueInput = new Vue({
24 | template: /* html */ `
25 |
26 |
27 |
34 | `,
35 | data() {
36 | return data;
37 | },
38 | });
39 |
40 | let prompt; // store dialog modal window
41 |
42 | (
43 | new Promise((resolve, reject) => {
44 | // modal window with input name
45 | prompt = GUI.showModalDialog({
46 | message: vueInput.$mount().$el,
47 | closeButton: false,
48 | buttons: {
49 | ok: { label: 'Ok', className: 'btn-success', callback: () => resolve(data.value) },
50 | cancel: { label: 'Cancel', className: 'btn-danger', callback: () => reject() },
51 | },
52 | });
53 | // conditionally disable confirm button (based on input value)
54 | const okBtn = prompt.find('button.btn-success');
55 | okBtn.prop('disabled', 0 === data.value.trim().length);
56 | vueInput.$watch('value', value => { okBtn.prop('disabled', 0 === value.trim().length) });
57 | })
58 | )
59 | .then(callback)
60 | .catch(e => console.warn(e))
61 | .finally(() => {
62 | vueInput.$destroy();
63 | vueInput = null;
64 | data = null;
65 | prompt = null;
66 | })
67 | }
--------------------------------------------------------------------------------
/src/utils/removeZValue.js:
--------------------------------------------------------------------------------
1 | import { GEOMETRY_TYPES } from 'g3w-constants';
2 |
3 | /**
4 | * Remove Z values from geometry coordinates
5 | */
6 | export function removeZValue({ feature } = {}) {
7 |
8 | const geometry = feature.getGeometry();
9 |
10 | // skip when feature has no geometry (alphanumerical feature)
11 | if (!geometry) {
12 | return feature;
13 | }
14 |
15 | const coords = geometry.getCoordinates();
16 |
17 | switch (geometry.getType()) {
18 |
19 | // POINT: [x, y]
20 | case GEOMETRY_TYPES.POINT:
21 | coords.splice(2);
22 | geometry.setCoordinates(coords);
23 | break;
24 |
25 | // MULTIPOINT: [ [x1, y1], [x2, y2] ]
26 | case GEOMETRY_TYPES.MULTIPOINT:
27 | // LINE: [ [x1, y1], [x2, y2] ]
28 | case GEOMETRY_TYPES.LINESTRING:
29 | case GEOMETRY_TYPES.LINE:
30 | coords.forEach(c => c.splice(2));
31 | geometry.setCoordinates(coords);
32 | break;
33 |
34 | // MULTILINE: [
35 | // [ [x1, y1], [x2, y2] ],
36 | // [ [x3, y3], [x4, y4] ]
37 | // ]
38 | case GEOMETRY_TYPES.MULTILINESTRING:
39 | case GEOMETRY_TYPES.MULTILINE:
40 | coords.forEach(line => line.forEach(c => c.splice(2)));
41 | geometry.setCoordinates(coords);
42 | break;
43 |
44 | // POLYGON: [
45 | // [ [x1, y1], [x2, y2], [x3, y3], [x1, y1] ]
46 | // ]
47 | case GEOMETRY_TYPES.POLYGON:
48 | coords[0].forEach(c => c.splice(2));
49 | geometry.setCoordinates(coords);
50 | break;
51 |
52 | // MULTIPOLYGON: [
53 | // [ [x1, y1], [x2, y2], [x3, y3], [x1, y1] ],
54 | // [ [xa, ya], [xb, yb], [xc, yc], [xa, ya] ]
55 | // ]
56 | case GEOMETRY_TYPES.MULTIPOLYGON:
57 | coords.forEach(poly => poly[0].forEach(c => c.splice(2)));
58 | geometry.setCoordinates(coords);
59 | break;
60 |
61 | default:
62 | console.warn('unsupported geometry type: ' + geometry.getType());
63 |
64 | }
65 |
66 | return feature;
67 | }
--------------------------------------------------------------------------------
/src/utils/resolve.js:
--------------------------------------------------------------------------------
1 | import { $promisify } from 'utils/promisify';
2 |
3 | export function resolve(value) {
4 | return $promisify(Promise.resolve(value));
5 | }
--------------------------------------------------------------------------------
/src/utils/reverseGeometry.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param geometry
3 | */
4 | export function reverseGeometry(geometry) {
5 | geometry.setCoordinates(_reverseCoords(geometry.getCoordinates()));
6 | return geometry
7 | }
8 |
9 | function _reverseCoords(coords) {
10 | coords.find(c => {
11 | if (!Array.isArray(c)) {
12 | const [y, x] = coords; coords[0] = x; coords[1] = y;
13 | return true;
14 | }
15 | _reverseCoords(c);
16 | });
17 | return coords;
18 | }
--------------------------------------------------------------------------------
/src/utils/sameOrigin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param {string} url1
3 | * @param {string} url2
4 | *
5 | * @returns {boolean} whether URLs have same origin.
6 | *
7 | * @since 3.8.0
8 | */
9 | export function sameOrigin(url1, url2) {
10 | try {
11 | return new URL(url1).origin === new URL(url2).origin;
12 | } catch(e) {
13 | console.warn(e);
14 | return false;
15 | }
16 | }
--------------------------------------------------------------------------------
/src/utils/sanitizeFidFeature.js:
--------------------------------------------------------------------------------
1 | export function sanitizeFidFeature(fid) {
2 | if ('string' === typeof fid && Number.isNaN(1*fid)) {
3 | fid = fid.split('.');
4 | fid = fid.at(2 === fid.length ? 1 : 0);
5 | }
6 | return fid;
7 | }
--------------------------------------------------------------------------------
/src/utils/saveBlob.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Save blob file to disk, same as: `Content-Disposition: attachment; filename="file name.jpg"` response header
3 | */
4 | export function saveBlob(blob, filename = 'filename=g3w_file') {
5 | Object.assign(document.createElement('a'), {
6 | href: URL.createObjectURL(blob),
7 | download: filename.split('filename=').at(-1)
8 | }).click();
9 | URL.revokeObjectURL(blob);
10 | }
--------------------------------------------------------------------------------
/src/utils/throttle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * build throttle function
3 | */
4 | export function throttle(fnc, delay = 500) {
5 | let lastCall;
6 | return function (...args) {
7 | let previousCall = lastCall;
8 | lastCall = Date.now();
9 | if (previousCall === undefined // function is being called for the first time
10 | || (lastCall - previousCall) > delay) { // throttle time has elapsed
11 | fnc(...args);
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/utils/toRawType.js:
--------------------------------------------------------------------------------
1 | export function toRawType(value) {
2 | return Object.prototype.toString.call(value).slice(8, -1)
3 | }
--------------------------------------------------------------------------------
/src/utils/waitFor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Function to wait for predicates.
3 | *
4 | * @param { () => Boolean } predicate - A function that returns a bool
5 | * @param { number } [timeout] - Optional maximum waiting time in ms after rejected
6 | *
7 | * @see https://gist.github.com/chrisjhoughton/7890239?permalink_comment_id=4411125#gistcomment-4411125
8 | */
9 | export function waitFor(predicate, timeout) {
10 | return new Promise((resolve, reject) => {
11 | const check = () => {
12 | if (!predicate()) {
13 | return 'invalid predicate';
14 | }
15 | clearInterval(interval);
16 | resolve('predicate');
17 | };
18 | const interval = setInterval(check, 100);
19 | check();
20 | if (timeout) {
21 | setTimeout(() => { clearInterval(interval); reject('timeout'); }, timeout);
22 | }
23 | });
24 | }
--------------------------------------------------------------------------------
/src/utils/within.js:
--------------------------------------------------------------------------------
1 | import 'jsts/dist/jsts.min.js';
2 |
3 | /**
4 | * @param { ol.geometry } geometry
5 | * @param { ol.geometry } geometryToCheck
6 | * @returns { boolean } whether `geometry` contains `geometryToCheck`
7 | *
8 | * @since 3.8.0
9 | */
10 | export function within(geometry, geometryToCheck) {
11 | const parser = new jsts.io.OL3Parser();
12 | parser.inject(
13 | ol.geom.Point,
14 | ol.geom.LineString,
15 | ol.geom.LinearRing,
16 | ol.geom.Polygon,
17 | ol.geom.MultiPoint,
18 | ol.geom.MultiLineString,
19 | ol.geom.MultiPolygon,
20 | );
21 | return parser.read(geometryToCheck).within(parser.read(geometry))
22 | }
--------------------------------------------------------------------------------