Skip to content

Commit 6b4ce32

Browse files
authored
Merge pull request #6107 from rldhont/fix-export-enabled-layer
Fix regression: exporter disappear from layer information sub dock
2 parents 2652898 + 5a348dd commit 6b4ce32

File tree

3 files changed

+198
-3
lines changed

3 files changed

+198
-3
lines changed

assets/src/legacy/switcher-layers-actions.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,32 @@ var lizLayerActionButtons = function() {
176176
if ( 'exportLayers' in lizMap.config.options
177177
&& lizMap.config.options.exportLayers == 'True'
178178
&& featureTypes != null
179-
&& featureTypes.length != 0 ) {
179+
&& featureTypes.length != 0
180+
&& layerConfig.typename != undefined) {
180181
var exportFormats = lizMap.mainLizmap.initialConfig.vectorLayerResultFormat;
181182
var options = '';
182183
for ( const format of exportFormats ) {
183184
options += '<option value="'+format+'">'+format+'</option>';
184185
}
186+
// Check export enabled
187+
// By default, export is enabled for all layers with typename
188+
let exportEnabled = true;
189+
// If attribute layers is defined, we have to check if the publisher
190+
// has disabled export in attribute table config
191+
const attrLayersConfig = lizMap.mainLizmap.initialConfig.attributeLayers;
192+
if (attrLayersConfig !== null) {
193+
const attrLayerConfigsLen = attrLayersConfig.layerConfigs.length;
194+
const exportLayersLen = attrLayersConfig.layerConfigs.filter(attr => attr.exportEnabled).length;
195+
// If some layers have export disabled, we have to check if the current layer is in the list
196+
if (attrLayerConfigsLen != exportLayersLen) {
197+
const attrLayerConfig = attrLayersConfig.layerConfigs.find(layer => layer.id === layerConfig.id);
198+
// If the layer is not in the list, export is disabled
199+
// else export is available as definde in attribute layer config
200+
exportEnabled = (attrLayerConfig !== undefined && attrLayerConfig.exportEnabled);
201+
}
202+
}
185203
// Export layer
186-
// Only if layer is in attribute table
187-
if( options != '' && layerConfig.typename != undefined) {
204+
if( options != '' && exportEnabled) {
188205
html+= ' <dt>'+lizDict['layer.metadata.export.title']+'</dt>';
189206
html+= '<dd>';
190207
html+= '<select class="exportLayer '+isBaselayer+'">';

lizmap/modules/lizmap/lib/Project/Project.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,10 @@ public function getUpdatedConfig()
19991999
}
20002000
}
20012001

2002+
// Add export layer right
2003+
if ($this->appContext->aclCheck('lizmap.tools.layer.export', $this->repository->getKey())) {
2004+
$configJson->options->exportLayers = 'True';
2005+
}
20022006
// Set layers export permissions
20032007
$this->setLayersExportPermissions($configJson, $userGroups);
20042008

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// @ts-check
2+
import { test, expect } from '@playwright/test';
3+
import { ProjectPage } from "./pages/project";
4+
5+
test.describe('Sub dock', () => {
6+
7+
test('Metadata layer in attribute table project', async ({ page }) => {
8+
const project = new ProjectPage(page, 'attribute_table');
9+
await project.open();
10+
11+
// Display info button
12+
await expect(page.getByTestId('Les quartiers à Montpellier').locator('.icon-info-sign')).toBeHidden();
13+
await page.getByTestId('Les quartiers à Montpellier').hover();
14+
await expect(page.getByTestId('Les quartiers à Montpellier').locator('.icon-info-sign')).toBeVisible();
15+
16+
// Display sub dock metadata
17+
await expect(page.locator('#sub-dock')).toBeHidden();
18+
await page.getByTestId('Les quartiers à Montpellier').locator('.icon-info-sign').click();
19+
await expect(page.locator('#sub-dock')).toBeVisible();
20+
21+
// Check sub dock metadata content
22+
await expect(page.locator('#sub-dock .sub-metadata h3 .text')).toHaveText('Information');
23+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt')).toHaveCount(5);
24+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(0)).toHaveText('Name');
25+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(1)).toHaveText('Type');
26+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(2)).toHaveText('Zoom to the layer extent');
27+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(3)).toHaveText('Opacity');
28+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(4)).toHaveText('Export');
29+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dd')).toHaveCount(5);
30+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dd').nth(0)).toHaveText('Les quartiers à Montpellier');
31+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dd').nth(1)).toHaveText('Layer');
32+
33+
//close sub dock
34+
await expect(page.locator('#hide-sub-dock')).toBeVisible();
35+
await page.locator('#hide-sub-dock').click();
36+
await expect(page.locator('#sub-dock')).toBeHidden();
37+
38+
// Display sub dock metadata for group
39+
await page.getByTestId('relation').locator('> div.group > div.node').hover();
40+
await expect(page.getByTestId('relation').locator('> div.group > div.node .icon-info-sign')).toBeVisible();
41+
await page.getByTestId('relation').locator('> div.group > div.node .icon-info-sign').click();
42+
await expect(page.locator('#hide-sub-dock')).toBeVisible();
43+
44+
// Check sub dock metadata content
45+
await expect(page.locator('#sub-dock .sub-metadata h3 .text')).toHaveText('Information');
46+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt')).toHaveCount(4);
47+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(0)).toHaveText('Name');
48+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(1)).toHaveText('Type');
49+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(2)).toHaveText('Zoom to the layer extent');
50+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(3)).toHaveText('Opacity');
51+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dd')).toHaveCount(4);
52+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dd').nth(0)).toHaveText('relation');
53+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dd').nth(1)).toHaveText('Group');
54+
55+
//close sub dock
56+
await expect(page.locator('#hide-sub-dock')).toBeVisible();
57+
await page.locator('#hide-sub-dock').click();
58+
await expect(page.locator('#sub-dock')).toBeHidden();
59+
});
60+
61+
test('Metadata one on two layers in WFS with attribute table', async ({ page }) => {
62+
const project = new ProjectPage(page, 'permalink');
63+
await project.open();
64+
65+
// Display sub dock metadata for layer in WFS with multiple styles
66+
await page.getByTestId('sousquartiers').hover();
67+
await page.getByTestId('sousquartiers').locator('.icon-info-sign').click();
68+
await expect(page.locator('#sub-dock')).toBeVisible();
69+
70+
// Check sub dock metadata content
71+
await expect(page.locator('#sub-dock .sub-metadata h3 .text')).toHaveText('Information');
72+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt')).toHaveCount(6);
73+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(0)).toHaveText('Name');
74+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(1)).toHaveText('Type');
75+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(2)).toHaveText('Zoom to the layer extent');
76+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(3)).toHaveText('Change layer style');
77+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(4)).toHaveText('Opacity');
78+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(5)).toHaveText('Export');
79+
80+
// Display sub dock metadata for layer not in WFS and no multiple styles
81+
await page.getByTestId('Les quartiers à Montpellier').hover();
82+
await page.getByTestId('Les quartiers à Montpellier').locator('.icon-info-sign').click();
83+
await expect(page.locator('#sub-dock')).toBeVisible();
84+
85+
// Check sub dock metadata content
86+
await expect(page.locator('#sub-dock .sub-metadata h3 .text')).toHaveText('Information');
87+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt')).toHaveCount(4);
88+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(0)).toHaveText('Name');
89+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(1)).toHaveText('Type');
90+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(2)).toHaveText('Zoom to the layer extent');
91+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(3)).toHaveText('Opacity');
92+
});
93+
94+
test('Metadata one on two layers in WFS without attribute table', async ({ page }) => {
95+
// Remove attribute table config
96+
await page.route('**/service/getProjectConfig*', async route => {
97+
const response = await route.fetch();
98+
const json = await response.json();
99+
json.attributeLayers = {};
100+
await route.fulfill({ response, json });
101+
});
102+
103+
const project = new ProjectPage(page, 'permalink');
104+
await project.open();
105+
106+
// Display sub dock metadata for layer in WFS with multiple styles
107+
await page.getByTestId('sousquartiers').hover();
108+
await page.getByTestId('sousquartiers').locator('.icon-info-sign').click();
109+
await expect(page.locator('#sub-dock')).toBeVisible();
110+
111+
// Check sub dock metadata content
112+
await expect(page.locator('#sub-dock .sub-metadata h3 .text')).toHaveText('Information');
113+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt')).toHaveCount(6);
114+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(0)).toHaveText('Name');
115+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(1)).toHaveText('Type');
116+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(2)).toHaveText('Zoom to the layer extent');
117+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(3)).toHaveText('Change layer style');
118+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(4)).toHaveText('Opacity');
119+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(5)).toHaveText('Export');
120+
121+
// Display sub dock metadata for layer not in WFS and no multiple styles
122+
await page.getByTestId('Les quartiers à Montpellier').hover();
123+
await page.getByTestId('Les quartiers à Montpellier').locator('.icon-info-sign').click();
124+
await expect(page.locator('#sub-dock')).toBeVisible();
125+
126+
// Check sub dock metadata content
127+
await expect(page.locator('#sub-dock .sub-metadata h3 .text')).toHaveText('Information');
128+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt')).toHaveCount(4);
129+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(0)).toHaveText('Name');
130+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(1)).toHaveText('Type');
131+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(2)).toHaveText('Zoom to the layer extent');
132+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(3)).toHaveText('Opacity');
133+
});
134+
135+
test('Metadata one on two layers in WFS with export disable in attribute table', async ({ page }) => {
136+
// Remove attribute table config
137+
await page.route('**/service/getProjectConfig*', async route => {
138+
const response = await route.fetch();
139+
const json = await response.json();
140+
json.attributeLayers.sousquartiers.export_enabled = 'False';
141+
await route.fulfill({ response, json });
142+
});
143+
144+
const project = new ProjectPage(page, 'permalink');
145+
await project.open();
146+
147+
// Display sub dock metadata for layer in WFS with multiple styles
148+
await page.getByTestId('sousquartiers').hover();
149+
await page.getByTestId('sousquartiers').locator('.icon-info-sign').click();
150+
await expect(page.locator('#sub-dock')).toBeVisible();
151+
152+
// Check sub dock metadata content
153+
await expect(page.locator('#sub-dock .sub-metadata h3 .text')).toHaveText('Information');
154+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt')).toHaveCount(5);
155+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(0)).toHaveText('Name');
156+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(1)).toHaveText('Type');
157+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(2)).toHaveText('Zoom to the layer extent');
158+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(3)).toHaveText('Change layer style');
159+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(4)).toHaveText('Opacity');
160+
161+
// Display sub dock metadata for layer not in WFS and no multiple styles
162+
await page.getByTestId('Les quartiers à Montpellier').hover();
163+
await page.getByTestId('Les quartiers à Montpellier').locator('.icon-info-sign').click();
164+
await expect(page.locator('#sub-dock')).toBeVisible();
165+
166+
// Check sub dock metadata content
167+
await expect(page.locator('#sub-dock .sub-metadata h3 .text')).toHaveText('Information');
168+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt')).toHaveCount(4);
169+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(0)).toHaveText('Name');
170+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(1)).toHaveText('Type');
171+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(2)).toHaveText('Zoom to the layer extent');
172+
await expect(page.locator('#sub-dock .sub-metadata .menu-content dt').nth(3)).toHaveText('Opacity');
173+
});
174+
});

0 commit comments

Comments
 (0)