Skip to content

Commit

Permalink
feat: Allow to duplicate Site Templates - MEED-8087 - Meeds-io/MIPs#173
Browse files Browse the repository at this point in the history
… (#287)

This change will allow to duplicate Site Template including its pages
and navigation.
  • Loading branch information
boubaker authored and exo-swf committed Jan 17, 2025
1 parent 6843a7f commit 81f3d3f
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down Expand Up @@ -105,7 +104,7 @@ public SiteTemplate createSiteTemplate(
}
}

@PostMapping(value = "{siteId}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@PostMapping("{siteId}")
@Secured("users")
@Operation(summary = "Create a site template based on an existing site", method = "POST", description = "This creates a new site template based on an existing site identified by its identifier")
@ApiResponses(value = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ public SiteTemplate createSiteTemplate(SiteTemplate siteTemplate, String usernam
throw new ObjectAlreadyExistsException(String.format("Site Template with name %s already exists",
siteTemplate.getLayout()));
}
return createSiteTemplate(siteTemplate, username, true);
return createSiteTemplate(siteTemplate, null, username, true);
}

public SiteTemplate createSiteTemplate(SiteTemplate siteTemplate) {
return createSiteTemplate(siteTemplate, null, true);
return createSiteTemplate(siteTemplate, null, null, true);
}

public SiteTemplate updateSiteTemplate(SiteTemplate siteTemplate, String username) throws IllegalAccessException,
Expand Down Expand Up @@ -157,19 +157,22 @@ public SiteTemplate saveAsSiteTemplate(SiteTemplate siteTemplate, long siteId, S
throw new ObjectNotFoundException(String.format("Site with id %s doesn't exists", siteId));
} else if (!aclService.isAdministrator(username)) {
throw new IllegalAccessException();
} else if (layoutService.getPortalConfig(SiteKey.portalTemplate(siteTemplate.getLayout())) != null) {
throw new ObjectAlreadyExistsException(String.format("Site Template with name %s already exists",
siteTemplate.getLayout()));
}
siteTemplate = createSiteTemplate(siteTemplate, username, true);
// TODO skeleton method to implement in next tasks
return null;
return createSiteTemplate(siteTemplate, new SiteKey(portalConfig.getType(), portalConfig.getName()), username, true);
}

