diff --git a/ccm-cms/src/main/java/org/librecms/assets/SideNote.java b/ccm-cms/src/main/java/org/librecms/assets/SideNote.java index 7aa752804..22d45f5cf 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/SideNote.java +++ b/ccm-cms/src/main/java/org/librecms/assets/SideNote.java @@ -19,9 +19,13 @@ package org.librecms.assets; import com.arsdigita.cms.ui.assets.forms.SideNoteForm; + import org.librecms.contentsection.Asset; import org.hibernate.envers.Audited; import org.libreccm.l10n.LocalizedString; +import org.librecms.ui.contentsections.assets.MvcAssetEditKit; +import org.librecms.ui.contentsections.assets.SideNoteCreateStep; +import org.librecms.ui.contentsections.assets.SideNoteEditStep; import java.io.Serializable; import java.util.Objects; @@ -38,21 +42,27 @@ import static org.librecms.assets.AssetConstants.*; /** * Assets for side notes (additional informations) for a content item. - * + * * @author Jens Pelzetter */ @Entity @Table(name = "SIDE_NOTES", schema = DB_SCHEMA) @Audited -@AssetType(assetForm = SideNoteForm.class, - labelBundle= ASSETS_BUNDLE, - labelKey = "sidenote.label", - descriptionBundle = ASSETS_BUNDLE, - descriptionKey = "sidenote.description") +@AssetType( + assetForm = SideNoteForm.class, + labelBundle = ASSETS_BUNDLE, + labelKey = "sidenote.label", + descriptionBundle = ASSETS_BUNDLE, + descriptionKey = "sidenote.description" +) +@MvcAssetEditKit( + createStep = SideNoteCreateStep.class, + editStep = SideNoteEditStep.class +) public class SideNote extends Asset implements Serializable { private static final long serialVersionUID = -4566222634780521726L; - + @Embedded @AssociationOverride( name = "values", diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AbstractMvcAssetCreateStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AbstractMvcAssetCreateStep.java index c061b4145..63b20015b 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AbstractMvcAssetCreateStep.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AbstractMvcAssetCreateStep.java @@ -19,13 +19,17 @@ 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.Asset; +import org.librecms.contentsection.AssetManager; import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.Folder; import org.librecms.contentsection.FolderManager; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; @@ -42,6 +46,15 @@ import javax.transaction.Transactional; public abstract class AbstractMvcAssetCreateStep implements MvcAssetCreateStep { + 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; + /** * Provides operations for folders. */ @@ -71,6 +84,12 @@ public abstract class AbstractMvcAssetCreateStep */ private SortedMap messages; + private String name; + + private String title; + + private String initialLocale; + public AbstractMvcAssetCreateStep() { messages = new TreeMap<>(); } @@ -154,4 +173,92 @@ public abstract class AbstractMvcAssetCreateStep this.messages = new TreeMap<>(messages); } + public String getName() { + return name; + } + + public String getTitle() { + return title; + } + + public String getInitialLocale() { + return initialLocale; + } + + @Override + public String getAssetType() { + return getAssetClass().getName(); + } + + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + @Override + public String createAsset(final Map 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(); + } + + 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(); + } + 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(); + } + initialLocale = formParams.get(FORM_PARAM_INITIAL_LOCALE)[0]; + final Locale locale = new Locale(initialLocale); + +// final T asset = createAsset(name, title, locale, folder); + + final T asset = assetManager.createAsset( + name, + title, + locale, + folder, + getAssetClass() + ); + + return setAssetProperties(asset); + } + + protected abstract Class getAssetClass(); + + protected abstract String setAssetProperties(final T asset); + } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AbstractMvcAssetEditStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AbstractMvcAssetEditStep.java index df984bdf8..0eeaa48ce 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AbstractMvcAssetEditStep.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/AbstractMvcAssetEditStep.java @@ -19,6 +19,7 @@ package org.librecms.ui.contentsections.assets; import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.security.AuthorizationRequired; import org.librecms.contentsection.Asset; import org.librecms.contentsection.AssetManager; import org.librecms.contentsection.AssetRepository; @@ -28,13 +29,23 @@ import org.librecms.ui.contentsections.ContentSectionModel; import org.librecms.ui.contentsections.ContentSectionsUi; import org.librecms.ui.contentsections.ContentSectionNotFoundException; +import java.util.Collections; import java.util.HashMap; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; import javax.inject.Inject; +import javax.mvc.Controller; import javax.mvc.Models; import javax.servlet.http.HttpServletRequest; +import javax.transaction.Transactional; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.WebApplicationException; @@ -44,8 +55,12 @@ import javax.ws.rs.core.UriBuilder; * * @author Jens Pelzetter */ +@Controller public abstract class AbstractMvcAssetEditStep implements MvcAssetEditStep { + @Inject + private AssetStepsDefaultMessagesBundle messageBundle; + @Inject private AssetUi assetUi; @@ -90,6 +105,10 @@ public abstract class AbstractMvcAssetEditStep implements MvcAssetEditStep { private String stepPath; + private Map titleValues; + + private List unusedTitleLocales; + protected void init() throws ContentSectionNotFoundException, AssetNotFoundException { contentSection = sectionsUi @@ -143,6 +162,29 @@ public abstract class AbstractMvcAssetEditStep implements MvcAssetEditStep { ) .orElse(""); + titleValues = getAsset() + .getTitle() + .getValues() + .entrySet() + .stream() + .collect( + Collectors.toMap( + entry -> entry.getKey().toString(), + entry -> entry.getValue() + ) + ); + + final Set titleLocales = getAsset() + .getTitle() + .getAvailableLocales(); + + unusedTitleLocales = globalizationHelper + .getAvailableLocales() + .stream() + .filter(locale -> !titleLocales.contains(locale)) + .map(Locale::toString) + .collect(Collectors.toList()); + models.put("activeAssetTab", "editTab"); models.put("stepPath", stepPath); } @@ -236,30 +278,30 @@ public abstract class AbstractMvcAssetEditStep implements MvcAssetEditStep { ) ) ); - + final Map values = new HashMap<>(); values.put( MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM, section.getLabel() ); values.put( - MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME, + 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() + .fromPath(path) + .buildFromMap(values) + .toString() ) .map(path -> String.format("redirect:%s", path)) .orElse(""); } - + @Override public String buildRedirectPathForStep(final String subPath) { final ContentSection section = Optional @@ -286,31 +328,182 @@ public abstract class AbstractMvcAssetEditStep implements MvcAssetEditStep { ) ) ); - + final Map values = new HashMap<>(); values.put( MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM, section.getLabel() ); values.put( - MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME, + 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() + .fromPath(path) + .path(subPath) + .buildFromMap(values) + .toString() ) .map(path -> String.format("redirect:%s", path)) .orElse(""); } - - + public String getName() { + return getAsset().getDisplayName(); + } + + @POST + @Path("/name") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String updateName( + @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) + final String assetPath, + @FormParam("name") @DefaultValue("") final String name + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (AssetNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (assetPermissionsChecker.canEditAsset(getAsset())) { + if (name.isEmpty() || name.matches("\\s*")) { + models.put("nameMissing", true); + + return showStep(sectionIdentifier, assetPath); + } + + getAsset().setDisplayName(name); + assetRepo.save(getAsset()); + + updateAssetPath(); + + return buildRedirectPathForStep(); + } else { + return assetUi.showAccessDenied( + getContentSection(), + getAsset(), + messageBundle.get("asset.edit.denied")); + } + } + + public Map getTitleValues() { + return Collections.unmodifiableMap(titleValues); + } + + public List getUnusedTitleLocales() { + return Collections.unmodifiableList(unusedTitleLocales); + } + + @POST + @Path("/title/@add") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String addTitle( + @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) + final String assetPath, + @FormParam("locale") final String localeParam, + @FormParam("value") final String value + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (AssetNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (assetPermissionsChecker.canEditAsset(getAsset())) { + final Locale locale = new Locale(localeParam); + getAsset().getTitle().addValue(locale, value); + assetRepo.save(getAsset()); + + return buildRedirectPathForStep(); + } else { + return assetUi.showAccessDenied( + getContentSection(), + getAsset(), + messageBundle.get("asset.edit.denied")); + } + } + + @POST + @Path("/title/@edit/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String editTitle( + @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) + final String assetPath, + @PathParam("locale") final String localeParam, + @FormParam("value") final String value + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (AssetNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (assetPermissionsChecker.canEditAsset(getAsset())) { + final Locale locale = new Locale(localeParam); + getAsset().getTitle().addValue(locale, value); + assetRepo.save(getAsset()); + + return buildRedirectPathForStep(); + } else { + return assetUi.showAccessDenied( + getContentSection(), + getAsset(), + messageBundle.get("asset.edit.denied")); + } + } + + @POST + @Path("/title/@remove/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String removeTitle( + @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) + final String assetPath, + @PathParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (AssetNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (assetPermissionsChecker.canEditAsset(getAsset())) { + final Locale locale = new Locale(localeParam); + getAsset().getTitle().removeValue(locale); + assetRepo.save(getAsset()); + + return buildRedirectPathForStep(); + } else { + return assetUi.showAccessDenied( + getContentSection(), + getAsset(), + messageBundle.get("asset.edit.denied")); + } + } + } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/CmsAssetEditSteps.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/CmsAssetEditSteps.java index f492305b4..a4b8c3b38 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/CmsAssetEditSteps.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/CmsAssetEditSteps.java @@ -18,6 +18,7 @@ */ package org.librecms.ui.contentsections.assets; + import java.util.HashSet; import java.util.Set; @@ -32,6 +33,7 @@ public class CmsAssetEditSteps implements MvcAssetEditSteps { final Set> classes = new HashSet<>(); classes.add(PostalAddressEditStep.class); + classes.add(SideNoteEditStep.class); return classes; } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/MvcAssetEditStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/MvcAssetEditStep.java index 4663c7c81..cb5566303 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/MvcAssetEditStep.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/MvcAssetEditStep.java @@ -18,10 +18,16 @@ */ package org.librecms.ui.contentsections.assets; +import org.libreccm.security.AuthorizationRequired; import org.librecms.contentsection.Asset; import org.librecms.contentsection.ContentSection; import org.librecms.ui.contentsections.ContentSectionNotFoundException; +import javax.transaction.Transactional; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + /** * * @author Jens Pelzetter @@ -61,9 +67,20 @@ public interface MvcAssetEditStep { String getStepPath(); String buildRedirectPathForStep() throws ContentSectionNotFoundException, - AssetNotFoundException; + AssetNotFoundException; String buildRedirectPathForStep(final String subPath) throws ContentSectionNotFoundException, AssetNotFoundException; + @GET + @Path("/") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + String showStep( + @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) + final String assetPath + ); + } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/PostalAddressCreateStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/PostalAddressCreateStep.java index bb5ee3eed..1f03cea16 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/PostalAddressCreateStep.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/PostalAddressCreateStep.java @@ -21,7 +21,6 @@ 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.Arrays; @@ -46,27 +45,12 @@ import javax.transaction.Transactional; public class PostalAddressCreateStep extends AbstractMvcAssetCreateStep { - 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; - private String name; - - private String title; - - private String initialLocale; - private String address; private String postalCode; @@ -82,74 +66,15 @@ public class PostalAddressCreateStep return "org/librecms/ui/contentsection/assets/postaladdress/create-postaladdress.xhtml"; } + @Override + protected Class getAssetClass() { + return PostalAddress.class; + } + @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) @Override - public String createAsset(final Map 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(); - } - - 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(); - } - 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(); - } - initialLocale = formParams.get(FORM_PARAM_INITIAL_LOCALE)[0]; - final Locale locale = new Locale(initialLocale); - - address = formParams.get("address")[0]; - postalCode = formParams.get("postalCode")[0]; - city = formParams.get("city")[0]; - state = formParams.get("state")[0]; - isoCountryCode = formParams.get("isoCountryCode")[0]; - - final PostalAddress postalAddress = assetManager.createAsset( - name, - title, - locale, - getFolder(), - PostalAddress.class - ); - + protected String setAssetProperties(final PostalAddress postalAddress) { postalAddress.setAddress(address); postalAddress.setPostalCode(postalCode); postalAddress.setCity(city); @@ -162,7 +87,7 @@ public class PostalAddressCreateStep "redirect:/%s/assets/%s/%s/@postaladdress-edit", getContentSectionLabel(), getFolderPath(), - name + getName() ); } @@ -190,18 +115,6 @@ public class PostalAddressCreateStep return MvcAssetStepsConstants.BUNDLE; } - public String getName() { - return name; - } - - public String getTitle() { - return title; - } - - public String getInitialLocale() { - return initialLocale; - } - public String getAddress() { return address; } @@ -230,6 +143,7 @@ public class PostalAddressCreateStep final Map countriesMap = countries .stream() + .sorted(this::sortCountries) .collect( Collectors.toMap( Locale::getCountry, @@ -240,12 +154,20 @@ public class PostalAddressCreateStep LinkedHashMap::new ) ); - + final Map values = new LinkedHashMap<>(); values.put("", ""); values.putAll(countriesMap); - + return values; } + private int sortCountries(final Locale locale1, final Locale locale2) { + final Locale negotiated = globalizationHelper.getNegotiatedLocale(); + final String country1 = locale1.getDisplayCountry(negotiated); + final String country2 = locale2.getDisplayCountry(negotiated); + + return country1.compareTo(country2); + } + } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/PostalAddressEditStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/PostalAddressEditStep.java index 0c6a4b67f..688fbba27 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/PostalAddressEditStep.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/PostalAddressEditStep.java @@ -31,7 +31,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -43,7 +42,6 @@ import javax.inject.Named; import javax.mvc.Controller; import javax.mvc.Models; import javax.transaction.Transactional; -import javax.ws.rs.DefaultValue; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -69,18 +67,12 @@ public class PostalAddressEditStep extends AbstractMvcAssetEditStep { @Inject private AssetStepsDefaultMessagesBundle messageBundle; - @Inject - private AssetManager assetManager; - @Inject private AssetUi assetUi; @Inject private AssetRepository assetRepo; - @Inject - private FolderManager folderManager; - @Inject private GlobalizationHelper globalizationHelper; @@ -90,10 +82,6 @@ public class PostalAddressEditStep extends AbstractMvcAssetEditStep { @Inject private Models models; - private Map titleValues; - - private List unusedTitleLocales; - private Map countries; @Override @@ -101,8 +89,16 @@ public class PostalAddressEditStep extends AbstractMvcAssetEditStep { return PostalAddressEditStep.class; } + private int sortCountries(final Locale locale1, final Locale locale2) { + final Locale negotiated = globalizationHelper.getNegotiatedLocale(); + final String country1 = locale1.getDisplayCountry(negotiated); + final String country2 = locale2.getDisplayCountry(negotiated); + + return country1.compareTo(country2); + } + @Override - protected void init() throws ContentSectionNotFoundException, + protected void init() throws ContentSectionNotFoundException, AssetNotFoundException { super.init(); @@ -113,6 +109,7 @@ public class PostalAddressEditStep extends AbstractMvcAssetEditStep { final Map countriesMap = countryLocales .stream() + .sorted(this::sortCountries) .collect( Collectors.toMap( Locale::getCountry, @@ -133,6 +130,7 @@ public class PostalAddressEditStep extends AbstractMvcAssetEditStep { @Path("/") @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) + @Override public String showStep( @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) final String sectionIdentifier, @@ -148,29 +146,6 @@ public class PostalAddressEditStep extends AbstractMvcAssetEditStep { } if (assetPermissionsChecker.canEditAsset(getAsset())) { - titleValues = getAsset() - .getTitle() - .getValues() - .entrySet() - .stream() - .collect( - Collectors.toMap( - entry -> entry.getKey().toString(), - entry -> entry.getValue() - ) - ); - - final Set titleLocales = getAsset() - .getTitle() - .getAvailableLocales(); - - unusedTitleLocales = globalizationHelper - .getAvailableLocales() - .stream() - .filter(locale -> !titleLocales.contains(locale)) - .map(Locale::toString) - .collect(Collectors.toList()); - return "org/librecms/ui/contentsection/assets/postaladdress/edit-postaladdress.xhtml"; } else { return assetUi.showAccessDenied( @@ -179,164 +154,15 @@ public class PostalAddressEditStep extends AbstractMvcAssetEditStep { messageBundle.get("asset.edit.denied")); } } - - public String getName() { - return getAsset().getDisplayName(); - } +// +// public String getName() { +// return getAsset().getDisplayName(); +// } public PostalAddress getPostalAddress() { return (PostalAddress) getAsset(); } - @POST - @Path("/name") - @AuthorizationRequired - @Transactional(Transactional.TxType.REQUIRED) - public String updateName( - @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) - final String sectionIdentifier, - @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) - final String assetPath, - @FormParam("name") @DefaultValue("") final String name - ) { - try { - init(); - } catch (ContentSectionNotFoundException ex) { - return ex.showErrorMessage(); - } catch (AssetNotFoundException ex) { - return ex.showErrorMessage(); - } - - if (assetPermissionsChecker.canEditAsset(getAsset())) { - if (name.isEmpty() || name.matches("\\s*")) { - models.put("nameMissing", true); - - return showStep(sectionIdentifier, assetPath); - } - - getAsset().setDisplayName(name); - assetRepo.save(getAsset()); - - updateAssetPath(); - - return buildRedirectPathForStep(); - } else { - return assetUi.showAccessDenied( - getContentSection(), - getAsset(), - messageBundle.get("asset.edit.denied")); - } - } - - public Map getTitleValues() { - return Collections.unmodifiableMap(titleValues); - } - - public List getUnusedTitleLocales() { - return Collections.unmodifiableList(unusedTitleLocales); - } - - @POST - @Path("/title/@add") - @AuthorizationRequired - @Transactional(Transactional.TxType.REQUIRED) - public String addTitle( - @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) - final String sectionIdentifier, - @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) - final String assetPath, - @FormParam("locale") final String localeParam, - @FormParam("value") final String value - ) { - try { - init(); - } catch (ContentSectionNotFoundException ex) { - return ex.showErrorMessage(); - } catch (AssetNotFoundException ex) { - return ex.showErrorMessage(); - } - - if (assetPermissionsChecker.canEditAsset(getAsset())) { - final Locale locale = new Locale(localeParam); - getAsset().getTitle().addValue(locale, value); - assetRepo.save(getAsset()); - - return buildRedirectPathForStep(); - } else { - return assetUi.showAccessDenied( - getContentSection(), - getAsset(), - messageBundle.get("asset.edit.denied")); - } - } - - @POST - @Path("/title/@edit/{locale}") - @AuthorizationRequired - @Transactional(Transactional.TxType.REQUIRED) - public String editTitle( - @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) - final String sectionIdentifier, - @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) - final String assetPath, - @PathParam("locale") final String localeParam, - @PathParam("value") final String value - ) { - try { - init(); - } catch (ContentSectionNotFoundException ex) { - return ex.showErrorMessage(); - } catch (AssetNotFoundException ex) { - return ex.showErrorMessage(); - } - - if (assetPermissionsChecker.canEditAsset(getAsset())) { - final Locale locale = new Locale(localeParam); - getAsset().getTitle().addValue(locale, value); - assetRepo.save(getAsset()); - - return buildRedirectPathForStep(); - } else { - return assetUi.showAccessDenied( - getContentSection(), - getAsset(), - messageBundle.get("asset.edit.denied")); - } - } - - @POST - @Path("/title/@remove/{locale}") - @AuthorizationRequired - @Transactional(Transactional.TxType.REQUIRED) - public String removeTitle( - @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) - final String sectionIdentifier, - @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) - final String assetPath, - @PathParam("locale") final String localeParam - ) { - try { - init(); - } catch (ContentSectionNotFoundException ex) { - return ex.showErrorMessage(); - } catch (AssetNotFoundException ex) { - return ex.showErrorMessage(); - } - - if (assetPermissionsChecker.canEditAsset(getAsset())) { - final Locale locale = new Locale(localeParam); - getAsset().getTitle().removeValue(locale); - assetRepo.save(getAsset()); - - return buildRedirectPathForStep(); - } else { - return assetUi.showAccessDenied( - getContentSection(), - getAsset(), - messageBundle.get("asset.edit.denied")); - } - } - public String getAddress() { return getPostalAddress().getAddress(); } @@ -358,8 +184,12 @@ public class PostalAddressEditStep extends AbstractMvcAssetEditStep { } public String getCountry() { - return new Locale("", getPostalAddress().getIsoCountryCode()) - .getDisplayCountry(globalizationHelper.getNegotiatedLocale()); + if (getPostalAddress().getIsoCountryCode() == null) { + return ""; + } else { + return new Locale("", getPostalAddress().getIsoCountryCode()) + .getDisplayCountry(globalizationHelper.getNegotiatedLocale()); + } } @POST @@ -405,7 +235,9 @@ public class PostalAddressEditStep extends AbstractMvcAssetEditStep { } public Map getCountries() { - return countries; + final LinkedHashMap result = new LinkedHashMap<>(); + result.putAll(countries); + return result; } } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/SideNoteCreateStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/SideNoteCreateStep.java new file mode 100644 index 000000000..baea56933 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/SideNoteCreateStep.java @@ -0,0 +1,99 @@ +/* + * 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.SideNote; +import org.librecms.contentsection.AssetRepository; + +import java.util.Locale; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.inject.Named; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Named("CmsSideNoteCreateStep") +public class SideNoteCreateStep extends AbstractMvcAssetCreateStep { + + @Inject + private AssetRepository assetRepo; + + @Inject + private GlobalizationHelper globalizationHelper; + + private String name; + + private String text; + + @Override + public String showCreateStep() { + return "org/librecms/ui/contentsection/assets/sidenote/create-sidenote.xhtml"; + } + + @Override + public String getLabel() { + return globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("side_note.label"); + } + + @Override + public String getDescription() { + return globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("side_note.description"); + } + + @Override + public String getBundle() { + return MvcAssetStepsConstants.BUNDLE; + } + + public String getText() { + return text; + } + + @Override + public Class getAssetClass() { + return SideNote.class; + } + + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + @Override + public String setAssetProperties(final SideNote sideNote) { + sideNote.getText().addValue(new Locale(getInitialLocale()), text); + assetRepo.save(sideNote); + + return String.format( + "redirect:/%s/assets/%s/%s/@sidenote-edit", + getContentSectionLabel(), + getFolderPath(), + name + ); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/SideNoteEditStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/SideNoteEditStep.java new file mode 100644 index 000000000..9b18af44a --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/SideNoteEditStep.java @@ -0,0 +1,282 @@ +/* + * 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.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.security.AuthorizationRequired; +import org.librecms.assets.SideNote; +import org.librecms.contentsection.AssetRepository; +import org.librecms.ui.contentsections.AssetPermissionsChecker; +import org.librecms.ui.contentsections.ContentSectionNotFoundException; +import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow; + +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.stream.Collectors; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.inject.Named; +import javax.mvc.Controller; +import javax.transaction.Transactional; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Path(MvcAssetEditSteps.PATH_PREFIX + "sidenote-edit") +@Controller +@Named("CmsSideNoteEditStep") +@MvcAssetEditStepDef( + bundle = MvcAssetStepsConstants.BUNDLE, + descriptionKey = "postaladdress.editstep.description", + labelKey = "postaladdress.editstep.label", + supportedAssetType = SideNote.class +) +public class SideNoteEditStep extends AbstractMvcAssetEditStep { + + @Inject + private AssetStepsDefaultMessagesBundle messageBundle; + + @Inject + private AssetUi assetUi; + + @Inject + private AssetRepository assetRepo; + + @Inject + private GlobalizationHelper globalizationHelper; + + @Inject + private AssetPermissionsChecker assetPermissionsChecker; + + private Map textValues; + + private List variants; + + private List unusedTextLocales; + + @Override + public Class extends MvcAssetEditStep> getStepClass() { + return SideNoteEditStep.class; + } + + @GET + @Path("/") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + @Override + public String showStep( + @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) + final String assetPath + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (AssetNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (assetPermissionsChecker.canEditAsset(getAsset())) { + textValues = getSideNote() + .getText() + .getValues() + .entrySet() + .stream() + .collect( + Collectors.toMap( + entry -> entry.getKey().toString(), + entry -> entry.getValue() + ) + ); + + final Set textLocales = getSideNote() + .getText() + .getAvailableLocales(); + unusedTextLocales = globalizationHelper + .getAvailableLocales() + .stream() + .filter(locale -> !textLocales.contains(locale)) + .map(Locale::toString) + .collect(Collectors.toList()); + + variants = getSideNote() + .getText() + .getValues() + .entrySet() + .stream() + .map(this::buildVariantRow) + .collect(Collectors.toList()); + + return "org/librecms/ui/contentsection/assets/sidenote/edit-sidenote.xhtml"; + } else { + return assetUi.showAccessDenied( + getContentSection(), + getAsset(), + messageBundle.get("asset.edit.denied")); + } + } + + public SideNote getSideNote() { + return (SideNote) getAsset(); + } + + public Map getTextValues() { + return Collections.unmodifiableMap(textValues); + } + + public List getVariants() { + return Collections.unmodifiableList(variants); + } + + public List getUnusedTextLocales() { + return Collections.unmodifiableList(unusedTextLocales); + } + + @POST + @Path("/text/add") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String addText( + @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) + final String assetPath, + @FormParam("locale") final String localeParam, + @FormParam("value") final String value + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (AssetNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (assetPermissionsChecker.canEditAsset(getAsset())) { + final Locale locale = new Locale(localeParam); + getSideNote().getText().addValue(locale, value); + assetRepo.save(getSideNote()); + + return buildRedirectPathForStep(); + } else { + return assetUi.showAccessDenied( + getContentSection(), + getAsset(), + messageBundle.get("asset.edit.denied")); + } + } + + @POST + @Path("/text/edit/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String editText( + @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) + final String assetPath, + @PathParam("locale") final String localeParam, + @PathParam("value") final String value + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (AssetNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (assetPermissionsChecker.canEditAsset(getAsset())) { + final Locale locale = new Locale(localeParam); + getSideNote().getText().addValue(locale, value); + assetRepo.save(getSideNote()); + + return buildRedirectPathForStep(); + } else { + return assetUi.showAccessDenied( + getContentSection(), + getAsset(), + messageBundle.get("asset.edit.denied")); + } + } + + @POST + @Path("/text/remove/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String removeText( + @PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME) + final String assetPath, + @PathParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (AssetNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (assetPermissionsChecker.canEditAsset(getAsset())) { + final Locale locale = new Locale(localeParam); + getSideNote().getText().removeValue(locale); + assetRepo.save(getSideNote()); + + return buildRedirectPathForStep(); + } else { + return assetUi.showAccessDenied( + getContentSection(), + getAsset(), + messageBundle.get("asset.edit.denied")); + } + } + + private CmsEditorLocaleVariantRow buildVariantRow( + final Map.Entry entry + ) { + final CmsEditorLocaleVariantRow variant + = new CmsEditorLocaleVariantRow(); + variant.setLocale(entry.getKey().toString()); + final Document document = Jsoup.parseBodyFragment(entry.getValue()); + variant.setWordCount( + new StringTokenizer(document.body().text()).countTokens() + ); + + return variant; + } + +} diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/sidenote/create-sidenote.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/sidenote/create-sidenote.xhtml new file mode 100644 index 000000000..06dc32aad --- /dev/null +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/sidenote/create-sidenote.xhtml @@ -0,0 +1,68 @@ +]> + + + + + + #{CmsAssetsStepsDefaultMessagesBundle["sidenote.createform.title"]} + + + + #{message.value} + + + + + + + + + + + + #{CmsAssetsStepsDefaultMessagesBundle['createform.cancel']} + + + #{CmsAssetsStepsDefaultMessagesBundle['createform.submit']} + + + + + + + + + + + + diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/sidenote/edit-sidenote.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/sidenote/edit-sidenote.xhtml new file mode 100644 index 000000000..976773b1a --- /dev/null +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/assets/sidenote/edit-sidenote.xhtml @@ -0,0 +1,138 @@ +]> + + + + + + + #{CmsAssetsStepsDefaultMessagesBundle.getMessage('sidenote.editstep.header', [CmsSideNoteEditStep.name])} + + + #{CmsAssetsStepsDefaultMessagesBundle['editstep.name.header']} + + #{CmsSideNoteEditStep.name} + + + + + #{CmsAssetsStepsDefaultMessagesBundle['editstep.name.edit']} + + + + + + + + + + + + #{CmsAssetsStepsDefaultMessagesBundle['editstep.name.edit.title']} + + + + + + + + + + + + + + + + + #{CmsAssetsStepsDefaultMessagesBundle['sidenote.editstep.text.header']} + + + + + + + + diff --git a/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle.properties b/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle.properties index 625355195..9cb368033 100644 --- a/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle.properties +++ b/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle.properties @@ -65,3 +65,7 @@ postaladdress.editstep.properties.country.label=Country postaladdress.editstep.properties.edit.submit=Save postal_address.label=Postal address editstep.name.close=Cancel +postal_address.description=A postal address. +side_note.label=Side Note +side_note.description=A side note. +sidenote.createform.title=Create a new side note diff --git a/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle_de.properties b/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle_de.properties index e978b663a..5b6145fad 100644 --- a/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle_de.properties +++ b/ccm-cms/src/main/resources/org/librecms/ui/MvcAssetStepsBundle_de.properties @@ -65,3 +65,7 @@ postaladdress.editstep.properties.country.label=Land postaladdress.editstep.properties.edit.submit=Speichern postal_address.label=Postanschrift editstep.name.close=Abbrechen +postal_address.description=Eine Postanschrift. +side_note.label=Randbemerkung +side_note.description=Eine Randbemerkung. +sidenote.createform.title=Eine neue Randbemerkungen anlegen
#{CmsSideNoteEditStep.name}