Skip to content

Commit ebab485

Browse files
committed
feat: Export space template navigation - MEED-8705 - Meeds-io/MIPs#180 (#395)
This PR will ensure export/import space template navigation
1 parent bbc186e commit ebab485

11 files changed

+731
-79
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* This file is part of the Meeds project (https://meeds.io/).
3+
*
4+
* Copyright (C) 2020 - 2025 Meeds Association contact@meeds.io
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public License
16+
* along with this program; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18+
*/
19+
package io.meeds.layout.model;
20+
21+
import io.meeds.social.databind.model.SpaceTemplateDatabind;
22+
import lombok.AllArgsConstructor;
23+
import lombok.Data;
24+
import lombok.EqualsAndHashCode;
25+
import lombok.NoArgsConstructor;
26+
27+
import java.util.ArrayList;
28+
import java.util.List;
29+
30+
@EqualsAndHashCode(callSuper = true)
31+
@Data
32+
@AllArgsConstructor
33+
@NoArgsConstructor
34+
public class SpaceNavigationDatabind extends SpaceTemplateDatabind {
35+
36+
private List<NodeDefinition> nodeDefinitions = new ArrayList<>();
37+
38+
private List<LayoutModel> pages = new ArrayList<>();
39+
40+
private String spaceTemplateId;
41+
}

layout-service/src/main/java/io/meeds/layout/plugin/PageTemplateDatabindPlugin.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.apache.commons.codec.binary.Base64;
4040
import org.apache.commons.io.FileUtils;
4141
import org.apache.commons.lang3.StringUtils;
42+
import org.apache.commons.lang3.tuple.Pair;
4243
import org.exoplatform.social.attachment.model.UploadedAttachmentDetail;
4344
import org.exoplatform.upload.UploadResource;
4445
import org.springframework.beans.factory.annotation.Autowired;
@@ -148,12 +149,12 @@ public void serialize(String objectId, ZipOutputStream zipOutputStream, String u
148149
writeContent(zipOutputStream, objectId, jsonData);
149150
}
150151

151-
public CompletableFuture<DatabindReport> deserialize(File zipFile, Map<String, String> params, String username) {
152+
public CompletableFuture<Pair<DatabindReport, File>> deserialize(File zipFile, Map<String, String> params, String username) {
152153
return CompletableFuture.supplyAsync(() -> importPageTemplates(zipFile)).thenApply(processedTemplates -> {
153154
DatabindReport report = new DatabindReport();
154155
report.setSuccess(!processedTemplates.isEmpty());
155156
report.setProcessedItems(processedTemplates);
156-
return report;
157+
return Pair.of(report, zipFile);
157158
});
158159
}
159160

layout-service/src/main/java/io/meeds/layout/plugin/PortletInstanceDatabindPlugin.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.apache.commons.codec.binary.Base64;
3737
import org.apache.commons.io.FileUtils;
3838
import org.apache.commons.lang3.StringUtils;
39+
import org.apache.commons.lang3.tuple.Pair;
3940
import org.exoplatform.commons.file.model.FileItem;
4041
import org.exoplatform.commons.file.services.FileService;
4142
import org.exoplatform.portal.config.UserACL;
@@ -153,15 +154,15 @@ public void serialize(String objectId, ZipOutputStream zipOutputStream, String u
153154
writeContent(zipOutputStream, objectId, jsonData);
154155
}
155156

156-
public CompletableFuture<DatabindReport> deserialize(File zipFile, Map<String, String> params, String username) {
157+
public CompletableFuture<Pair<DatabindReport, File>> deserialize(File zipFile, Map<String, String> params, String username) {
157158
String categoryId = params.get("categoryId");
158159
if (categoryId != null) {
159160
return CompletableFuture.supplyAsync(() -> importPortletInstances(zipFile, Long.parseLong(categoryId)))
160161
.thenApply(processedTemplates -> {
161162
DatabindReport report = new DatabindReport();
162163
report.setSuccess(!processedTemplates.isEmpty());
163164
report.setProcessedItems(processedTemplates);
164-
return report;
165+
return Pair.of(report, zipFile);
165166
});
166167

167168
}

layout-service/src/main/java/io/meeds/layout/plugin/SectionTemplateDatabindPlugin.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.apache.commons.codec.binary.Base64;
4141
import org.apache.commons.io.FileUtils;
4242
import org.apache.commons.lang3.StringUtils;
43+
import org.apache.commons.lang3.tuple.Pair;
4344
import org.exoplatform.commons.file.model.FileItem;
4445
import org.springframework.beans.factory.annotation.Autowired;
4546
import org.springframework.core.Ordered;
@@ -153,12 +154,12 @@ public void serialize(String objectId, ZipOutputStream zipOutputStream, String u
153154
writeContent(zipOutputStream, objectId, jsonData);
154155
}
155156

156-
public CompletableFuture<DatabindReport> deserialize(File zipFile, Map<String, String> params, String username) {
157+
public CompletableFuture<Pair<DatabindReport, File>> deserialize(File zipFile, Map<String, String> params, String username) {
157158
return CompletableFuture.supplyAsync(() -> importSectionTemplates(zipFile)).thenApply(processedTemplates -> {
158159
DatabindReport report = new DatabindReport();
159160
report.setSuccess(!processedTemplates.isEmpty());
160161
report.setProcessedItems(processedTemplates);
161-
return report;
162+
return Pair.of(report, zipFile);
162163
});
163164
}
164165

layout-service/src/main/java/io/meeds/layout/plugin/SiteTemplateDatabindPlugin.java

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@
4747
import org.apache.commons.collections4.CollectionUtils;
4848
import org.apache.commons.io.FileUtils;
4949
import org.apache.commons.lang3.StringUtils;
50+
import org.apache.commons.lang3.tuple.Pair;
5051
import org.exoplatform.portal.config.model.Page;
5152
import org.exoplatform.portal.config.model.PortalConfig;
5253
import org.exoplatform.portal.mop.SiteKey;
53-
import org.exoplatform.portal.mop.State;
5454
import org.exoplatform.portal.mop.Utils;
5555
import org.exoplatform.portal.mop.Visibility;
5656
import org.exoplatform.portal.mop.navigation.*;
@@ -100,7 +100,7 @@ public class SiteTemplateDatabindPlugin implements DatabindPlugin {
100100
private SiteTemplateService siteTemplateService;
101101

102102
@Autowired
103-
LayoutService layoutService;
103+
private LayoutService layoutService;
104104

105105
@Autowired
106106
private DatabindService databindService;
@@ -132,10 +132,10 @@ public class SiteTemplateDatabindPlugin implements DatabindPlugin {
132132
private NavigationLayoutService navigationLayoutService;
133133

134134
@Autowired
135-
DescriptionService descriptionService;
135+
private DescriptionService descriptionService;
136136

137137
@Autowired
138-
PageLayoutService pageLayoutService;
138+
private PageLayoutService pageLayoutService;
139139

140140
@PostConstruct
141141
public void init() {
@@ -216,7 +216,7 @@ public void serialize(String objectId, ZipOutputStream zipOutputStream, String u
216216
if (CollectionUtils.isNotEmpty(pageContexts)) {
217217
pages = pageContexts.stream().map(this::toPage).toList();
218218
}
219-
List<NodeDefinition> nodeDefinitions = buildNodeDefinitions(siteKey);
219+
List<NodeDefinition> nodeDefinitions = buildNodeDefinitions(siteKey, username);
220220

221221
String navigationJsonData = JsonUtils.toJsonString(nodeDefinitions);
222222

@@ -235,12 +235,12 @@ public void serialize(String objectId, ZipOutputStream zipOutputStream, String u
235235
writeToZip(zipOutputStream, folderPath + "/" + NAVIGATION_JSON, navigationJsonData);
236236
}
237237

238-
public CompletableFuture<DatabindReport> deserialize(File zipFile, Map<String, String> params, String username) {
238+
public CompletableFuture<Pair<DatabindReport, File>> deserialize(File zipFile, Map<String, String> params, String username) {
239239
return CompletableFuture.supplyAsync(() -> importSiteTemplates(zipFile, username)).thenApply(processedTemplates -> {
240240
DatabindReport report = new DatabindReport();
241241
report.setSuccess(!processedTemplates.isEmpty());
242242
report.setProcessedItems(processedTemplates);
243-
return report;
243+
return Pair.of(report, zipFile);
244244
});
245245

246246
}
@@ -289,8 +289,7 @@ private Map<String, SiteTemplateDatabind> extractTemplates(File zipFile) {
289289
}
290290
templateDatabindMap.put(key, databindFromJson);
291291
}
292-
}
293-
else if (entryName.endsWith(NAVIGATION_JSON)) {
292+
} else if (entryName.endsWith(NAVIGATION_JSON)) {
294293
List<NodeDefinition> nodeDefinitions = JsonUtils.fromJsonString(jsonContent, new TypeReference<>() {
295294
});
296295
if (nodeDefinitions != null) {
@@ -302,8 +301,7 @@ else if (entryName.endsWith(NAVIGATION_JSON)) {
302301
});
303302
databind.setNodeDefinitions(nodeDefinitions);
304303
}
305-
}
306-
else if (entryName.matches(".+/pages/.+\\.json$")) {
304+
} else if (entryName.matches(".+/pages/.+\\.json$")) {
307305
LayoutModel page = JsonUtils.fromJsonString(jsonContent, LayoutModel.class);
308306
if (page != null) {
309307
String key = entryName.substring(0, entryName.indexOf("/pages/"));
@@ -428,17 +426,16 @@ private void processSiteTemplate(SiteTemplateDatabind siteTemplateDatabind, Stri
428426
List<NodeDefinition> nodeDefinitions = siteTemplateDatabind.getNodeDefinitions();
429427
if (CollectionUtils.isNotEmpty(nodeDefinitions)) {
430428
NodeDefinition targetParentNode = nodeDefinitions.getFirst();
431-
NavigationUpdateModel navigationUpdateModel = new NavigationUpdateModel(targetParentNode.getName(),
432-
getPageKey(portalConfig.getSiteKey(),
433-
targetParentNode),
434-
null,
435-
targetParentNode.getVisibility()
436-
.equals(Visibility.DISPLAYED),
437-
false,
438-
null,
439-
null,
440-
targetParentNode.getIcon(),
441-
targetParentNode.getLabels());
429+
430+
NavigationUpdateModel navigationUpdateModel = new NavigationUpdateModel();
431+
navigationUpdateModel.setNodeLabel(targetParentNode.getName());
432+
navigationUpdateModel.setPageRef(getPageKey(portalConfig.getSiteKey(), targetParentNode));
433+
navigationUpdateModel.setVisible(targetParentNode.getVisibility()
434+
.equals(Visibility.DISPLAYED));
435+
navigationUpdateModel.setScheduled(false);
436+
navigationUpdateModel.setIcon(targetParentNode.getIcon());
437+
targetParentNode.setLabels(targetParentNode.getLabels());
438+
442439
navigationLayoutService.updateNode(Long.parseLong(parentNode.getId()), navigationUpdateModel, username);
443440
parentNode.getNodes().forEach(node -> navigationLayoutService.deleteNode(Long.parseLong(node.getId())));
444441
createNodesRecursively(nodeDefinitions, parentNode.getId(), portalConfig.getSiteKey(), username);
@@ -491,7 +488,7 @@ private Page toPage(PageContext pageContext) {
491488
return page;
492489
}
493490

494-
private List<NodeDefinition> buildNodeDefinitions(SiteKey siteKey) {
491+
private List<NodeDefinition> buildNodeDefinitions(SiteKey siteKey, String username) {
495492
NavigationContext navigationContext = navigationService.loadNavigation(siteKey);
496493

497494
NodeContext<?> rootNode = navigationService.loadNode(NodeModel.SELF_MODEL, navigationContext, Scope.ALL, null);
@@ -504,34 +501,28 @@ private List<NodeDefinition> buildNodeDefinitions(SiteKey siteKey) {
504501

505502
Collection<NodeContext<?>> children = getChildren(rootNode);
506503
for (NodeContext<?> child : children) {
507-
nodeDefinitions.add(buildNodeDefinitionRecursively(child));
504+
nodeDefinitions.add(buildNodeDefinitionRecursively(child, username));
508505
}
509506
return nodeDefinitions;
510507
}
511508

512-
private NodeDefinition buildNodeDefinitionRecursively(NodeContext<?> nodeContext) {
509+
@SneakyThrows
510+
private NodeDefinition buildNodeDefinitionRecursively(NodeContext<?> nodeContext, String username) {
513511
NodeState state = nodeContext.getData().getState();
514512

515513
NodeDefinition def = new NodeDefinition();
516514
def.setName(nodeContext.getName());
517515
def.setIcon(state.getIcon());
518516
def.setVisibility(state.getVisibility());
519-
def.setPageReference(state.getPageRef().format());
520-
521-
Map<Locale, State> descriptions = descriptionService.getDescriptions(nodeContext.getId());
517+
def.setPageReference(state.getPageRef() != null ? state.getPageRef().format() : null);
522518

523-
Map<String, String> labels = new HashMap<>();
524-
if (descriptions != null) {
525-
for (Map.Entry<Locale, State> entry : descriptions.entrySet()) {
526-
labels.put(entry.getKey().toLanguageTag(), entry.getValue().getName());
527-
}
528-
}
519+
NodeLabel nodeLabel = navigationLayoutService.getNodeLabels(Long.parseLong(nodeContext.getId()), username);
529520

530-
def.setLabels(labels);
521+
def.setLabels(nodeLabel.getLabels());
531522

532523
Collection<NodeContext<?>> children = getChildren(nodeContext);
533524
for (NodeContext<?> child : children) {
534-
def.getChildren().add(buildNodeDefinitionRecursively(child));
525+
def.getChildren().add(buildNodeDefinitionRecursively(child, username));
535526
}
536527
return def;
537528
}

0 commit comments

Comments
 (0)