Some typos fixed, base classes for asset edit steps

pull/10/head
Jens Pelzetter 2021-05-14 11:39:01 +02:00
parent cf79f39a7a
commit bf62007391
27 changed files with 829 additions and 72 deletions

View File

@ -34,6 +34,7 @@ import org.librecms.contentsection.FolderManager;
import org.librecms.contentsection.FolderRepository; import org.librecms.contentsection.FolderRepository;
import org.librecms.contentsection.FolderType; import org.librecms.contentsection.FolderType;
import org.librecms.contentsection.privileges.AssetPrivileges; import org.librecms.contentsection.privileges.AssetPrivileges;
import org.librecms.ui.contentsections.assets.MvcAssetCreateStep;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -44,6 +45,8 @@ import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject; import javax.inject.Inject;
import javax.mvc.Controller; import javax.mvc.Controller;
import javax.mvc.Models; import javax.mvc.Models;
@ -154,6 +157,10 @@ public class AssetFolderController {
@Inject @Inject
private Models models; private Models models;
@Inject
@Any
private Instance<MvcAssetCreateStep<?>> assetCreateSteps;
/** /**
* Performs operations on permissions. * Performs operations on permissions.
*/ */
@ -267,6 +274,17 @@ public class AssetFolderController {
assetFolderTree.buildFolderTree(section, folder) assetFolderTree.buildFolderTree(section, folder)
); );
contentSectionModel.setAvailableAssetTypes(
assetCreateSteps
.stream()
.collect(
Collectors.toMap(
step -> step.getAssetType(),
step -> step.getLabel()
)
)
);
assetFolderModel.setRows( assetFolderModel.setRows(
folderEntries folderEntries
.stream() .stream()

View File

@ -145,6 +145,14 @@ public class AssetFolderModel {
this.path = path; this.path = path;
} }
public String getPathWithTrailingSlash() {
if (path.isEmpty()) {
return "";
} else {
return String.format("%s/", path);
}
}
public boolean isCanCreateSubFolders() { public boolean isCanCreateSubFolders() {
return canCreateSubFolders; return canCreateSubFolders;
} }

View File

@ -202,7 +202,7 @@ public class AssetPermissionsChecker {
* {@link AssetPrivileges#EDIT} privilege for the provided * {@link AssetPrivileges#EDIT} privilege for the provided
* {@link Asset} to the current user, {@code false} otherwise. * {@link Asset} to the current user, {@code false} otherwise.
*/ */
public boolean canEditAssets(final Asset asset) { public boolean canEditAsset(final Asset asset) {
return permissionChecker.isPermitted( return permissionChecker.isPermitted(
AssetPrivileges.EDIT, asset AssetPrivileges.EDIT, asset
); );

View File

@ -91,7 +91,7 @@ public class AssetPermissionsModelProvider {
permissionChecker.canDeleteAssets(asset) permissionChecker.canDeleteAssets(asset)
); );
model.setGrantedEdit( model.setGrantedEdit(
permissionChecker.canEditAssets(asset) permissionChecker.canEditAsset(asset)
); );
model.setGrantedUse( model.setGrantedUse(
permissionChecker.canUseAssets(asset) permissionChecker.canUseAssets(asset)

View File

@ -71,6 +71,8 @@ public class ContentSectionModel {
private Map<String, String> availableDocumentTypes; private Map<String, String> availableDocumentTypes;
private Map<String, String> availableAssetTypes;
/** /**
* *
* *
@ -129,6 +131,16 @@ public class ContentSectionModel {
= new LinkedHashMap<>(availableDocumentTypes); = new LinkedHashMap<>(availableDocumentTypes);
} }
public Map<String, String> getAvailableAssetTypes() {
return Collections.unmodifiableMap(availableAssetTypes);
}
protected void setAvailableAssetTypes(
final Map<String, String> availableAssetTypes
) {
this.availableAssetTypes = new LinkedHashMap<>(availableAssetTypes);
}
/** /**
* Can the current user administer the categories of the domains/category * Can the current user administer the categories of the domains/category
* sytems assigned to the section? * sytems assigned to the section?

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA * MA 02110-1301 USA
*/ */
package org.librecms.ui.contentsections.documents; package org.librecms.ui.contentsections;
/** /**
* Used by the {@link MvcAuthoringStepService} to indicate that the requested * Used by the {@link MvcAuthoringStepService} to indicate that the requested
@ -39,7 +39,7 @@ public class ContentSectionNotFoundException extends Exception {
* *
* @param errorMessageTemplate Template for the error message. * @param errorMessageTemplate Template for the error message.
*/ */
ContentSectionNotFoundException(final String errorMessageTemplate) { public ContentSectionNotFoundException(final String errorMessageTemplate) {
super(); super();
this.errorMessageTemplate = errorMessageTemplate; this.errorMessageTemplate = errorMessageTemplate;
} }
@ -51,7 +51,7 @@ public class ContentSectionNotFoundException extends Exception {
* @param msg The detail message. * @param msg The detail message.
* @param errorMessageTemplate Template for the error message. * @param errorMessageTemplate Template for the error message.
*/ */
ContentSectionNotFoundException( public ContentSectionNotFoundException(
final String errorMessageTemplate, final String msg final String errorMessageTemplate, final String msg
) { ) {
super(msg); super(msg);

View File

@ -0,0 +1,315 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.ui.contentsections.assets;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.contentsection.Asset;
import org.librecms.contentsection.AssetManager;
import org.librecms.contentsection.AssetRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.ui.contentsections.AssetPermissionsChecker;
import org.librecms.ui.contentsections.ContentSectionModel;
import org.librecms.ui.contentsections.ContentSectionsUi;
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
import javax.mvc.Models;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.UriBuilder;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public abstract class AbstractMvcAssetEditStep implements MvcAssetEditStep {
@Inject
private AssetUi assetUi;
@Inject
private AssetManager assetManager;
@Inject
private AssetPermissionsChecker assetPermissionsChecker;
@Inject
private AssetRepository assetRepo;
@Inject
private GlobalizationHelper globalizationHelper;
@Inject
private ContentSectionModel sectionModel;
@Inject
private ContentSectionsUi sectionsUi;
@Inject
private HttpServletRequest request;
@Inject
private Models models;
@Inject
private SelectedAssetModel assetModel;
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
private String sectionIdentifier;
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
private String assetPathParam;
private ContentSection contentSection;
private Asset asset;
private String assetPath;
private String stepPath;
protected void init() throws ContentSectionNotFoundException,
AssetNotFoundException {
contentSection = sectionsUi
.findContentSection(sectionIdentifier)
.orElseThrow(
() -> new ContentSectionNotFoundException(
sectionsUi.showContentSectionNotFound(sectionIdentifier),
String.format(
"ContentSection %s not found.",
sectionIdentifier
)
)
);
sectionModel.setSection(contentSection);
asset = assetRepo
.findByPath(contentSection, assetPathParam)
.orElseThrow(
() -> new AssetNotFoundException(
assetUi.showAssetNotFound(
contentSection, assetPathParam
),
String.format(
"No asset for path %s found in section %s.",
assetPathParam,
contentSection.getLabel()
)
)
);
assetModel.setAsset(asset);
assetPath = assetManager.getAssetPath(asset);
final Map<String, String> values = new HashMap<>();
values.put(
MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM,
contentSection.getLabel()
);
values.put(
MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME,
assetPath
);
stepPath = Optional
.ofNullable(getStepClass().getAnnotation(Path.class))
.map(Path::value)
.map(
path -> UriBuilder
.fromPath(path)
.buildFromMap(values)
.toString()
)
.orElse("");
models.put("activeAssetTab", "editTab");
models.put("stepPath", stepPath);
}
@Override
public ContentSection getContentSection() {
return Optional
.ofNullable(contentSection)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Edit step %s was not initialized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAssetEditStep.class.getName()
)
)
);
}
@Override
public Asset getAsset() {
return Optional
.ofNullable(asset)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Edit step %s was not initialized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAssetEditStep.class.getName()
)
)
);
}
@Override
public String getAssetPath() {
return Optional
.ofNullable(assetPath)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Edit step %s was not initialized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAssetEditStep.class.getName()
)
)
);
}
@Override
public boolean getCanEdit() {
return assetPermissionsChecker.canEditAsset(asset);
}
@Override
public void updateAssetPath() {
assetPath = assetManager.getAssetPath(asset).substring(1); // Without leading slash
}
@Override
public String getStepPath() {
return stepPath;
}
@Override
public String buildRedirectPathForStep() {
final ContentSection section = Optional
.ofNullable(contentSection)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Edit Step %s was not initalized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAssetEditStep.class.getName()
)
)
);
final String assetPathNonNull = Optional
.ofNullable(assetPath)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Edit step %s was not initialized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAssetEditStep.class.getName()
)
)
);
final Map<String, String> values = new HashMap<>();
values.put(
MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM,
section.getLabel()
);
values.put(
MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME,
assetPathNonNull
);
return Optional
.ofNullable(getStepClass().getAnnotation(Path.class))
.map(Path::value)
.map(
path -> UriBuilder
.fromPath(path)
.buildFromMap(values)
.toString()
)
.map(path -> String.format("redirect:%s", path))
.orElse("");
}
@Override
public String buildRedirectPathForStep(final String subPath) {
final ContentSection section = Optional
.ofNullable(contentSection)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Edit Step %s was not initalized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAssetEditStep.class.getName()
)
)
);
final String assetPathNonNull = Optional
.ofNullable(assetPath)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Edit step %s was not initialized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAssetEditStep.class.getName()
)
)
);
final Map<String, String> values = new HashMap<>();
values.put(
MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM,
section.getLabel()
);
values.put(
MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME,
assetPathNonNull
);
return Optional
.ofNullable(getStepClass().getAnnotation(Path.class))
.map(Path::value)
.map(
path -> UriBuilder
.fromPath(path)
.path(subPath)
.buildFromMap(values)
.toString()
)
.map(path -> String.format("redirect:%s", path))
.orElse("");
}
}