@SneakyThrows
private SiteTemplate createSiteTemplate(SiteTemplate siteTemplate,
SiteKey sourceSiteKey,
String username,
boolean broadcast) {
PortalConfig portalConfig = layoutService.getPortalConfig(SiteKey.portalTemplate(siteTemplate.getLayout()));
if (portalConfig == null) {
portalConfigService.createSiteFromTemplate(SiteKey.portalTemplate(SITE_TEMPLATE_BASE),
portalConfigService.createSiteFromTemplate(sourceSiteKey == null ? SiteKey.portalTemplate(SITE_TEMPLATE_BASE) :
sourceSiteKey,
SiteKey.portalTemplate(siteTemplate.getLayout()));
portalConfig = layoutService.getPortalConfig(SiteKey.portalTemplate(siteTemplate.getLayout()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
id="siteTemplateDrawer"
v-model="drawer"
:loading="saving"
:go-back-button="goBackButton"
allow-expand
right>
<template #title>
Expand Down Expand Up @@ -86,6 +85,7 @@
<site-template-preview
ref="siteTemplatePreview"
v-model="illustrationUploadId"
:preview-image="illustrationData"
:site-template-id="siteTemplateId" />
</div>
</template>
Expand Down Expand Up @@ -121,8 +121,8 @@ export default {
maxTitleLength: 250,
maxDescriptionLength: 1000,
illustrationUploadId: null,
illustrationData: null,
lang: eXo.env.portal.language,
goBackButton: false,
saving: false,
isNew: false,
}),
Expand All @@ -148,18 +148,20 @@ export default {
this.$root.$off('site-template-edit', this.open);
},
methods: {
open(siteTemplate, goBackButton) {
open(siteTemplate, sourceSiteId, name, nameTranslations, description, descriptionTranslations, illustrationUploadId, illustrationData) {
this.$root.$emit('close-alert-message');
this.isNew = !siteTemplate?.id;
this.goBackButton = goBackButton;
this.siteTemplate = siteTemplate && JSON.parse(JSON.stringify(siteTemplate)) || {
icon: 'fa-globe',
};
this.siteTemplateId = siteTemplate?.id || null;
this.title = siteTemplate?.name || null;
this.titleTranslations = {};
this.descriptionTranslations = {};
this.description = siteTemplate?.description || null;
this.sourceSiteId = sourceSiteId;
this.title = name || siteTemplate?.name || null;
this.titleTranslations = nameTranslations || {};
this.descriptionTranslations = descriptionTranslations || {};
this.description = description || siteTemplate?.description || null;
this.illustrationUploadId = illustrationUploadId;
this.illustrationData = illustrationData || null;
this.$refs.drawer.open();
},
close() {
Expand All @@ -171,7 +173,11 @@ export default {
let siteTemplate;
if (this.isNew) {
this.siteTemplate.layout = this.generateLayoutName(this.titleTranslations[eXo.env.portal.defaultLanguage]);
siteTemplate = await this.$siteTemplateService.createSiteTemplate(this.siteTemplate);
if (this.sourceSiteId) {
siteTemplate = await this.$siteTemplateService.saveAsSiteTemplate(this.siteTemplate, this.sourceSiteId);
} else {
siteTemplate = await this.$siteTemplateService.createSiteTemplate(this.siteTemplate);
}
} else {
siteTemplate = await this.$siteTemplateService.updateSiteTemplate(this.siteTemplate);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,14 @@ export default {
this.init();
},
methods: {
init() {
async init() {
if (this.previewImage) {
this.avatarData = this.previewImage;
this.attachments = null;
} else if (this.siteTemplateId) {
return this.$fileAttachmentService.getAttachments('siteTemplate', this.siteTemplateId)
.then(data => this.attachments = data?.attachments || []);
const data = await this.$fileAttachmentService.getAttachments('siteTemplate', this.siteTemplateId);
this.attachments = data?.attachments || [];
this.avatarData = null;
}
},
uploadFile(file) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,14 @@ export function deleteSiteTemplate(id) {
});
}

export function saveAsSiteTemplate(siteId) {
export function saveAsSiteTemplate(siteTemplate, siteId) {
return fetch(`/layout/rest/site/templates/${siteId}`, {
credentials: 'include',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Type': 'application/json',
},
body: JSON.stringify(siteTemplate),
}).then((resp) => {
if (resp?.ok) {
return resp.json();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
</v-list-item>
<v-list-item
dense
@click="duplicateSiteTemplate">
@click="duplicate">
<v-card
color="transparent"
min-width="15"
Expand Down Expand Up @@ -186,57 +186,31 @@ export default {
this.menu = false;
}
},
async duplicateSiteTemplate() {
this.loading = true;
try {
const siteTemplate = JSON.parse(JSON.stringify(this.siteTemplate));
siteTemplate.id = null;
siteTemplate.system = false;
const createdSiteTemplate = await this.$siteTemplateService.createSiteTemplate(siteTemplate);
async duplicate() {
const nameTranslations = await this.$translationService.getTranslations('siteTemplate', this.siteTemplate.id, 'title');
const descriptionTranslations = await this.$translationService.getTranslations('siteTemplate', this.siteTemplate.id, 'description');

const nameLabels = await this.$translationService.getTranslations('siteTemplate', this.siteTemplate.id, 'title');
await this.$translationService.saveTranslations('siteTemplate', createdSiteTemplate.id, 'title', nameLabels);
const bannerBlob = !this.siteTemplate.illustrationId ? null : await fetch(`${eXo.env.portal.context}/${eXo.env.portal.rest}/v1/social/attachments/siteTemplate/${this.siteTemplate.id}/${this.siteTemplate.illustrationId}`, {
credentials: 'include',
method: 'GET',
}).then(resp => resp?.ok && resp.blob());
const bannerData = bannerBlob && await this.$utils.blobToBase64(bannerBlob);
const bannerUploadId = bannerBlob && await this.$uploadService.upload(bannerBlob);

const descriptionLabels = await this.$translationService.getTranslations('siteTemplate', this.siteTemplate.id, 'description');
await this.$translationService.saveTranslations('siteTemplate', createdSiteTemplate.id, 'description', descriptionLabels);

if (this.siteTemplate.illustrationId) {
const illustrationSrc = `${eXo.env.portal.context}/${eXo.env.portal.rest}/v1/social/attachments/siteTemplate/${this.siteTemplate.id}/${this.siteTemplate.illustrationId}`;
const file = await this.getIllustrationFile(illustrationSrc);
const uploadId = await this.uploadFile(file);
await this.$fileAttachmentService.saveAttachments({
objectType: 'siteTemplate',
objectId: createdSiteTemplate.id,
uploadedFiles: [{uploadId}],
attachedFiles: [],
});
}
this.$root.$emit('site-template-edit', createdSiteTemplate);
} finally {
this.loading = false;
}
},
async uploadFile(file) {
const uploadId = await this.$uploadService.upload(file);
return await new Promise((resolve, reject) => {
const interval = window.setInterval(() => {
this.$uploadService.getUploadProgress(uploadId)
.then(percent => {
if (Number(percent) === 100) {
window.clearInterval(interval);
resolve(uploadId);
}
})
.catch(e => reject(e));
}, 200);
});
},
getIllustrationFile(src) {
return fetch(src, {
'method': 'GET',
'credentials': 'include'
})
.then(resp => resp.ok && resp.blob());
this.$root.$emit('site-template-add', {
...this.siteTemplate,
id: null,
layout: null,
illustrationId: null,
system: false,
},
this.siteTemplate.id,
nameTranslations?.[eXo.env.portal.defaultLanguage],
nameTranslations,
descriptionTranslations?.[eXo.env.portal.defaultLanguage],
descriptionTranslations,
bannerUploadId,
bannerData);
},
},
};
Expand Down

0 comments on commit 81f3d3f

Please sign in to comment.