Skip to content

Commit

Permalink
feat: Auto assign style packages
Browse files Browse the repository at this point in the history
Refs: #64
  • Loading branch information
yurtsevich-sbb committed Sep 2, 2024
1 parent 437b1a5 commit 41e0b80
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 15 deletions.
49 changes: 48 additions & 1 deletion docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,53 @@
]
}
},
"/api/settings/style-package/suitable-names": {
"get": {
"operationId": "getSuitableStylePackageNames",
"parameters": [
{
"in": "query",
"name": "projectId",
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "spaceId",
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "documentName",
"schema": {
"type": "string"
}
}
],
"responses": {
"default": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/SettingName"
},
"type": "array"
}
}
},
"description": "default response"
}
},
"summary": "Get list of style packages suitable for a document",
"tags": [
"Settings"
]
}
},
"/api/settings/{feature}/default-content": {
"get": {
"operationId": "getDefaultValues_1",
Expand Down Expand Up @@ -1165,7 +1212,7 @@
"description": "default response"
}
},
"summary": "Returns boolean value telling if webhooks are enabled or not",
"summary": "Gets webhooks status - if they are enabled or not",
"tags": [
"Utility resources"
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public class PdfExporterFormExtension implements IFormExtension {
private static final String OPTION_SELECTED = "<option value='%s' selected";
private static final String SELECTED = "selected";

private final PdfExporterPolarionService polarionService = new PdfExporterPolarionService();

@Override
@Nullable
public String render(@NotNull IFormExtensionContext context) {
Expand All @@ -66,7 +68,7 @@ public String renderForm(@NotNull SharedContext context, @NotNull IPObject objec
String scope = ScopeUtils.getScopeFromProject(module.getProject().getId());
form = form.replace("{SCOPE_VALUE}", scope);

Collection<SettingName> stylePackageNames = getSettingNames(StylePackageSettings.FEATURE_NAME, scope);
Collection<SettingName> stylePackageNames = getSuitableStylePackages(module);
SettingName stylePackageNameToSelect = getStylePackageNameToSelect(stylePackageNames); // Either default (if exists) or first from list

form = form.replace("{STYLE_PACKAGE_OPTIONS}", generateSelectOptions(stylePackageNames, stylePackageNameToSelect != null ? stylePackageNameToSelect.getName() : null));
Expand Down Expand Up @@ -109,7 +111,7 @@ public String renderForm(@NotNull SharedContext context, @NotNull IPObject objec

private SettingName getStylePackageNameToSelect(Collection<SettingName> stylePackageNames) {
return stylePackageNames.stream()
.filter(stylePackageName -> NamedSettings.DEFAULT_NAME.equals(stylePackageName.getName()))
.filter(stylePackageName -> !NamedSettings.DEFAULT_NAME.equals(stylePackageName.getName()))
.findFirst()
.orElse(stylePackageNames.stream()
.findFirst()
Expand Down Expand Up @@ -161,6 +163,19 @@ private String adjustWebhooks(String scope, String form, StylePackageModel style
return form.replace("{WEBHOOKS_SELECTED}", noHooks ? "" : "checked");
}

private Collection<SettingName> getSuitableStylePackages(@NotNull IModule module) {
String locationPath = module.getModuleLocation().getLocationPath();
String spaceId = "";
final String documentName;
if (locationPath.contains("/")) {
spaceId = locationPath.substring(0, locationPath.lastIndexOf('/'));
documentName = locationPath.substring(locationPath.lastIndexOf('/') + 1);
} else {
documentName = locationPath;
}
return polarionService.getSuitableStylePackages(module.getProject().getId(), spaceId, documentName);
}

private Collection<SettingName> getSettingNames(@NotNull String featureName, @NotNull String scope) {
try {
return NamedSettingsRegistry.INSTANCE.getByFeatureName(featureName).readNames(scope);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ch.sbb.polarion.extension.generic.rest.filter.Secured;
import ch.sbb.polarion.extension.generic.service.PolarionService;
import ch.sbb.polarion.extension.generic.settings.SettingName;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;

import javax.ws.rs.Path;
Expand Down Expand Up @@ -39,4 +40,9 @@ public void persistCoverPageTemplate(String template, String scope) {
public void deleteImages(String coverPageName, String scope) {
polarionService.callPrivileged(() -> super.deleteImages(coverPageName, scope));
}

@Override
public Collection<SettingName> getSuitableStylePackageNames(String projectId, String spaceId, String documentName) {
return polarionService.callPrivileged(() -> super.getSuitableStylePackageNames(projectId, spaceId, documentName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ch.sbb.polarion.extension.generic.settings.SettingName;
import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.coverpage.CoverPageModel;
import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.localization.LocalizationModel;
import ch.sbb.polarion.extension.pdf.exporter.service.PdfExporterPolarionService;
import ch.sbb.polarion.extension.pdf.exporter.settings.CoverPageSettings;
import ch.sbb.polarion.extension.pdf.exporter.settings.LocalizationSettings;
import ch.sbb.polarion.extension.pdf.exporter.util.LocalizationHelper;
Expand All @@ -14,6 +15,7 @@
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataParam;

import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
Expand All @@ -38,6 +40,7 @@
public class SettingsInternalController {

private Set<String> predefinedCoverPageTemplates;
private final PdfExporterPolarionService pdfExporterPolarionService = new PdfExporterPolarionService();

@GET
@Path("/settings/localization/names/{name}/download")
Expand Down Expand Up @@ -116,4 +119,17 @@ public void persistCoverPageTemplate(@PathParam("template") String template, @Qu
public void deleteImages(@PathParam("name") String coverPageName, @QueryParam("scope") @DefaultValue("") String scope) {
new CoverPageSettings().deleteCoverPageImages(coverPageName, scope);
}

@GET
@Path("/settings/style-package/suitable-names")
@Produces(MediaType.APPLICATION_JSON)
@Tag(name = "Settings")
@Operation(summary = "Get list of style packages suitable for a document")
public Collection<SettingName> getSuitableStylePackageNames(@QueryParam("projectId") String projectId, @QueryParam("spaceId") String spaceId, @QueryParam("documentName") String documentName) {
if (projectId == null || spaceId == null || documentName == null) {
throw new BadRequestException("Parameters 'projectId', 'spaceId', 'documentName' are required'");
}
return pdfExporterPolarionService.getSuitableStylePackages(projectId, spaceId, documentName);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StylePackageModel extends SettingsModel {
private static final String MATCHING_QUERY_ENTRY_NAME = "MATCHING QUERY";
private static final String EXPOSE_SETTINGS_ENTRY_NAME = "EXPOSE SETTINGS";
private static final String COVER_PAGE_ENTRY_NAME = "COVER PAGE";
private static final String HEADER_FOOTER_ENTRY_NAME = "HEADER FOOTER";
Expand All @@ -46,6 +47,7 @@ public class StylePackageModel extends SettingsModel {
private static final String LINKED_WORKITEM_ROLES_ENTRY_NAME = "LINKED WORKITEM ROLES";
private static final String EXPOSE_PAGE_WIDTH_VALIDATION_ENTRY_NAME = "EXPOSE PAGE WIDTH VALIDATION";

private String matchingQuery;
private boolean exposeSettings;
private String coverPage;
private String headerFooter;
Expand All @@ -71,7 +73,8 @@ public class StylePackageModel extends SettingsModel {

@Override
protected String serializeModelData() {
return serializeEntry(EXPOSE_SETTINGS_ENTRY_NAME, exposeSettings) +
return serializeEntry(MATCHING_QUERY_ENTRY_NAME, matchingQuery) +
serializeEntry(EXPOSE_SETTINGS_ENTRY_NAME, exposeSettings) +
serializeEntry(COVER_PAGE_ENTRY_NAME, coverPage) +
serializeEntry(HEADER_FOOTER_ENTRY_NAME, headerFooter) +
serializeEntry(CSS_ENTRY_NAME, css) +
Expand All @@ -97,6 +100,7 @@ protected String serializeModelData() {

@Override
protected void deserializeModelData(String serializedString) {
matchingQuery = deserializeEntry(MATCHING_QUERY_ENTRY_NAME, serializedString);
exposeSettings = Boolean.parseBoolean(deserializeEntry(EXPOSE_SETTINGS_ENTRY_NAME, serializedString));
coverPage = deserializeEntry(COVER_PAGE_ENTRY_NAME, serializedString);
headerFooter = deserializeEntry(HEADER_FOOTER_ENTRY_NAME, serializedString);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package ch.sbb.polarion.extension.pdf.exporter.service;

import ch.sbb.polarion.extension.generic.service.PolarionService;
import ch.sbb.polarion.extension.generic.settings.NamedSettingsRegistry;
import ch.sbb.polarion.extension.generic.settings.SettingId;
import ch.sbb.polarion.extension.generic.settings.SettingName;
import ch.sbb.polarion.extension.generic.util.ScopeUtils;
import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.stylepackage.StylePackageModel;
import ch.sbb.polarion.extension.pdf.exporter.settings.StylePackageSettings;
import com.polarion.alm.projects.IProjectService;
import com.polarion.alm.tracker.ITrackerService;
import com.polarion.alm.tracker.model.IModule;
import com.polarion.alm.tracker.model.ITrackerProject;
import com.polarion.core.util.StringUtils;
import com.polarion.platform.IPlatformService;
import com.polarion.platform.persistence.IDataService;
import com.polarion.platform.persistence.model.IPObjectList;
import com.polarion.platform.security.ISecurityService;
import com.polarion.platform.service.repository.IRepositoryService;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;

public class PdfExporterPolarionService extends PolarionService {

public PdfExporterPolarionService() {
Expand All @@ -35,4 +45,34 @@ public ITrackerProject getProjectFromScope(String scope) {
}
return project;
}

public Collection<SettingName> getSuitableStylePackages(@NotNull String projectId, @NotNull String spaceId, @NotNull String documentName) {
StylePackageSettings stylePackageSettings = (StylePackageSettings) NamedSettingsRegistry.INSTANCE.getByFeatureName(StylePackageSettings.FEATURE_NAME);
Collection<SettingName> stylePackageNames = stylePackageSettings.readNames(ScopeUtils.getScopeFromProject(projectId));
return stylePackageNames.stream().filter(stylePackageName -> isStylePackageSuitable(projectId, spaceId, documentName, stylePackageSettings, stylePackageName)).toList();
}

@SuppressWarnings("unchecked")
private boolean isStylePackageSuitable(@NotNull String projectId, @NotNull String spaceId, @NotNull String documentName,
@NotNull StylePackageSettings stylePackageSettings, @NotNull SettingName stylePackageName) {
StylePackageModel model = stylePackageSettings.read(ScopeUtils.getScopeFromProject(projectId), SettingId.fromName(stylePackageName.getName()), null);

if (StringUtils.isEmpty(model.getMatchingQuery())) {
return true;
} else {
IDataService dataService = getTrackerService().getDataService();
IPObjectList<IModule> suitableDocuments = dataService.searchInstances(dataService.getPrototype("Module"), model.getMatchingQuery(), "name");
for (IModule suitableDocument : suitableDocuments) {
if (sameDocument(projectId, spaceId, documentName, suitableDocument)) {
return true;
}
}
return false;
}
}

private boolean sameDocument(@NotNull String projectId, @NotNull String spaceId, @NotNull String documentName, @NotNull IModule document) {
return projectId.equals(document.getProjectId()) && String.format("%s/%s", spaceId, documentName).equals(document.getModuleLocation().getLocationPath());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ function saveStylePackage() {
url: `/polarion/${SbbCommon.extension}/rest/internal/settings/${SbbCommon.setting}/names/${Configurations.getSelectedConfiguration()}/content?scope=${SbbCommon.scope}`,
contentType: 'application/json',
body: JSON.stringify({
'matchingQuery': SbbCommon.getValueById('matching-query'),
'exposeSettings': SbbCommon.getCheckboxValueById('exposeSettings'),
'coverPage': SbbCommon.getCheckboxValueById('cover-page-checkbox') ? ChildConfigurations.coverPageSelect.getSelectedValue() : null,
'css': ChildConfigurations.cssSelect.getSelectedValue(),
Expand Down Expand Up @@ -210,6 +211,10 @@ function revertToDefault() {

function setStylePackage(content) {
const stylePackage = JSON.parse(content);

SbbCommon.setValueById('matching-query', stylePackage.matchingQuery || "");
document.getElementById('matching-query-container').style.display = DEFAULT_SETTING_NAME === Configurations.getSelectedConfiguration() ? "none" : "flex";

SbbCommon.setCheckboxValueById('exposeSettings', stylePackage.exposeSettings);
SbbCommon.setCheckboxValueById('cover-page-checkbox', !!stylePackage.coverPage);
document.getElementById('cover-page-checkbox').dispatchEvent(new Event('change'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,32 @@

<jsp:include page='/common/jsp/configurations.jsp' />

<div class="content-area" style="border-top: 1px solid #ccc; margin-top: 20px; padding-top: 15px;">
<div class="content-area">
<div id="child-configs-load-error" class="style-package-error" style="display: none; margin-bottom: 15px">
There was an error loading names of children configurations. Please, contact project/system administrator to solve the issue, a style package can't be configured without them.
</div>
<div id="link-roles-load-error" class="style-package-error" style="display: none; margin-bottom: 15px">
There was an error loading link role names.
</div>

<div class='checkbox input-group'>
<label for='exposeSettings'>
<input id='exposeSettings' type='checkbox'/>
Expose style package settings to be redefined on UI
</label>
<div class="flex-container" id="matching-query-container" style="border-top: 1px solid #ccc; margin-top: 20px; padding-top: 15px;">
<p>Here you can specify a query to select documents to which this style package will be relevant. For documents not matching this query the style package won't be visible.
If you want to make this style package be available to all documents, just leave this field empty.</p>
<div class='input-group'>
<label for='matching-query'>Matching query:</label>
<input id='matching-query' style="width: 725px;"/>
</div>
</div>

<div class="flex-container" style="border-top: 1px solid #ccc; margin-top: 20px; padding-top: 15px;">
<div class="flex-column">
<div class='checkbox input-group'>
<label for='exposeSettings'>
<input id='exposeSettings' type='checkbox'/>
Expose style package settings to be redefined on UI
</label>
</div>
</div>
</div>

<div class="flex-container">
Expand Down
12 changes: 7 additions & 5 deletions src/main/resources/webapp/pdf-exporter/js/pdf-exporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,16 @@ const PdfExporter = {
this.adjustWebhooksVisibility()
]).then(() => {
return this.loadSettingNames({
setting: "style-package",
scope: this.exportContext.scope,
customUrl: `/polarion/pdf-exporter/rest/internal/settings/style-package/suitable-names?projectId=${this.exportContext.getProjectId()}`
+ `&spaceId=${this.exportContext.getSpaceId()}&documentName=${this.exportContext.getDocumentName()}`,
selectElement: document.getElementById("popup-style-package-select")
}).then(() => {
let valueToPreselect = SbbCommon.getCookie(SELECTED_STYLE_PACKAGE_COOKIE);
const stylePackageSelect = document.getElementById("popup-style-package-select");
const valueToPreselect = SbbCommon.getCookie(SELECTED_STYLE_PACKAGE_COOKIE);
if (valueToPreselect && this.containsOption(stylePackageSelect, valueToPreselect)) {
stylePackageSelect.value = valueToPreselect;
} else if (stylePackageSelect.options.length > 1) {
stylePackageSelect.value = stylePackageSelect.options[1].value;
}

this.onStylePackageChanged();
Expand All @@ -154,11 +156,11 @@ const PdfExporter = {
});
},

loadSettingNames: function ({setting, scope, selectElement}) {
loadSettingNames: function ({setting, scope, selectElement, customUrl}) {
return new Promise((resolve, reject) => {
this.callAsync({
method: "GET",
url: `/polarion/pdf-exporter/rest/internal/settings/${setting}/names?scope=${scope}`,
url: customUrl ? customUrl : `/polarion/pdf-exporter/rest/internal/settings/${setting}/names?scope=${scope}`,
responseType: "json",
}).then(({response}) => {
selectElement.innerHTML = ""; // Clear previously loaded content
Expand Down

0 comments on commit 41e0b80

Please sign in to comment.