View File

@ -75,12 +75,12 @@ public class AssetEditStepsValidator {
return false; return false;
} }
if (stepClass.getAnnotation(MvcAssetEditStep.class) == null) { if (stepClass.getAnnotation(MvcAssetEditStepDef.class) == null) {
LOGGER.warn( LOGGER.warn(
"Class {} is part of a set of asset edit steps, but is not " "Class {} is part of a set of asset edit steps, but is not "
+ "annotated with {}. The class will be ignored.", + "annotated with {}. The class will be ignored.",
stepClass.getName(), stepClass.getName(),
MvcAssetEditStep.class MvcAssetEditStepDef.class
); );
} }
@ -89,7 +89,7 @@ public class AssetEditStepsValidator {
public boolean supportsAsset(final Class<?> stepClass, final Asset asset) { public boolean supportsAsset(final Class<?> stepClass, final Asset asset) {
return Optional return Optional
.ofNullable(stepClass.getAnnotation(MvcAssetEditStep.class)) .ofNullable(stepClass.getAnnotation(MvcAssetEditStepDef.class))
.map( .map(
stepAnnotation -> asset.getClass().isAssignableFrom( stepAnnotation -> asset.getClass().isAssignableFrom(
stepAnnotation.supportedAssetType() stepAnnotation.supportedAssetType()
@ -97,8 +97,8 @@ public class AssetEditStepsValidator {
) )
.orElse(false); .orElse(false);
// final MvcAssetEditStep stepAnnotation = stepClass.getAnnotation( // final MvcAssetEditStepDef stepAnnotation = stepClass.getAnnotation(
// MvcAssetEditStep.class // MvcAssetEditStepDef.class
// ); // );
// //
// if (stepAnnotation == null) { // if (stepAnnotation == null) {

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.ui.contentsections.assets;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class AssetNotFoundException extends Exception {
private static final long serialVersionUID = 1L;
private final String errorMessageTemplate;
public AssetNotFoundException(final String errorMessageTemplate) {
super();
this.errorMessageTemplate = errorMessageTemplate;
}
public AssetNotFoundException(
final String errorMessageTemplate, final String msg
) {
super(msg);
this.errorMessageTemplate = errorMessageTemplate;
}
public String showErrorMessage() {
return errorMessageTemplate;
}
}

View File

@ -67,6 +67,15 @@ public interface MvcAssetCreateStep<T extends Asset> {
*/ */
String getAssetType(); String getAssetType();
/**
* Localized label of the asset type. The current locale as returned by
* {@link GlobalizationHelper#getNegotiatedLocale()} should be used to
* select the language variant to return.
*
* @return The localized label of the asset type.
*/
String getLabel();
/** /**
* Localized description of the create step. The current locale as returned * Localized description of the create step. The current locale as returned
* by {@link GlobalizationHelper#getNegotiatedLocale()} should be used to * by {@link GlobalizationHelper#getNegotiatedLocale()} should be used to

View File

@ -19,50 +19,51 @@
package org.librecms.ui.contentsections.assets; package org.librecms.ui.contentsections.assets;
import org.librecms.contentsection.Asset; import org.librecms.contentsection.Asset;
import org.librecms.contentsection.ContentSection;
import java.lang.annotation.ElementType; import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* Metadata of an edit step for assets.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@Target(ElementType.TYPE) public interface MvcAssetEditStep {
@Retention(RetentionPolicy.RUNTIME)
public @interface MvcAssetEditStep { Class<? extends MvcAssetEditStep> getStepClass();
ContentSection getContentSection() throws ContentSectionNotFoundException;
Asset getAsset() throws ContentSectionNotFoundException,
AssetNotFoundException;
String getAssetPath() throws ContentSectionNotFoundException,
AssetNotFoundException;
/** /**
* The name of the resource bundle providing the localized values for * Can the current user edit the asset. This method MUST only return
* {@link #labelKey} and {@link descriptionKey}.
* *
* @return The resource bundle providing the localized labelKey and * @return {@code true} if the current user can edit the asset, {
* descriptionKey. *
* @false} otherwise.
*/ */
String bundle(); boolean getCanEdit();
/** /**
* The key for the localized description of the step. * If an edit step alters the name of the asset and therefore the path of
* the asset, the step MUST call this method to update the asset path used
* by the step.
* *
* @return The key for the localized description of the step. * @throws ContentSectionNotFoundException
* @throws AssetNotFoundException
*/ */
String descriptionKey(); void updateAssetPath() throws ContentSectionNotFoundException,
AssetNotFoundException;
/** String getStepPath();
* The key for the localized label of the authoring step..
*
* @return The key for the localized label of the authoring step...
*/
String labelKey();
/** String buildRedirectPathForStep() throws ContentSectionNotFoundException,
* Edit steps only support a specific type, and all subtypes. AssetNotFoundException;
*
* @return The asset type supported by the edit step.
*/
Class<? extends Asset> supportedAssetType(); String buildRedirectPathForStep(final String subPath)
throws ContentSectionNotFoundException, AssetNotFoundException;
} }

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.ui.contentsections.assets;
import org.librecms.contentsection.Asset;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Metadata of an edit step for assets.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MvcAssetEditStepDef {
/**
* The name of the resource bundle providing the localized values for
* {@link #labelKey} and {@link descriptionKey}.
*
* @return The resource bundle providing the localized labelKey and
* descriptionKey.
*/
String bundle();
/**
* The key for the localized description of the step.
*
* @return The key for the localized description of the step.
*/
String descriptionKey();
/**
* The key for the localized label of the authoring step..
*
* @return The key for the localized label of the authoring step...
*/
String labelKey();
/**
* Edit steps only support a specific type, and all subtypes.
*
* @return The asset type supported by the edit step.
*/
Class<? extends Asset> supportedAssetType();
}

View File

@ -0,0 +1,174 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.ui.contentsections.assets;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.security.AuthorizationRequired;
import org.librecms.assets.PostalAddress;
import org.librecms.contentsection.AssetManager;
import org.librecms.contentsection.AssetRepository;
import java.util.Locale;
import java.util.Map;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("CmsPostalAddressCreateStep")
public class PostalAddressCreateStep
extends AbstractMvcAssetCreateStep<PostalAddress> {
private static final String FORM_PARAMS_NAME = "name";
private static final String FORM_PARAMS_TITLE = "title";
private static final String FORM_PARAM_INITIAL_LOCALE = "locale";
@Inject
private AssetManager assetManager;
@Inject
private AssetRepository assetRepo;
@Inject
private GlobalizationHelper globalizationHelper;
@Override
public String showCreateStep() {
return "/org/librecms/ui/assets/postaladdress/create-postaladdress.xhtml";
}
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String createAsset(final Map<String, String[]> formParams) {
if (!formParams.containsKey(FORM_PARAMS_NAME)
|| formParams.get(FORM_PARAMS_NAME) == null
|| formParams.get(FORM_PARAMS_NAME).length == 0) {
addMessage(
"danger",
globalizationHelper
.getLocalizedTextsUtil(getBundle())
.getText("postaladdress.createstep.name.error.missing")
);
return showCreateStep();
}
final String name = formParams.get(FORM_PARAMS_NAME)[0];
if (!name.matches("^([a-zA-Z0-9_-]*)$")) {
addMessage(
"danger",
globalizationHelper
.getLocalizedTextsUtil(getBundle())
.getText("postaladdress.createstep.name.error.invalid")
);
return showCreateStep();
}
if (!formParams.containsKey(FORM_PARAMS_TITLE)
|| formParams.get(FORM_PARAMS_TITLE) == null
|| formParams.get(FORM_PARAMS_TITLE).length == 0) {
addMessage(
"danger",
globalizationHelper
.getLocalizedTextsUtil(getBundle())
.getText("postaladdress.createstep.title.error.missing")
);
return showCreateStep();
}
final String title = formParams.get(FORM_PARAMS_TITLE)[0];
if (!formParams.containsKey(FORM_PARAM_INITIAL_LOCALE)
|| formParams.get(FORM_PARAM_INITIAL_LOCALE) == null
|| formParams.get(FORM_PARAM_INITIAL_LOCALE).length == 0) {
addMessage(
"danger",
globalizationHelper.getLocalizedTextsUtil(
getBundle()
).getText("createstep.initial_locale.error.missing")
);
return showCreateStep();
}
final Locale locale = new Locale(
formParams.get(FORM_PARAM_INITIAL_LOCALE)[0]
);
final String address = formParams.get("address")[0];
final String postalCode = formParams.get("postalCode")[0];
final String city = formParams.get("city")[0];
final String state = formParams.get("state")[0];
final String isoCountryCode = formParams.get("isoCountryCode")[0];
final PostalAddress postalAddress = assetManager.createAsset(
name,
title,
locale,
getFolder(),
PostalAddress.class
);
postalAddress.setAddress(address);
postalAddress.setPostalCode(postalCode);
postalAddress.setCity(city);
postalAddress.setState(state);
postalAddress.setIsoCountryCode(isoCountryCode);
assetRepo.save(postalAddress);
return String.format(
"redirect:/%s/assets/%s/%s/@postaladdress-edit",
getContentSectionLabel(),
getFolderPath(),
name
);
}
@Override
public String getAssetType() {
return PostalAddress.class.getName();
}
@Override
public String getLabel() {
return globalizationHelper
.getLocalizedTextsUtil(getBundle())
.getText("postal_address.label");
}
@Override
public String getDescription() {
return globalizationHelper
.getLocalizedTextsUtil(getBundle())
.getText("postal_address.description");
}
@Override
public String getBundle() {
return MvcAssetStepsConstants.BUNDLE;
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.ui.contentsections.assets;
import org.librecms.assets.PostalAddress;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import javax.mvc.Controller;
import javax.ws.rs.Path;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Path(MvcAssetEditSteps.PATH_PREFIX + "postaladdress-edit")
@Controller
@Named("CmsPostalAddressEditStep")
@MvcAssetEditStepDef(
bundle = MvcAssetStepsConstants.BUNDLE,
descriptionKey = "postaladdress.editstep.description",
labelKey = "postaladdress.editstep.label",
supportedAssetType = PostalAddress.class
)
public class PostalAddressEditStep {
}

View File

@ -18,6 +18,7 @@
*/ */
package org.librecms.ui.contentsections.documents; package org.librecms.ui.contentsections.documents;
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.hibernate.LazyInitializationException; import org.hibernate.LazyInitializationException;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
@ -109,7 +110,8 @@ public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
sectionsUi.showContentSectionNotFound(sectionIdentifier), sectionsUi.showContentSectionNotFound(sectionIdentifier),
String.format( String.format(
"ContentSection %s not found.", "ContentSection %s not found.",
sectionIdentifier) sectionIdentifier
)
) )
); );
sectionModel.setSection(contentSection); sectionModel.setSection(contentSection);
@ -119,9 +121,10 @@ public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
.orElseThrow( .orElseThrow(
() -> new DocumentNotFoundException( () -> new DocumentNotFoundException(
documentUi.showDocumentNotFound( documentUi.showDocumentNotFound(
contentSection, documentPathParam), contentSection, documentPathParam
),
String.format( String.format(
"Not document for path %s in section %s.", "No document for path %s in section %s.",
documentPathParam, documentPathParam,
contentSection.getLabel() contentSection.getLabel()
) )
@ -129,8 +132,8 @@ public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
); );
documentModel.setContentItem(document); documentModel.setContentItem(document);
this.documentPath = itemManager.getItemPath(document); documentPath = itemManager.getItemPath(document);
final Map<String, String> values = new HashMap<>(); final Map<String, String> values = new HashMap<>();
values.put( values.put(
MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM, MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM,
contentSection.getLabel() contentSection.getLabel()
@ -356,11 +359,4 @@ public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
.orElse(""); .orElse("");
} }
private String withoutLeadingSlash(final String path) {
if (path.startsWith("/")) {
return path.substring(1);
} else {
return path;
}
}
} }

View File

@ -18,6 +18,7 @@
*/ */
package org.librecms.ui.contentsections.documents; package org.librecms.ui.contentsections.documents;
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.libreccm.api.Identifier; import org.libreccm.api.Identifier;
import org.libreccm.api.IdentifierParser; import org.libreccm.api.IdentifierParser;
import org.libreccm.categorization.Category; import org.libreccm.categorization.Category;

View File

@ -18,6 +18,7 @@
*/ */
package org.librecms.ui.contentsections.documents; package org.librecms.ui.contentsections.documents;
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;

View File

@ -18,6 +18,7 @@
*/ */
package org.librecms.ui.contentsections.documents; package org.librecms.ui.contentsections.documents;
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager; import org.librecms.contentsection.ContentItemManager;

View File

@ -18,6 +18,7 @@
*/ */
package org.librecms.ui.contentsections.documents; package org.librecms.ui.contentsections.documents;
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.libreccm.api.Identifier; import org.libreccm.api.Identifier;
import org.libreccm.api.IdentifierParser; import org.libreccm.api.IdentifierParser;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;

View File

@ -179,9 +179,9 @@ public class MvcArticleCreateStep
|| formParams.get(FORM_PARAM_NAME).length == 0) { || formParams.get(FORM_PARAM_NAME).length == 0) {
addMessage( addMessage(
"danger", "danger",
globalizationHelper.getLocalizedTextsUtil( globalizationHelper
getBundle() .getLocalizedTextsUtil(getBundle())
).getText("createstep.name.error.missing") .getText("createstep.name.error.missing")
); );
return showCreateStep(); return showCreateStep();
} }
@ -190,9 +190,9 @@ public class MvcArticleCreateStep
if (!name.matches("^([a-zA-Z0-9_-]*)$")) { if (!name.matches("^([a-zA-Z0-9_-]*)$")) {
addMessage( addMessage(
"danger", "danger",
globalizationHelper.getLocalizedTextsUtil( globalizationHelper
getBundle() .getLocalizedTextsUtil(getBundle())
).getText("createstep.name.error.invalid") .getText("createstep.name.error.invalid")
); );
return showCreateStep(); return showCreateStep();
} }
@ -202,9 +202,9 @@ public class MvcArticleCreateStep
|| formParams.get(FORM_PARAM_TITLE).length == 0) { || formParams.get(FORM_PARAM_TITLE).length == 0) {
addMessage( addMessage(
"danger", "danger",
globalizationHelper.getLocalizedTextsUtil( globalizationHelper
getBundle() .getLocalizedTextsUtil(getBundle())
).getText("createstep.title.error.missing") .getText("createstep.title.error.missing")
); );
return showCreateStep(); return showCreateStep();
} }
@ -215,9 +215,9 @@ public class MvcArticleCreateStep
|| formParams.get(FORM_PARAM_SUMMARY).length == 0) { || formParams.get(FORM_PARAM_SUMMARY).length == 0) {
addMessage( addMessage(
"danger", "danger",
globalizationHelper.getLocalizedTextsUtil( globalizationHelper
getBundle() .getLocalizedTextsUtil(getBundle())
).getText("createstep.summary.error.missing") .getText("createstep.summary.error.missing")
); );
return showCreateStep(); return showCreateStep();
} }
@ -292,6 +292,4 @@ public class MvcArticleCreateStep
); );
} }
} }

