@geogirafe/lib-geoportal 0.6.0-1428917543 → 0.6.0-1433157121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/main.d.ts +1 -0
- package/components/main.js +1 -0
- package/components/metadatawindow/component.d.ts +12 -0
- package/components/metadatawindow/component.js +104 -0
- package/components/selectiongrid/component.d.ts +2 -1
- package/components/selectiongrid/component.js +38 -12
- package/components/selectiongrid/tools/selectiontabulatormanager.d.ts +81 -0
- package/components/selectiongrid/tools/selectiontabulatormanager.js +193 -0
- package/components/treeviewgroup/component.d.ts +1 -0
- package/components/treeviewgroup/component.js +19 -1
- package/components/treeviewitem/component.d.ts +1 -0
- package/components/treeviewitem/component.js +19 -1
- package/main.js +2 -0
- package/models/gmf.d.ts +1 -0
- package/models/layers/baselayer.d.ts +3 -0
- package/models/layers/baselayer.js +17 -0
- package/models/layers/grouplayer.d.ts +1 -0
- package/models/layers/grouplayer.js +1 -0
- package/models/layers/layer.d.ts +1 -0
- package/models/layers/layercog.d.ts +1 -0
- package/models/layers/layercog.js +2 -0
- package/models/layers/layervectortiles.d.ts +1 -0
- package/models/layers/layervectortiles.js +1 -0
- package/models/layers/layerwms.d.ts +1 -0
- package/models/layers/layerwms.js +2 -0
- package/models/layers/layerwmts.d.ts +1 -0
- package/models/layers/layerwmts.js +2 -0
- package/models/layers/layerxyz.d.ts +1 -0
- package/models/layers/layerxyz.js +2 -0
- package/models/layers/themelayer.d.ts +1 -0
- package/package.json +3 -1
- package/public/about.json +1 -1
- package/styles/index.css +8 -0
- package/tools/configuration/girafeconfig.d.ts +6 -0
- package/tools/configuration/girafeconfig.js +18 -0
- package/tools/state/state.d.ts +6 -0
- package/tools/state/state.js +10 -0
- package/tools/themesmanager.js +1 -0
package/components/main.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { default as LidarProfileComponent } from './lidar/profile/component';
|
|
|
12
12
|
export { default as LRPanelComponent } from './lr-panel/component';
|
|
13
13
|
export { default as MapComponent } from './map/component';
|
|
14
14
|
export { default as MenuButtonComponent } from './menubutton/component';
|
|
15
|
+
export { default as MetadataWindowComponent } from './metadatawindow/component';
|
|
15
16
|
export { default as NavBookmarksComponent } from './navigation/navbookmarks/component';
|
|
16
17
|
export { default as NavHelperComponent } from './navigation/navhelper/component';
|
|
17
18
|
export { default as OfflineComponent } from './offline/component';
|
package/components/main.js
CHANGED
|
@@ -12,6 +12,7 @@ export { default as LidarProfileComponent } from './lidar/profile/component';
|
|
|
12
12
|
export { default as LRPanelComponent } from './lr-panel/component';
|
|
13
13
|
export { default as MapComponent } from './map/component';
|
|
14
14
|
export { default as MenuButtonComponent } from './menubutton/component';
|
|
15
|
+
export { default as MetadataWindowComponent } from './metadatawindow/component';
|
|
15
16
|
export { default as NavBookmarksComponent } from './navigation/navbookmarks/component';
|
|
16
17
|
export { default as NavHelperComponent } from './navigation/navhelper/component';
|
|
17
18
|
export { default as OfflineComponent } from './offline/component';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import GirafeDraggableElement from '../../base/GirafeDraggableElement';
|
|
2
|
+
declare class MetadataWindowComponent extends GirafeDraggableElement {
|
|
3
|
+
template: () => import("uhtml").Hole;
|
|
4
|
+
private initialized;
|
|
5
|
+
constructor();
|
|
6
|
+
registerEvents(): void;
|
|
7
|
+
render(): void;
|
|
8
|
+
toggleMetadata(visible: boolean): void;
|
|
9
|
+
closeWindow(): void;
|
|
10
|
+
connectedCallback(): void;
|
|
11
|
+
}
|
|
12
|
+
export default MetadataWindowComponent;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { html as uHtml } from 'uhtml';
|
|
2
|
+
import GirafeDraggableElement from '../../base/GirafeDraggableElement';
|
|
3
|
+
class MetadataWindowComponent extends GirafeDraggableElement {
|
|
4
|
+
constructor() {
|
|
5
|
+
super('metadatawindow');
|
|
6
|
+
Object.defineProperty(this, "template", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: () => {
|
|
11
|
+
return uHtml `<style>
|
|
12
|
+
#draggable {
|
|
13
|
+
border-radius: 1px;
|
|
14
|
+
box-shadow: var(--bx-shdw);
|
|
15
|
+
height: 100%;
|
|
16
|
+
width: 100%;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#header {
|
|
20
|
+
height: 2rem;
|
|
21
|
+
line-height: 2rem;
|
|
22
|
+
cursor: grabbing;
|
|
23
|
+
z-index: 10;
|
|
24
|
+
background: var(--bkg-color-grad2);
|
|
25
|
+
color: var(--text-color);
|
|
26
|
+
text-align: center;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#content {
|
|
30
|
+
padding-left: 1rem;
|
|
31
|
+
width: calc(100% - 1rem);
|
|
32
|
+
height: calc(100% - 2rem);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#close {
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
float: right;
|
|
38
|
+
width: 12px;
|
|
39
|
+
color: var(--text-color);
|
|
40
|
+
padding: 0.45rem;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
iframe {
|
|
44
|
+
border: none;
|
|
45
|
+
width: 100%;
|
|
46
|
+
height: 100%;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
</style>
|
|
50
|
+
<div id="draggable">
|
|
51
|
+
<div id="header">
|
|
52
|
+
<span i18n="${this.state.metadata.title}"></span>
|
|
53
|
+
<img id="close" alt="close-icon" src="icons/close.svg" />
|
|
54
|
+
</div>
|
|
55
|
+
<div id="content">
|
|
56
|
+
<iframe title="iframe content" src="${this.state.metadata.url}"></iframe>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
Object.defineProperty(this, "initialized", {
|
|
63
|
+
enumerable: true,
|
|
64
|
+
configurable: true,
|
|
65
|
+
writable: true,
|
|
66
|
+
value: false
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
registerEvents() {
|
|
70
|
+
this.stateManager.subscribe('interface.metadataVisible', (_oldValue, newValue) => this.toggleMetadata(newValue));
|
|
71
|
+
this.stateManager.subscribe(/metadata.*/, () => this.render());
|
|
72
|
+
}
|
|
73
|
+
render() {
|
|
74
|
+
if (!this.initialized) {
|
|
75
|
+
const host = this.shadow.getRootNode().host;
|
|
76
|
+
host.style.width = this.configManager.Config.metadata.defaultWindowWidth;
|
|
77
|
+
host.style.height = this.configManager.Config.metadata.defaultWindowHeight;
|
|
78
|
+
this.initialized = true;
|
|
79
|
+
}
|
|
80
|
+
super.render();
|
|
81
|
+
this.girafeTranslate();
|
|
82
|
+
this.makeDraggable();
|
|
83
|
+
}
|
|
84
|
+
toggleMetadata(visible) {
|
|
85
|
+
if (visible) {
|
|
86
|
+
this.render();
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
this.renderEmpty();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
closeWindow() {
|
|
93
|
+
this.state.interface.metadataVisible = false;
|
|
94
|
+
}
|
|
95
|
+
connectedCallback() {
|
|
96
|
+
this.loadConfig().then(() => {
|
|
97
|
+
this.render();
|
|
98
|
+
this.girafeTranslate();
|
|
99
|
+
this.makeDraggable();
|
|
100
|
+
this.registerEvents();
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export default MetadataWindowComponent;
|
|
@@ -10,6 +10,7 @@ declare class SelectionGridComponent extends GirafeResizableElement {
|
|
|
10
10
|
template: () => import("uhtml").Hole;
|
|
11
11
|
private readonly eventsCallbacks;
|
|
12
12
|
private readonly selectionGridManager;
|
|
13
|
+
private readonly selectionTabulatorManager;
|
|
13
14
|
private isVisibleComponentSetup;
|
|
14
15
|
private debounceOnFeaturesSelected;
|
|
15
16
|
visible: boolean;
|
|
@@ -26,7 +27,7 @@ declare class SelectionGridComponent extends GirafeResizableElement {
|
|
|
26
27
|
/**
|
|
27
28
|
* Activates the specified tab, renders the grid, and displays the grid for the specified id.
|
|
28
29
|
*/
|
|
29
|
-
displayGrid(id: string): void;
|
|
30
|
+
displayGrid(id: string, replaceData?: boolean): void;
|
|
30
31
|
/**
|
|
31
32
|
* Clean the grid, closes the panel and deselect the selected features.
|
|
32
33
|
*/
|
|
@@ -2,6 +2,7 @@ import { html as uHtml } from 'uhtml';
|
|
|
2
2
|
import GirafeResizableElement from '../../base/GirafeResizableElement';
|
|
3
3
|
import { debounce } from '../../tools/utils/debounce';
|
|
4
4
|
import SelectionGridManager from './tools/selectiongridmanager';
|
|
5
|
+
import SelectionTabulatorManager from './tools/selectiontabulatormanager';
|
|
5
6
|
/**
|
|
6
7
|
* Represents a selection grid component based on GridJs.
|
|
7
8
|
* Display itself when it should be visible and have selected features.
|
|
@@ -25,7 +26,6 @@ class SelectionGridComponent extends GirafeResizableElement {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
#panel {
|
|
28
|
-
position: absolute;
|
|
29
29
|
top: 0;
|
|
30
30
|
left: 0;
|
|
31
31
|
right: 0;
|
|
@@ -161,11 +161,28 @@ th.gridjs-th {
|
|
|
161
161
|
margin: 0.1rem;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
/* Define the style when the column is not sorted */
|
|
165
|
+
.tabulator-col[aria-sort='none'] .tabulator-col-sorter i {
|
|
166
|
+
color: #999;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Define the style when the column is sorted in ascending order */
|
|
170
|
+
.tabulator-col[aria-sort='asc'] .tabulator-col-sorter i {
|
|
171
|
+
color: #f00;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Define the style when the column is sorted in descending order */
|
|
175
|
+
.tabulator-col[aria-sort='desc'] .tabulator-col-sorter i {
|
|
176
|
+
color: #f00;
|
|
177
|
+
transform: scaleY(-1); /* flip the icon vertically so the arrow points down */
|
|
178
|
+
}
|
|
179
|
+
|
|
164
180
|
</style>
|
|
165
181
|
<link rel="stylesheet" href="styles/common.css" />
|
|
166
182
|
<link rel="stylesheet" href="lib/gridjs/mermaid.min.css" />
|
|
167
183
|
<link rel="stylesheet" href="lib/fontawesome/css/all.min.css" />
|
|
168
184
|
<link rel="stylesheet" href="lib/font-gis/font-gis.css" />
|
|
185
|
+
<link rel="stylesheet" href="../../../node_modules/tabulator-tables/dist/css/tabulator.css" />
|
|
169
186
|
|
|
170
187
|
<div id="panel">
|
|
171
188
|
<div id="content">
|
|
@@ -176,10 +193,10 @@ th.gridjs-th {
|
|
|
176
193
|
i18n="${th.text}"
|
|
177
194
|
class="${th.active ? 'tab active' : 'tab'}"
|
|
178
195
|
.active="${th.active}"
|
|
179
|
-
onclick="${() => this.displayGrid(th.id)}"></button>
|
|
196
|
+
onclick="${() => this.displayGrid(th.id, true)}"></button>
|
|
180
197
|
`)}
|
|
181
198
|
</div>
|
|
182
|
-
<div id="
|
|
199
|
+
<div id="tabulator"></div>
|
|
183
200
|
</div>
|
|
184
201
|
<div id="gutter"></div>
|
|
185
202
|
<button id="close" onclick="this.closePanel()">
|
|
@@ -201,6 +218,12 @@ th.gridjs-th {
|
|
|
201
218
|
writable: true,
|
|
202
219
|
value: new SelectionGridManager()
|
|
203
220
|
});
|
|
221
|
+
Object.defineProperty(this, "selectionTabulatorManager", {
|
|
222
|
+
enumerable: true,
|
|
223
|
+
configurable: true,
|
|
224
|
+
writable: true,
|
|
225
|
+
value: new SelectionTabulatorManager()
|
|
226
|
+
});
|
|
204
227
|
Object.defineProperty(this, "isVisibleComponentSetup", {
|
|
205
228
|
enumerable: true,
|
|
206
229
|
configurable: true,
|
|
@@ -234,15 +257,18 @@ th.gridjs-th {
|
|
|
234
257
|
* @returns The current array of TabHeader objects.
|
|
235
258
|
*/
|
|
236
259
|
getTabHeaders() {
|
|
237
|
-
return this.
|
|
260
|
+
return this.selectionTabulatorManager.tabHeaders;
|
|
238
261
|
}
|
|
239
262
|
/**
|
|
240
263
|
* Activates the specified tab, renders the grid, and displays the grid for the specified id.
|
|
241
264
|
*/
|
|
242
|
-
displayGrid(id) {
|
|
243
|
-
|
|
265
|
+
displayGrid(id, replaceData = false) {
|
|
266
|
+
if (replaceData) {
|
|
267
|
+
this.selectionTabulatorManager.replaceData(id);
|
|
268
|
+
}
|
|
269
|
+
this.selectionTabulatorManager.activateTab(id);
|
|
244
270
|
this.render();
|
|
245
|
-
this.
|
|
271
|
+
this.selectionTabulatorManager.displayGrid(id);
|
|
246
272
|
}
|
|
247
273
|
/**
|
|
248
274
|
* Clean the grid, closes the panel and deselect the selected features.
|
|
@@ -260,7 +286,6 @@ th.gridjs-th {
|
|
|
260
286
|
renderComponent() {
|
|
261
287
|
super.render();
|
|
262
288
|
super.girafeTranslate();
|
|
263
|
-
this.selectionGridManager.setGridElement(this.shadow.querySelector('#grid'));
|
|
264
289
|
this.activateTooltips(false, [800, 0], 'top-end');
|
|
265
290
|
if (!this.isVisibleComponentSetup) {
|
|
266
291
|
this.setupVisibleComponent();
|
|
@@ -309,15 +334,16 @@ th.gridjs-th {
|
|
|
309
334
|
* @private
|
|
310
335
|
*/
|
|
311
336
|
onFeaturesSelected(features) {
|
|
312
|
-
this.
|
|
337
|
+
this.selectionTabulatorManager.tabHeaders = [];
|
|
313
338
|
// No feature ? Close.
|
|
314
339
|
if (this.isNullOrUndefined(features) || features.length <= 0) {
|
|
315
340
|
this.closePanel();
|
|
316
341
|
return;
|
|
317
342
|
}
|
|
318
|
-
|
|
319
|
-
this.
|
|
320
|
-
|
|
343
|
+
this.selectionTabulatorManager.featuresToGridData(features);
|
|
344
|
+
const tabIds = Object.keys(this.selectionTabulatorManager.idTab);
|
|
345
|
+
//define table element
|
|
346
|
+
this.selectionTabulatorManager.setElement(this.shadow.querySelector('#tabulator'));
|
|
321
347
|
// No tab ? Close the panel.
|
|
322
348
|
if (!tabIds.length) {
|
|
323
349
|
this.closePanel();
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type OlFeature from 'ol/Feature';
|
|
2
|
+
import { GridDataById } from '../../../tools/featuretogriddatabyid';
|
|
3
|
+
import { ColumnDefinition, TabulatorFull as Tabulator } from 'tabulator-tables';
|
|
4
|
+
/**
|
|
5
|
+
* Represents the header text and state of a tab.
|
|
6
|
+
*/
|
|
7
|
+
export interface TabHeader {
|
|
8
|
+
id: string;
|
|
9
|
+
text: string;
|
|
10
|
+
active: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Represents a column in a data table.
|
|
14
|
+
*/
|
|
15
|
+
export interface Column {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Represents the content and backrefs of a tab.
|
|
21
|
+
*/
|
|
22
|
+
export interface TabContent {
|
|
23
|
+
columns: Column[];
|
|
24
|
+
data: unknown[][];
|
|
25
|
+
features: OlFeature[];
|
|
26
|
+
}
|
|
27
|
+
export default class SelectionTabulatorManager {
|
|
28
|
+
private readonly formatGridGeomValue;
|
|
29
|
+
private configManager;
|
|
30
|
+
private readonly featureToGridData;
|
|
31
|
+
idTab: Record<string, TabContent>;
|
|
32
|
+
tabHeaders: TabHeader[];
|
|
33
|
+
table: Tabulator | null;
|
|
34
|
+
element: string | HTMLElement;
|
|
35
|
+
data: GridDataById;
|
|
36
|
+
constructor();
|
|
37
|
+
/**
|
|
38
|
+
* Set the HTML element to be used by the grid.
|
|
39
|
+
*/
|
|
40
|
+
setElement(htmlElement: HTMLElement): void;
|
|
41
|
+
/**
|
|
42
|
+
* Replace the data of the current grid with the data of the specified tab.
|
|
43
|
+
*/
|
|
44
|
+
replaceData(id: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Activates a tab matching the given id.
|
|
47
|
+
*/
|
|
48
|
+
activateTab(id: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Creates (replace) the GridJS grid based on the provided tab id and related data and features.
|
|
51
|
+
*/
|
|
52
|
+
displayGrid(id: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* Transforms the given features into grid data and sets tab headers.
|
|
55
|
+
* The grid data are completely replaced.
|
|
56
|
+
*/
|
|
57
|
+
featuresToGridData(features: OlFeature[]): void;
|
|
58
|
+
/**
|
|
59
|
+
* Converts grid data to grid tab format and adds it to the idTab object.
|
|
60
|
+
* @private
|
|
61
|
+
*/
|
|
62
|
+
private gridDataToGridTab;
|
|
63
|
+
columnsToGridColumns(columns: string[]): ColumnDefinition[];
|
|
64
|
+
filterEmptyColumnsOnData(data: GridDataById): GridDataById;
|
|
65
|
+
/**
|
|
66
|
+
* @returns A newly created grid column object.
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
private createGridColumn;
|
|
70
|
+
/**
|
|
71
|
+
* Creates grid data by mapping values (simple values, or transformed values in case of HTML).
|
|
72
|
+
* @returns The grid data array.
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
private createGridData;
|
|
76
|
+
/**
|
|
77
|
+
* @returns The locale specified in the configuration.
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
private getLocale;
|
|
81
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import OlGeomGeometry from 'ol/geom/Geometry';
|
|
2
|
+
import ConfigManager from '../../../tools/configuration/configmanager';
|
|
3
|
+
import FeatureToGridDataById from '../../../tools/featuretogriddatabyid';
|
|
4
|
+
import I18nManager from '../../../tools/i18n/i18nmanager';
|
|
5
|
+
import FormatGridGeomValue from './formatgridgeomvalue';
|
|
6
|
+
import { TabulatorFull as Tabulator } from 'tabulator-tables';
|
|
7
|
+
export default class SelectionTabulatorManager {
|
|
8
|
+
constructor() {
|
|
9
|
+
Object.defineProperty(this, "formatGridGeomValue", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true,
|
|
13
|
+
value: new FormatGridGeomValue()
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(this, "configManager", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true,
|
|
18
|
+
writable: true,
|
|
19
|
+
value: void 0
|
|
20
|
+
});
|
|
21
|
+
Object.defineProperty(this, "featureToGridData", {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
configurable: true,
|
|
24
|
+
writable: true,
|
|
25
|
+
value: new FeatureToGridDataById({ keepGeomProperty: true })
|
|
26
|
+
});
|
|
27
|
+
Object.defineProperty(this, "idTab", {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
configurable: true,
|
|
30
|
+
writable: true,
|
|
31
|
+
value: {}
|
|
32
|
+
});
|
|
33
|
+
Object.defineProperty(this, "tabHeaders", {
|
|
34
|
+
enumerable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
writable: true,
|
|
37
|
+
value: []
|
|
38
|
+
});
|
|
39
|
+
Object.defineProperty(this, "table", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
writable: true,
|
|
43
|
+
value: null
|
|
44
|
+
});
|
|
45
|
+
Object.defineProperty(this, "element", {
|
|
46
|
+
enumerable: true,
|
|
47
|
+
configurable: true,
|
|
48
|
+
writable: true,
|
|
49
|
+
value: ''
|
|
50
|
+
});
|
|
51
|
+
Object.defineProperty(this, "data", {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
configurable: true,
|
|
54
|
+
writable: true,
|
|
55
|
+
value: {}
|
|
56
|
+
});
|
|
57
|
+
this.configManager = ConfigManager.getInstance();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Set the HTML element to be used by the grid.
|
|
61
|
+
*/
|
|
62
|
+
setElement(htmlElement) {
|
|
63
|
+
this.element = htmlElement;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Replace the data of the current grid with the data of the specified tab.
|
|
67
|
+
*/
|
|
68
|
+
replaceData(id) {
|
|
69
|
+
const columns = this.columnsToGridColumns(this.data[id].columns);
|
|
70
|
+
this.table?.setColumns(columns);
|
|
71
|
+
this.table?.replaceData(this.data[id].notOlProperties);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Activates a tab matching the given id.
|
|
75
|
+
*/
|
|
76
|
+
activateTab(id) {
|
|
77
|
+
this.tabHeaders?.forEach((tabHeader) => (tabHeader.active = false));
|
|
78
|
+
const visibleTabHeader = this.tabHeaders?.find((tabHeader) => tabHeader.id === id);
|
|
79
|
+
if (!visibleTabHeader) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
visibleTabHeader.active = true;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Creates (replace) the GridJS grid based on the provided tab id and related data and features.
|
|
86
|
+
*/
|
|
87
|
+
displayGrid(id) {
|
|
88
|
+
if (!this.element) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.table = new Tabulator(this.element, {
|
|
92
|
+
data: this.data[id].notOlProperties,
|
|
93
|
+
columns: this.columnsToGridColumns(this.data[id].columns),
|
|
94
|
+
selectableRows: true,
|
|
95
|
+
layout: 'fitColumns',
|
|
96
|
+
headerSortElement: function (_, dir) {
|
|
97
|
+
switch (dir) {
|
|
98
|
+
case 'asc':
|
|
99
|
+
return "<i class='fas fa-sort-up'>";
|
|
100
|
+
case 'desc':
|
|
101
|
+
return "<i class='fas fa-sort-down'>";
|
|
102
|
+
default:
|
|
103
|
+
return "<i class='fas fa-sort'>";
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Transforms the given features into grid data and sets tab headers.
|
|
110
|
+
* The grid data are completely replaced.
|
|
111
|
+
*/
|
|
112
|
+
featuresToGridData(features) {
|
|
113
|
+
this.idTab = {};
|
|
114
|
+
const gridDataById = this.featureToGridData.toGridDataById(features);
|
|
115
|
+
// Create tabs and collect data.
|
|
116
|
+
Object.keys(gridDataById).forEach((id) => this.gridDataToGridTab(id, gridDataById[id]));
|
|
117
|
+
// Create tabs headers
|
|
118
|
+
this.tabHeaders = Object.keys(this.idTab).map((key) => {
|
|
119
|
+
return {
|
|
120
|
+
id: key,
|
|
121
|
+
text: I18nManager.getInstance().getTranslation(key),
|
|
122
|
+
active: false
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
this.data = this.filterEmptyColumnsOnData(gridDataById);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Converts grid data to grid tab format and adds it to the idTab object.
|
|
129
|
+
* @private
|
|
130
|
+
*/
|
|
131
|
+
gridDataToGridTab(id, gridData) {
|
|
132
|
+
if (id in this.idTab) {
|
|
133
|
+
// Already in ? Don't add a new one.
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
this.idTab[id] = {
|
|
137
|
+
columns: gridData.columns.map((column) => this.createGridColumn(column)),
|
|
138
|
+
data: gridData.data.map((data) => this.createGridData(data)),
|
|
139
|
+
features: gridData.features
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
columnsToGridColumns(columns) {
|
|
143
|
+
const columnDefinition = [];
|
|
144
|
+
columns.map((column) => columnDefinition.push({ title: column, field: column }));
|
|
145
|
+
columnDefinition.forEach((column) => {
|
|
146
|
+
if (column.title === 'geometry' || column.title === 'geom') {
|
|
147
|
+
column.formatter = (cell) => {
|
|
148
|
+
return this.formatGridGeomValue.getGeometryIcons(cell.getValue(), this.getLocale()) ?? cell.getValue();
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
return columnDefinition;
|
|
153
|
+
}
|
|
154
|
+
filterEmptyColumnsOnData(data) {
|
|
155
|
+
for (const [_, entry] of Object.entries(data)) {
|
|
156
|
+
const columns = entry.columns;
|
|
157
|
+
const notOlProperties = entry.notOlProperties;
|
|
158
|
+
for (const [_, row] of Object.entries(notOlProperties)) {
|
|
159
|
+
for (const [key, _] of Object.entries(row)) {
|
|
160
|
+
if (!columns.some((column) => column === key)) {
|
|
161
|
+
delete row[key];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return data;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* @returns A newly created grid column object.
|
|
170
|
+
* @private
|
|
171
|
+
*/
|
|
172
|
+
createGridColumn(id) {
|
|
173
|
+
return {
|
|
174
|
+
id,
|
|
175
|
+
name: I18nManager.getInstance().getTranslation(id)
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Creates grid data by mapping values (simple values, or transformed values in case of HTML).
|
|
180
|
+
* @returns The grid data array.
|
|
181
|
+
* @private
|
|
182
|
+
*/
|
|
183
|
+
createGridData(values) {
|
|
184
|
+
return values.map((value) => value instanceof OlGeomGeometry ? this.formatGridGeomValue.getGeometryIcons(value, this.getLocale()) : value);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* @returns The locale specified in the configuration.
|
|
188
|
+
* @private
|
|
189
|
+
*/
|
|
190
|
+
getLocale() {
|
|
191
|
+
return this.configManager.Config.general.locale;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -15,6 +15,7 @@ declare class TreeViewGroupComponent extends GirafeHTMLElement {
|
|
|
15
15
|
toggle(state?: 'on' | 'off' | 'semi'): void;
|
|
16
16
|
connectedCallback(): void;
|
|
17
17
|
deactivateGroup(layer: BaseLayer): void;
|
|
18
|
+
showMetadata(): void;
|
|
18
19
|
deleteGroup(): void;
|
|
19
20
|
private deleteGroupRecursive;
|
|
20
21
|
}
|
|
@@ -80,8 +80,13 @@ i {
|
|
|
80
80
|
width: 0;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
.
|
|
83
|
+
.metadata {
|
|
84
84
|
order: 5;
|
|
85
|
+
padding: 0.45rem;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.delete {
|
|
89
|
+
order: 6;
|
|
85
90
|
padding-top: 0.45rem;
|
|
86
91
|
}
|
|
87
92
|
|
|
@@ -144,6 +149,12 @@ i {
|
|
|
144
149
|
>${this.group.name}</span
|
|
145
150
|
>
|
|
146
151
|
|
|
152
|
+
<!-- Metadata icon -->
|
|
153
|
+
<i
|
|
154
|
+
class="${this.group.metadataUrl ? 'fa fa-solid fa-circle-info tool metadata selectable' : 'metadata hidden'}"
|
|
155
|
+
tip="More information"
|
|
156
|
+
onclick="${() => this.showMetadata()}"></i>
|
|
157
|
+
|
|
147
158
|
<!-- Remove icon -->
|
|
148
159
|
<i
|
|
149
160
|
class="fa fa-solid fa-xmark tool delete selectable"
|
|
@@ -231,6 +242,13 @@ i {
|
|
|
231
242
|
}
|
|
232
243
|
}
|
|
233
244
|
}
|
|
245
|
+
showMetadata() {
|
|
246
|
+
this.state.metadata = {
|
|
247
|
+
title: this.group.name,
|
|
248
|
+
url: this.group.metadataUrl ?? null
|
|
249
|
+
};
|
|
250
|
+
this.state.interface.metadataVisible = true;
|
|
251
|
+
}
|
|
234
252
|
deleteGroup() {
|
|
235
253
|
this.deactivateGroup(this.group);
|
|
236
254
|
if (!this.deleteGroupRecursive(this.state.layers.layersList)) {
|
|
@@ -21,6 +21,7 @@ declare class TreeViewItemComponent extends GirafeHTMLElement {
|
|
|
21
21
|
zoomToVisibleResolution(): void;
|
|
22
22
|
zoomToFullExtent(): void;
|
|
23
23
|
swipeLayer(side: 'left' | 'right'): void;
|
|
24
|
+
showMetadata(): void;
|
|
24
25
|
connectedCallback(): void;
|
|
25
26
|
}
|
|
26
27
|
export default TreeViewItemComponent;
|
|
@@ -125,8 +125,13 @@ i {
|
|
|
125
125
|
order: 11;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
.
|
|
128
|
+
.metadata {
|
|
129
129
|
order: 12;
|
|
130
|
+
padding-right: 0.15rem;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.legend {
|
|
134
|
+
order: 13;
|
|
130
135
|
}
|
|
131
136
|
|
|
132
137
|
.item i.advanced {
|
|
@@ -228,6 +233,12 @@ i {
|
|
|
228
233
|
class="${this.layer instanceof LayerWms && this.layer.queryable ? 'fa-solid fa-filter tool selectable filter advanced' : 'filter invisible'}"
|
|
229
234
|
tip="Filter layer"></i>
|
|
230
235
|
|
|
236
|
+
<!-- Metadata icon -->
|
|
237
|
+
<i
|
|
238
|
+
class="${this.layer.metadataUrl ? 'fa fa-solid fa-circle-info tool metadata selectable' : 'metadata hidden'}"
|
|
239
|
+
tip="More information"
|
|
240
|
+
onclick="${() => this.showMetadata()}"></i>
|
|
241
|
+
|
|
231
242
|
<!-- Toggle legend icon -->
|
|
232
243
|
<div
|
|
233
244
|
class="${this.layer instanceof LayerLocalFile || (this.layer instanceof LayerWms && this.layer.legend) ? 'legend selectable' : 'legend invisible'}">
|
|
@@ -456,6 +467,13 @@ ${Object.keys(this.legendUrls).map((l) => uHtml `<img
|
|
|
456
467
|
// Lastly, we update the state
|
|
457
468
|
this.state.layers.swipedLayers = newSwipedLayers;
|
|
458
469
|
}
|
|
470
|
+
showMetadata() {
|
|
471
|
+
this.state.metadata = {
|
|
472
|
+
title: this.layer.name,
|
|
473
|
+
url: this.layer.metadataUrl ?? null
|
|
474
|
+
};
|
|
475
|
+
this.state.interface.metadataVisible = true;
|
|
476
|
+
}
|
|
459
477
|
connectedCallback() {
|
|
460
478
|
this.loadConfig().then(() => {
|
|
461
479
|
this.render();
|
package/main.js
CHANGED
|
@@ -17,6 +17,7 @@ import ColorSwitcherComponent from './components/colorswitcher/component';
|
|
|
17
17
|
import CoordinateComponent from './components/coordinate/component';
|
|
18
18
|
import GlobeComponent from './components/globe/component';
|
|
19
19
|
import HelpComponent from './components/help/component';
|
|
20
|
+
import MetadataWindowComponent from './components/metadatawindow/component';
|
|
20
21
|
import InfoboxComponent from './components/infobox/component';
|
|
21
22
|
import LanguageComponent from './components/language/component';
|
|
22
23
|
import LidarPanelComponent from './components/lidar/panel/component';
|
|
@@ -81,6 +82,7 @@ try {
|
|
|
81
82
|
customElements.define('girafe-coordinate', CoordinateComponent);
|
|
82
83
|
customElements.define('girafe-globe-select', GlobeComponent);
|
|
83
84
|
customElements.define('girafe-help', HelpComponent);
|
|
85
|
+
customElements.define('girafe-metadata-window', MetadataWindowComponent);
|
|
84
86
|
customElements.define('girafe-infobox', InfoboxComponent);
|
|
85
87
|
customElements.define('girafe-language-select', LanguageComponent);
|
|
86
88
|
customElements.define('girafe-lidar-panel', LidarPanelComponent);
|
package/models/gmf.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import ThemeLayer from './themelayer';
|
|
|
3
3
|
type BaseLayerOptions = {
|
|
4
4
|
isDefaultChecked?: boolean;
|
|
5
5
|
disclaimer?: string;
|
|
6
|
+
metadataUrl?: string;
|
|
6
7
|
};
|
|
7
8
|
declare abstract class BaseLayer {
|
|
8
9
|
/**
|
|
@@ -18,6 +19,7 @@ declare abstract class BaseLayer {
|
|
|
18
19
|
order: number;
|
|
19
20
|
isDefaultChecked: boolean;
|
|
20
21
|
disclaimer?: string;
|
|
22
|
+
metadataUrl?: string;
|
|
21
23
|
hasError: boolean;
|
|
22
24
|
errorMessage: string | null;
|
|
23
25
|
abstract activeState: string;
|
|
@@ -26,6 +28,7 @@ declare abstract class BaseLayer {
|
|
|
26
28
|
abstract clone(): BaseLayer;
|
|
27
29
|
parent: ThemeLayer | GroupLayer | null;
|
|
28
30
|
constructor(id: number, name: string, order: number, options?: BaseLayerOptions);
|
|
31
|
+
private calculateMetadataUrl;
|
|
29
32
|
/**
|
|
30
33
|
* @returns the name of the class to facilitate the identification
|
|
31
34
|
* of subclasses, even in Proxy objects.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import ConfigManager from '../../tools/configuration/configmanager';
|
|
1
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
2
3
|
class BaseLayer {
|
|
3
4
|
constructor(id, name, order, options) {
|
|
@@ -44,6 +45,12 @@ class BaseLayer {
|
|
|
44
45
|
writable: true,
|
|
45
46
|
value: void 0
|
|
46
47
|
});
|
|
48
|
+
Object.defineProperty(this, "metadataUrl", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
writable: true,
|
|
52
|
+
value: void 0
|
|
53
|
+
});
|
|
47
54
|
Object.defineProperty(this, "hasError", {
|
|
48
55
|
enumerable: true,
|
|
49
56
|
configurable: true,
|
|
@@ -68,6 +75,16 @@ class BaseLayer {
|
|
|
68
75
|
this.order = order;
|
|
69
76
|
this.isDefaultChecked = options?.isDefaultChecked || false;
|
|
70
77
|
this.disclaimer = options?.disclaimer;
|
|
78
|
+
this.metadataUrl = this.calculateMetadataUrl(options?.metadataUrl);
|
|
79
|
+
}
|
|
80
|
+
calculateMetadataUrl(metadataUrl) {
|
|
81
|
+
if (!metadataUrl) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
if (!metadataUrl.startsWith('http') && ConfigManager.getInstance().Config.metadata.metadataUrlPrefix) {
|
|
85
|
+
return ConfigManager.getInstance().Config.metadata.metadataUrlPrefix + metadataUrl;
|
|
86
|
+
}
|
|
87
|
+
return metadataUrl;
|
|
71
88
|
}
|
|
72
89
|
/**
|
|
73
90
|
* @returns the name of the class to facilitate the identification
|
|
@@ -39,6 +39,7 @@ class GroupLayer extends BaseLayer {
|
|
|
39
39
|
clone() {
|
|
40
40
|
const options = {
|
|
41
41
|
isDefaultChecked: this.isDefaultChecked,
|
|
42
|
+
metadataUrl: this.metadataUrl,
|
|
42
43
|
disclaimer: this.disclaimer,
|
|
43
44
|
isDefaultExpanded: this.isExpanded,
|
|
44
45
|
isExclusiveGroup: this.isExclusiveGroup
|
package/models/layers/layer.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ class LayerCog extends Layer {
|
|
|
22
22
|
clone() {
|
|
23
23
|
const options = {
|
|
24
24
|
isDefaultChecked: this.isDefaultChecked,
|
|
25
|
+
metadataUrl: this.metadataUrl,
|
|
25
26
|
disclaimer: this.disclaimer,
|
|
26
27
|
opacity: this.opacity
|
|
27
28
|
};
|
|
@@ -35,6 +36,7 @@ class LayerCog extends Layer {
|
|
|
35
36
|
static getOptionsFromGMFTreeItem(options) {
|
|
36
37
|
return {
|
|
37
38
|
isDefaultChecked: options.metadata?.isChecked,
|
|
39
|
+
metadataUrl: options.metadata?.metadataUrl,
|
|
38
40
|
disclaimer: options.metadata?.disclaimer,
|
|
39
41
|
opacity: 1 // TODO REG : Set default opacity
|
|
40
42
|
};
|
|
@@ -143,6 +143,7 @@ class LayerWms extends Layer {
|
|
|
143
143
|
clone() {
|
|
144
144
|
const options = {
|
|
145
145
|
isDefaultChecked: this.isDefaultChecked,
|
|
146
|
+
metadataUrl: this.metadataUrl,
|
|
146
147
|
disclaimer: this.disclaimer,
|
|
147
148
|
opacity: this.opacity,
|
|
148
149
|
minResolution: this.minResolution,
|
|
@@ -180,6 +181,7 @@ class LayerWms extends Layer {
|
|
|
180
181
|
static getOptionsFromGMFTreeItem(options) {
|
|
181
182
|
const opts = {
|
|
182
183
|
isDefaultChecked: options.metadata?.isChecked,
|
|
184
|
+
metadataUrl: options.metadata?.metadataUrl,
|
|
183
185
|
disclaimer: options.metadata?.disclaimer,
|
|
184
186
|
opacity: 1, // TODO REG : Set default opacity
|
|
185
187
|
minResolution: options.minResolutionHint,
|
|
@@ -115,6 +115,7 @@ class LayerWmts extends Layer {
|
|
|
115
115
|
clone() {
|
|
116
116
|
const options = {
|
|
117
117
|
isDefaultChecked: this.isDefaultChecked,
|
|
118
|
+
metadataUrl: this.metadataUrl,
|
|
118
119
|
disclaimer: this.disclaimer,
|
|
119
120
|
opacity: this.opacity,
|
|
120
121
|
dimensions: this.dimensions,
|
|
@@ -145,6 +146,7 @@ class LayerWmts extends Layer {
|
|
|
145
146
|
static getOptionsFromGMFTreeItem(options) {
|
|
146
147
|
return {
|
|
147
148
|
isDefaultChecked: options.metadata?.isChecked,
|
|
149
|
+
metadataUrl: options.metadata?.metadataUrl,
|
|
148
150
|
disclaimer: options.metadata?.disclaimer,
|
|
149
151
|
opacity: 1, // TODO REG : Set default opacity
|
|
150
152
|
dimensions: options.dimensions,
|
|
@@ -22,6 +22,7 @@ class LayerXYZ extends Layer {
|
|
|
22
22
|
clone() {
|
|
23
23
|
const options = {
|
|
24
24
|
isDefaultChecked: this.isDefaultChecked,
|
|
25
|
+
metadataUrl: this.metadataUrl,
|
|
25
26
|
disclaimer: this.disclaimer,
|
|
26
27
|
opacity: this.opacity
|
|
27
28
|
};
|
|
@@ -35,6 +36,7 @@ class LayerXYZ extends Layer {
|
|
|
35
36
|
static getOptionsFromGMFTreeItem(options) {
|
|
36
37
|
return {
|
|
37
38
|
isDefaultChecked: options.metadata?.isChecked,
|
|
39
|
+
metadataUrl: options.metadata?.metadataUrl,
|
|
38
40
|
disclaimer: options.metadata?.disclaimer,
|
|
39
41
|
opacity: 1 // TODO REG : Set default opacity
|
|
40
42
|
};
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "GeoGirafe PSC",
|
|
6
6
|
"url": "https://doc.geomapfish.dev"
|
|
7
7
|
},
|
|
8
|
-
"version": "0.6.0-
|
|
8
|
+
"version": "0.6.0-1433157121",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"engines": {
|
|
11
11
|
"node": ">=20.0.0"
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"gridjs": "6.2.0",
|
|
41
41
|
"lz-string": "1.5.0",
|
|
42
42
|
"on-change": "5.0.1",
|
|
43
|
+
"tabulator-tables": "^6.2.5",
|
|
43
44
|
"source-map-js": "1.2.0",
|
|
44
45
|
"tippy.js": "6.3.7",
|
|
45
46
|
"uhtml": "4.5.9",
|
|
@@ -63,6 +64,7 @@
|
|
|
63
64
|
"@types/file-saver": "2.0.7",
|
|
64
65
|
"@types/geojson": "7946.0.14",
|
|
65
66
|
"@types/proj4": "2.5.5",
|
|
67
|
+
"@types/tabulator-tables": "^6.2.3",
|
|
66
68
|
"@types/uuid": "10.0.0",
|
|
67
69
|
"@typescript-eslint/eslint-plugin": "7.15.0",
|
|
68
70
|
"@typescript-eslint/parser": "7.15.0",
|
package/public/about.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.6.0-
|
|
1
|
+
{"version":"0.6.0-1433157121", "build":"1433157121", "date":"30/08/2024"}
|
package/styles/index.css
CHANGED
|
@@ -265,6 +265,14 @@ girafe-share {
|
|
|
265
265
|
transform: translate(-50%, -50%);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
girafe-metadata-window {
|
|
269
|
+
position: absolute;
|
|
270
|
+
z-index: 100;
|
|
271
|
+
background: var(--bkg-color);
|
|
272
|
+
top: 1rem;
|
|
273
|
+
left: 2rem;
|
|
274
|
+
}
|
|
275
|
+
|
|
268
276
|
.border-top {
|
|
269
277
|
border-top: solid 1px #fff;
|
|
270
278
|
}
|
|
@@ -121,6 +121,11 @@ declare class GirafeConfig {
|
|
|
121
121
|
quote: string;
|
|
122
122
|
separator: string;
|
|
123
123
|
};
|
|
124
|
+
metadata: {
|
|
125
|
+
metadataUrlPrefix: string;
|
|
126
|
+
defaultWindowWidth: string;
|
|
127
|
+
defaultWindowHeight: string;
|
|
128
|
+
};
|
|
124
129
|
offline?: {
|
|
125
130
|
downloadStartZoom: number;
|
|
126
131
|
downloadEndZoom: number;
|
|
@@ -145,6 +150,7 @@ declare class GirafeConfig {
|
|
|
145
150
|
private initConfigBasemaps;
|
|
146
151
|
private initConfigLidar;
|
|
147
152
|
private initConfigCsv;
|
|
153
|
+
private initConfigMetadata;
|
|
148
154
|
private initConfigOffline;
|
|
149
155
|
private initConfigBookmarks;
|
|
150
156
|
private initConfigThemes;
|
|
@@ -108,6 +108,12 @@ class GirafeConfig {
|
|
|
108
108
|
writable: true,
|
|
109
109
|
value: void 0
|
|
110
110
|
});
|
|
111
|
+
Object.defineProperty(this, "metadata", {
|
|
112
|
+
enumerable: true,
|
|
113
|
+
configurable: true,
|
|
114
|
+
writable: true,
|
|
115
|
+
value: void 0
|
|
116
|
+
});
|
|
111
117
|
Object.defineProperty(this, "offline", {
|
|
112
118
|
enumerable: true,
|
|
113
119
|
configurable: true,
|
|
@@ -129,6 +135,7 @@ class GirafeConfig {
|
|
|
129
135
|
this.bookmarks = this.initConfigBookmarks(config);
|
|
130
136
|
this.lidar = this.initConfigLidar(config);
|
|
131
137
|
this.csv = this.initConfigCsv(config);
|
|
138
|
+
this.metadata = this.initConfigMetadata(config);
|
|
132
139
|
this.offline = this.initConfigOffline(config);
|
|
133
140
|
try {
|
|
134
141
|
this.search = this.initConfigSearch(config);
|
|
@@ -302,6 +309,17 @@ class GirafeConfig {
|
|
|
302
309
|
...config.csv
|
|
303
310
|
};
|
|
304
311
|
}
|
|
312
|
+
initConfigMetadata(config) {
|
|
313
|
+
const defaultConfig = {
|
|
314
|
+
metadataUrlPrefix: '',
|
|
315
|
+
defaultWindowWidth: '960px',
|
|
316
|
+
defaultWindowHeight: '460px'
|
|
317
|
+
};
|
|
318
|
+
return {
|
|
319
|
+
...defaultConfig,
|
|
320
|
+
...config.metadata
|
|
321
|
+
};
|
|
322
|
+
}
|
|
305
323
|
initConfigOffline(config) {
|
|
306
324
|
// This can be null, that's not a problem. No default value either.
|
|
307
325
|
return config.offline;
|
package/tools/state/state.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ type GraphicalInterface = {
|
|
|
18
18
|
selectionComponentVisible: boolean;
|
|
19
19
|
selectionComponent: string;
|
|
20
20
|
aboutVisible: boolean;
|
|
21
|
+
metadataVisible: boolean;
|
|
21
22
|
shareVisible: boolean;
|
|
22
23
|
darkMapMode: boolean;
|
|
23
24
|
darkFrontendMode: boolean;
|
|
@@ -69,6 +70,10 @@ export type Lidar = {
|
|
|
69
70
|
line: OlGeomLineString | null;
|
|
70
71
|
drawActive: boolean;
|
|
71
72
|
};
|
|
73
|
+
export type Metadata = {
|
|
74
|
+
title: string | null;
|
|
75
|
+
url: string | null;
|
|
76
|
+
};
|
|
72
77
|
export default class State {
|
|
73
78
|
/**
|
|
74
79
|
* This class is a used as the state of the application, which will be accessed behind a javascript proxy.
|
|
@@ -97,6 +102,7 @@ export default class State {
|
|
|
97
102
|
infobox: {
|
|
98
103
|
elements: InfoBoxContent[];
|
|
99
104
|
};
|
|
105
|
+
metadata: Metadata;
|
|
100
106
|
isOffline: boolean;
|
|
101
107
|
extendedState: Record<string, object>;
|
|
102
108
|
}
|
package/tools/state/state.js
CHANGED
|
@@ -70,6 +70,7 @@ export default class State {
|
|
|
70
70
|
selectionComponentVisible: false,
|
|
71
71
|
selectionComponent: '',
|
|
72
72
|
aboutVisible: false,
|
|
73
|
+
metadataVisible: false,
|
|
73
74
|
shareVisible: false,
|
|
74
75
|
darkMapMode: false,
|
|
75
76
|
darkFrontendMode: false
|
|
@@ -177,6 +178,15 @@ export default class State {
|
|
|
177
178
|
elements: []
|
|
178
179
|
}
|
|
179
180
|
});
|
|
181
|
+
Object.defineProperty(this, "metadata", {
|
|
182
|
+
enumerable: true,
|
|
183
|
+
configurable: true,
|
|
184
|
+
writable: true,
|
|
185
|
+
value: {
|
|
186
|
+
title: null,
|
|
187
|
+
url: null
|
|
188
|
+
}
|
|
189
|
+
});
|
|
180
190
|
// Indicates is the application is currently used in offline mode
|
|
181
191
|
Object.defineProperty(this, "isOffline", {
|
|
182
192
|
enumerable: true,
|
package/tools/themesmanager.js
CHANGED
|
@@ -241,6 +241,7 @@ class ThemesManager extends GirafeSingleton {
|
|
|
241
241
|
// Group
|
|
242
242
|
const options = {
|
|
243
243
|
isDefaultChecked: elem.metadata?.isChecked,
|
|
244
|
+
metadataUrl: elem.metadata?.metadataUrl,
|
|
244
245
|
disclaimer: elem.metadata?.disclaimer,
|
|
245
246
|
isDefaultExpanded: elem.metadata?.isExpanded,
|
|
246
247
|
isExclusiveGroup: elem.metadata?.exclusiveGroup
|