View File

@ -26,7 +26,7 @@ import org.librecms.contentsection.FolderManager;
import org.librecms.contenttypes.Article; import org.librecms.contenttypes.Article;
import org.librecms.ui.contentsections.ItemPermissionChecker; import org.librecms.ui.contentsections.ItemPermissionChecker;
import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep; import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep;
import org.librecms.ui.contentsections.documents.ContentSectionNotFoundException; import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentNotFoundException; import org.librecms.ui.contentsections.documents.DocumentNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentUi; import org.librecms.ui.contentsections.documents.DocumentUi;
import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef; import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;

View File

@ -30,7 +30,7 @@ import org.librecms.contenttypes.Article;
import org.librecms.ui.contentsections.ItemPermissionChecker; import org.librecms.ui.contentsections.ItemPermissionChecker;
import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep; import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep;
import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow; import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow;
import org.librecms.ui.contentsections.documents.ContentSectionNotFoundException; import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentNotFoundException; import org.librecms.ui.contentsections.documents.DocumentNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentUi; import org.librecms.ui.contentsections.documents.DocumentUi;

View File

@ -188,10 +188,55 @@
</c:choose> </c:choose>
<c:choose> <c:choose>
<c:when test="#{AssetFolderModel.canCreateAssets}"> <c:when test="#{AssetFolderModel.canCreateAssets}">
<button class="btn btn-primary" title="#{CmsAdminMessages['contentsection.assetfolder.add_asset']}"> <button class="btn btn-primary"
data-toggle="modal"
data-target="#new-asset-dialog"
title="#{CmsAdminMessages['contentsection.assetfolder.add_asset']}">
<bootstrap:svgIcon icon="file-earmark-plus" /> <bootstrap:svgIcon icon="file-earmark-plus" />
<span class="sr-only">#{CmsAdminMessages['contentsection.assetfolder.add_asset']}</span> <span class="sr-only">#{CmsAdminMessages['contentsection.assetfolder.add_asset']}</span>
</button> </button>
<div aria-hidden="true"
aria-labelledby="new-asset-dialog-title"
class="modal fade"
id="new-asset-dialog">
<div class="modal-dialog">
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{AssetFolderModel.pathWithTrailingSlash}@create"
class="modal-content"
method="post">
<div class="modal-header">
<h2 class="modal-title"
id="new-asset-dialog-title">
#{CmsAdminMessages['contentsection.assetfolder.new_asset_dialog.title']}
</h2>
<button aria-label="#{CmsAdminMessages['contentsection.assetfolder.new_asset_dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<bootstrap:svgIcon icon="x" />
</button>
</div>
<div class="modal-body">
<bootstrap:formGroupSelect
help="#{CmsAdminMessages['contentsection.assetfolder.new_asset_dialog.assettype.help']}"
inputId="assetType"
label="#{CmsAdminMessages['contentsection.assetfolder.new_asset_dialog.assettype.label']}"
name="assetType"
options="#{ContentSectionModel.availableAssetTypes}" />
</div>
<div class="modal-footer">
<button class="btn btn-warning"
data-dismiss="modal"
type="button">
#{CmsAdminMessages['contentsection.assetfolder.new_asset_dialog.close']}
</button>
<button class="btn btn-success"
type="submit">
#{CmsAdminMessages['contentsection.assetfolder.new_asset_dialog.submit']}
</button>
</div>
</form>
</div>
</div>
</c:when> </c:when>
<c:otherwise> <c:otherwise>
<button class="btn btn-primary" <button class="btn btn-primary"
@ -263,7 +308,7 @@
id="rename-folder-#{row.name}-dialog-title"> id="rename-folder-#{row.name}-dialog-title">
#{CmsAdminMessages.getMessage('contentsection.assetfolder.rename_folder_dialog.title', [row.folderPath])} #{CmsAdminMessages.getMessage('contentsection.assetfolder.rename_folder_dialog.title', [row.folderPath])}
</h2> </h2>
<button aria-label="#{CmsMessages['contentsection.assetfolder.rename_folder_dialog.close']}" <button aria-label="#{CmsAdminMessages['contentsection.assetfolder.rename_folder_dialog.close']}"
class="close" class="close"
data-dismiss="modal" data-dismiss="modal"
type="button" > type="button" >

View File

@ -777,3 +777,9 @@ edit_button.label=Edit
save_button.label=Save save_button.label=Save
text.edit.dialog.title=Edit localized variant text.edit.dialog.title=Edit localized variant
text.editor.no_localized_values=No localized variants available yet. text.editor.no_localized_values=No localized variants available yet.
contentsection.assetfolder.types.folder=Folder
contentsection.assetfolder.new_asset_dialog.close=Cancel
contentsection.assetfolder.new_asset_dialog.title=Create new asset
contentsection.assetfolder.new_asset_dialog.assettype.help=Select the type of the new asset.
contentsection.assetfolder.new_asset_dialog.assettype.label=Type
contentsection.assetfolder.new_asset_dialog.submit=Create asset

View File

@ -778,3 +778,9 @@ edit_button.label=Bearbeiten
save_button.label=Speichern save_button.label=Speichern
text.edit.dialog.title=Lokalisierte Variante bearbeiten text.edit.dialog.title=Lokalisierte Variante bearbeiten
text.editor.no_localized_values=Es wurden noch keine lokalisierten Varianten angelegt text.editor.no_localized_values=Es wurden noch keine lokalisierten Varianten angelegt
contentsection.assetfolder.types.folder=Ordner
contentsection.assetfolder.new_asset_dialog.close=Abbrechen
contentsection.assetfolder.new_asset_dialog.title=Neues Asset erstellen
contentsection.assetfolder.new_asset_dialog.assettype.help=W\u00e4hlen Sie den Typ des neuen Assets aus.
contentsection.assetfolder.new_asset_dialog.assettype.label=Typ
contentsection.assetfolder.new_asset_dialog.submit=Asset erstellen

View File

@ -0,0 +1,2 @@
create_step=Access denied

View File

@ -0,0 +1,2 @@
create_step=Zugriff verweigert