diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/SciDepartment.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/SciDepartment.java
index 742c941..089c4a3 100644
--- a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/SciDepartment.java
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/SciDepartment.java
@@ -10,7 +10,6 @@ import org.librecms.contenttypes.ContentTypeDescription;
import org.librecms.ui.contentsections.documents.MvcAuthoringKit;
import org.scientificcms.contenttypes.scidepartment.ui.SciDepartmentCreateStep;
import org.scientificcms.contenttypes.scidepartment.ui.SciDepartmentDescriptionStep;
-import org.scientificcms.contenttypes.scidepartment.ui.SciDepartmentExtendedPropertiesStep;
import org.scientificcms.contenttypes.scidepartment.ui.SciDepartmentPropertiesStep;
import java.io.Serializable;
@@ -48,7 +47,6 @@ import static org.scientificcms.contenttypes.scidepartment.SciDepartmentConstant
createStep = SciDepartmentCreateStep.class,
authoringSteps = {
SciDepartmentPropertiesStep.class,
- SciDepartmentExtendedPropertiesStep.class,
SciDepartmentDescriptionStep.class
}
)
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentAuthoringSteps.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentAuthoringSteps.java
new file mode 100644
index 0000000..3579b11
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentAuthoringSteps.java
@@ -0,0 +1,35 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
+
+import java.util.Set;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@ApplicationScoped
+public class SciDepartmentAuthoringSteps implements MvcAuthoringSteps {
+
+ @Override
+ public Set> getClasses() {
+ return Set.of(
+ SciDepartmentPropertiesStep.class,
+ SciDepartmentDescriptionStep.class
+ );
+ }
+
+ @Override
+ public Set> getResourceClasses() {
+ return Set.of(
+ SciDepartmentDescriptionContacts.class,
+ SciDepartmentDescriptionStepResources.class,
+ SciDepartmentDescriptionStepService.class
+ );
+ }
+
+
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentContact.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentContact.java
new file mode 100644
index 0000000..efc22e8
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentContact.java
@@ -0,0 +1,67 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+/**
+ * DTO providing the information about a {@link Contact} of a
+ * {@link SciDepartment} in a form that is easy to use from a MVC template.
+ *
+ * @author Jens Pelzetter
+ */
+public class SciDepartmentContact {
+
+ /**
+ * The ID of the {@link Contact} represented by this object.
+ */
+ private long contactId;
+
+ /**
+ * The type of the contact.
+ *
+ * @see Contact#contactType
+ */
+ private String contactType;
+
+ /**
+ * Order of contact.
+ */
+ private long order;
+
+ /**
+ * The title of the {@link ContactableEntity}
+ *
+ * @see Contact#contactable
+ */
+ private String contactable;
+
+ public long getContactId() {
+ return contactId;
+ }
+
+ public void setContactId(final long contactId) {
+ this.contactId = contactId;
+ }
+
+ public String getContactType() {
+ return contactType;
+ }
+
+ public void setContactType(final String contactType) {
+ this.contactType = contactType;
+ }
+
+ public long getOrder() {
+ return order;
+ }
+
+ public void setOrder(final long order) {
+ this.order = order;
+ }
+
+ public String getContactable() {
+ return contactable;
+ }
+
+ public void setContactable(final String contactable) {
+ this.contactable = contactable;
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentContactModel.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentContactModel.java
new file mode 100644
index 0000000..92c9d51
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentContactModel.java
@@ -0,0 +1,67 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+/**
+ * DTO providing the information about a {@link Contact} of a
+ * {@link SciDepartment} in a form that is easy usable from a MVC template.
+ *
+ * @author Jens Pelzetter
+ */
+public class SciDepartmentContactModel {
+
+ /**
+ * The ID of the {@link Contact} represented by this object.
+ */
+ private long contactId;
+
+ /**
+ * The type of the contact.
+ *
+ * @see Contact#contactType
+ */
+ private String contactType;
+
+ /**
+ * Order of contact.
+ */
+ private long order;
+
+ /**
+ * The title of the {@link ContactableEntity}
+ *
+ * @see Contact#contactable
+ */
+ private String contactable;
+
+ public long getContactId() {
+ return contactId;
+ }
+
+ public void setContactId(final long contactId) {
+ this.contactId = contactId;
+ }
+
+ public String getContactType() {
+ return contactType;
+ }
+
+ public void setContactType(final String contactType) {
+ this.contactType = contactType;
+ }
+
+ public long getOrder() {
+ return order;
+ }
+
+ public void setOrder(final long order) {
+ this.order = order;
+ }
+
+ public String getContactable() {
+ return contactable;
+ }
+
+ public void setContactable(final String contactable) {
+ this.contactable = contactable;
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentCreateStep.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentCreateStep.java
index 1978b4e..afd7ba2 100644
--- a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentCreateStep.java
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentCreateStep.java
@@ -1,25 +1,142 @@
package org.scientificcms.contenttypes.scidepartment.ui;
+import org.libreccm.l10n.GlobalizationHelper;
+import org.librecms.contentsection.ContentItemManager;
+import org.librecms.contentsection.ContentItemRepository;
import org.librecms.ui.contentsections.documents.AbstractMvcDocumentCreateStep;
import org.scientificcms.contenttypes.scidepartment.SciDepartment;
+import org.scientificcms.contenttypes.sciproject.SciProject;
import java.util.Map;
import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
import javax.inject.Named;
+import javax.transaction.Transactional;
/**
+ * Create step for a {@link SciDepartment}.
*
* @author Jens Pelzetter
*/
@RequestScoped
@Named("SciDepartmentCreateStep")
-public class SciDepartmentCreateStep
- extends AbstractMvcDocumentCreateStep{
+public class SciDepartmentCreateStep
+ extends AbstractMvcDocumentCreateStep {
+
+ private static final String FORM_PARAM_NAME = "name";
+
+ private static final String FORM_PARAM_TITLE = "title";
+
+ private static final String FORM_PARAM_SHORT_DESCRIPTION = "shortdesc";
+
+ private static final String FORM_PARAM_INITIAL_LOCALE = "locale";
+
+ private static final String FORM_PARAM_SELECTED_WORKFLOW = "workflow";
+
+ /**
+ * Provides functions for working with content items.
+ */
+ @Inject
+ private ContentItemManager itemManager;
+
+ /**
+ * Used to save the event.
+ */
+ @Inject
+ private ContentItemRepository itemRepo;
+
+ /**
+ * Provides functions for working with {@link LocalizedString}s.
+ */
+ @Inject
+ private GlobalizationHelper globalizationHelper;
+
+ /**
+ * Nmae of the department.
+ */
+ private String name;
+
+ /**
+ * Title of the department.
+ */
+ private String title;
+
+ /**
+ * The short description of the department.
+ */
+ private String shortDescription;
+
+ /**
+ * The initial locale of the department.
+ */
+ private String initialLocale;
+
+ /**
+ * The workflow to use for the new department.
+ */
+ private String selectedWorkflow;
+
+ @Override
+ public String getDocumentType() {
+ return SciDepartment.class.getName();
+ }
+
+ @Override
+ public String getDescription() {
+ return globalizationHelper
+ .getLocalizedTextsUtil(getBundle())
+ .getText("createstep.description");
+ }
+
+ @Override
+ public String getBundle() {
+ return SciDepartmentStepsConstants.BUNDLE;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getShortDescription() {
+ return shortDescription;
+ }
+
+ public String getInitialLocale() {
+ return initialLocale;
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String getSelectedWorkflow() {
+ if (selectedWorkflow == null || selectedWorkflow.isEmpty()) {
+ return getContentSection()
+ .getContentTypes()
+ .stream()
+ .filter(
+ type -> type.getContentItemClass().equals(
+ SciProject.class.getName()
+ )
+ )
+ .findAny()
+ .map(type -> type.getDefaultWorkflow())
+ .map(
+ workflow -> globalizationHelper.getValueFromLocalizedString(
+ workflow.getName()
+ )
+ )
+ .orElse("");
+ } else {
+ return selectedWorkflow;
+ }
+ }
@Override
public String showCreateStep() {
- throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
+ return "org/scientificcms/contenttypes/scidepartment/ui/create-scidepartment.xhtml";
}
@Override
@@ -27,19 +144,4 @@ public class SciDepartmentCreateStep
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
- @Override
- public String getDocumentType() {
- throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
- }
-
- @Override
- public String getDescription() {
- throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
- }
-
- @Override
- public String getBundle() {
- throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
- }
-
}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionContacts.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionContacts.java
new file mode 100644
index 0000000..2b1cc35
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionContacts.java
@@ -0,0 +1,101 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import org.librecms.contentsection.ContentItem;
+import org.librecms.contentsection.ContentItemRepository;
+import org.librecms.contentsection.ContentSection;
+import org.librecms.ui.contentsections.ContentSectionsUi;
+import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
+import org.scientificcms.contenttypes.scidepartment.Contact;
+import org.scientificcms.contenttypes.scidepartment.ContactRepository;
+import org.scientificcms.contenttypes.scidepartment.SciDepartment;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Path(MvcAuthoringSteps.PATH_PREFIX + "scidepartment-description-contacts")
+public class SciDepartmentDescriptionContacts {
+
+ @Inject
+ private ContactRepository contactRepo;
+
+ @Inject
+ private ContentItemRepository itemRepo;
+
+ @Inject
+ private ContentSectionsUi sectionsUi;
+
+ @POST
+ @Path("/save-order")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Transactional(Transactional.TxType.REQUIRED)
+ public Response saveOrder(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM)
+ final String documentPath,
+ final List order
+ ) {
+ final ContentSection contentSection = sectionsUi
+ .findContentSection(sectionIdentifier)
+ .orElseThrow(
+ () -> new NotFoundException(
+ String.format(
+ "No content identifed by %s found.",
+ sectionIdentifier
+ )
+ )
+ );
+
+ final ContentItem document = itemRepo
+ .findByPath(contentSection, documentPath)
+ .orElseThrow(
+ () -> new NotFoundException(
+ String.format(
+ "No document for path %s in section %s.",
+ documentPath,
+ contentSection.getLabel()
+ )
+ )
+ );
+
+ if (!(document instanceof SciDepartment)) {
+ throw new NotFoundException(
+ String.format(
+ "No SciDepartment for path %s in section %s.",
+ documentPath,
+ contentSection.getLabel()
+ )
+ );
+ }
+
+ final Map orderMap = new HashMap<>();
+ for (int i = 0; i < order.size(); i++) {
+ orderMap.put(Long.parseLong(order.get(i)), (long) i);
+ }
+
+ final SciDepartment department = (SciDepartment)document;
+ for (final Contact contact : department.getContacts()) {
+ contact.setOrder(orderMap.get(contact.getContactId()));
+ contactRepo.save(contact);
+ }
+
+ return Response.ok().build();
+ }
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionContactsModel.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionContactsModel.java
new file mode 100644
index 0000000..c48c68c
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionContactsModel.java
@@ -0,0 +1,57 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import org.librecms.assets.Organization;
+import org.librecms.assets.Person;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Named("SciDepartmentDescriptionContacts")
+public class SciDepartmentDescriptionContactsModel {
+
+ private boolean canEdit;
+
+ private List contacts;
+
+ private String baseUrl;
+
+ public boolean getCanEdit() {
+ return canEdit;
+ }
+
+ protected void setCanEdit(final boolean canEdit) {
+ this.canEdit = canEdit;
+ }
+
+ public List getContacts() {
+ return Collections.unmodifiableList(contacts);
+ }
+
+ protected void setContacts(final List contacts) {
+ this.contacts = new ArrayList<>(contacts);
+ }
+
+ public String getContactableTypes() {
+ return String.join(
+ ",", Person.class.getName(), Organization.class.getName()
+ );
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ protected void setBaseUrl(final String baseUrl) {
+ this.baseUrl = baseUrl;
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionMembersModel.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionMembersModel.java
new file mode 100644
index 0000000..517219a
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionMembersModel.java
@@ -0,0 +1,60 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Named("SciDepartmentDescriptionMembers")
+public class SciDepartmentDescriptionMembersModel {
+
+ private boolean canEdit;
+
+ private List members;
+
+ private Map statusValues;
+
+ private String baseUrl;
+
+ public boolean getCanEdit() {
+ return canEdit;
+ }
+
+ protected void setCanEdit(final boolean canEdit) {
+ this.canEdit = canEdit;
+ }
+
+ public List getMembers() {
+ return Collections.unmodifiableList(members);
+ }
+
+ protected void setMembers(final List member) {
+ this.members = new ArrayList<>(members);
+ }
+
+ public Map getStatusValues() {
+ return Collections.unmodifiableMap(statusValues);
+ }
+
+ protected void setStatusValues(final Map statusValues) {
+ this.statusValues = new LinkedHashMap<>(statusValues);
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ protected void setBaseUrl(final String baseUrl) {
+ this.baseUrl = baseUrl;
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionModel.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionModel.java
new file mode 100644
index 0000000..240206b
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionModel.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2022 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.scientificcms.contenttypes.scidepartment.ui;
+
+import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Named("SciDepartmentDescriptionModel")
+public class SciDepartmentDescriptionModel {
+
+ private boolean canEdit;
+
+ private Map descriptionValues;
+
+ private List variants;
+
+ private List unusedLocales;
+
+ private String selectedLocale;
+
+ public Map getDescriptionValues() {
+ return Optional
+ .ofNullable(descriptionValues)
+ .map(Collections::unmodifiableMap)
+ .orElse(Collections.emptyMap());
+ }
+
+ protected void setDescriptionValues(
+ final Map descriptionValues
+ ) {
+ this.descriptionValues = Optional
+ .ofNullable(descriptionValues)
+ .map(values -> new HashMap<>(values))
+ .map(values -> (Map) values)
+ .orElse(Collections.emptyMap());
+ }
+
+ public List getVariants() {
+ return Optional
+ .ofNullable(variants)
+ .map(Collections::unmodifiableList)
+ .orElse(Collections.emptyList());
+ }
+
+ protected void setVariants(final List variants) {
+ this.variants = Optional
+ .ofNullable(variants)
+ .map(list -> new ArrayList<>(list))
+ .map(list -> (List) list)
+ .orElse(Collections.emptyList());
+ }
+
+ public List getUnusedLocales() {
+ return Optional
+ .ofNullable(unusedLocales)
+ .map(Collections::unmodifiableList)
+ .orElse(Collections.emptyList());
+ }
+
+ protected void setUnusedLocales(final List unusedLocales) {
+ this.unusedLocales = Optional
+ .ofNullable(unusedLocales)
+ .map(list -> new ArrayList<>(list))
+ .map(list -> (List) list)
+ .orElse(Collections.emptyList());
+ }
+
+ public String getSelectedLocale() {
+ return selectedLocale;
+ }
+
+ protected void setSelectedLocale(final String selectedLocale) {
+ this.selectedLocale = selectedLocale;
+ }
+
+ public boolean getCanEdit() {
+ return canEdit;
+ }
+
+ protected void setCanEdit(final boolean canEdit) {
+ this.canEdit = canEdit;
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStep.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStep.java
index 0342ed8..569627e 100644
--- a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStep.java
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStep.java
@@ -1,12 +1,73 @@
+/*
+ * Copyright (C) 2022 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.scientificcms.contenttypes.scidepartment.ui;
+import org.libreccm.api.Identifier;
+import org.libreccm.api.IdentifierParser;
+import org.libreccm.l10n.GlobalizationHelper;
+import org.libreccm.l10n.LocalizedString;
+import org.libreccm.security.AuthorizationRequired;
+import org.libreccm.ui.BaseUrl;
+import org.librecms.assets.ContactableEntity;
+import org.librecms.assets.Person;
+import org.librecms.contentsection.Asset;
+import org.librecms.contentsection.AssetRepository;
+import org.librecms.contentsection.ContentItemRepository;
+import org.librecms.ui.contentsections.ContentSectionNotFoundException;
+import org.librecms.ui.contentsections.ItemPermissionChecker;
+import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep;
+import org.librecms.ui.contentsections.documents.CmsEditorUtil;
+import org.librecms.ui.contentsections.documents.DocumentNotFoundException;
+import org.librecms.ui.contentsections.documents.DocumentUi;
import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
+import org.scientificcms.contenttypes.scidepartment.Contact;
+import org.scientificcms.contenttypes.scidepartment.ContactRepository;
+import org.scientificcms.contenttypes.scidepartment.DepartmentText;
+import org.scientificcms.contenttypes.scidepartment.DepartmentTextRepository;
+import org.scientificcms.contenttypes.scidepartment.Membership;
+import org.scientificcms.contenttypes.scidepartment.MembershipRepository;
+import org.scientificcms.contenttypes.scidepartment.MembershipStatus;
import org.scientificcms.contenttypes.scidepartment.SciDepartment;
+import org.scientificcms.contenttypes.scidepartment.SciDepartmentManager;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
+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.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
/**
*
@@ -21,6 +82,1118 @@ import javax.ws.rs.Path;
labelKey = "authoringsteps.description.label",
supportedDocumentType = SciDepartment.class
)
-public class SciDepartmentDescriptionStep {
-
+public class SciDepartmentDescriptionStep extends AbstractMvcAuthoringStep {
+
+ @Inject
+ private AssetRepository assetRepo;
+
+ @Inject
+ private BaseUrl baseUrl;
+
+ @Inject
+ private ContentItemRepository itemRepo;
+
+ @Inject
+ private ContactRepository contactRepo;
+
+ @Inject
+ private DepartmentTextRepository departmentTextRepo;
+
+ @Inject
+ private DocumentUi documentUi;
+
+ @Inject
+ private GlobalizationHelper globalizationHelper;
+
+ @Inject
+ private IdentifierParser identifierParser;
+
+ @Context
+ private HttpServletRequest request;
+
+ @Inject
+ private ItemPermissionChecker itemPermissionChecker;
+
+ @Inject
+ private MembershipRepository membershipRepo;
+
+ @Inject
+ private Models models;
+
+ @Inject
+ private SciDepartmentManager departmentManager;
+
+ @Inject
+ private SciDepartmentDescriptionModel descriptionModel;
+
+ @Inject
+ private SciDepartmentDescriptionContactsModel contactsModel;
+
+ @Inject
+ private SciDepartmentDescriptionMembersModel membersModel;
+
+ @Inject
+ private SciDepartmentMessageBundle messageBundle;
+
+ @Inject
+ private SciDepartmentTextsModel textsModel;
+
+ @Override
+ public Class getStepClass() {
+ return SciDepartmentDescriptionStep.class;
+ }
+
+ @GET
+ @Path("/")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String showStep(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ return "org/scientificcms/contenttypes/scidepartment/ui/scidepartment-description.xhtml";
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @GET
+ @Path("/description/view/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String viewDescription(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ descriptionModel.setSelectedLocale(
+ new Locale(localeParam).toString()
+ );
+
+ return "org/scientificcms/contenttypes/scidepartment/ui/description/view.xhtml";
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/description/add")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String addDescriptionValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final String value;
+ if (getDepartment().getDepartmentDescription().getAvailableLocales()
+ .isEmpty()) {
+ value = "";
+ } else {
+ value = globalizationHelper.getValueFromLocalizedString(
+ getDepartment().getDepartmentDescription()
+ );
+ }
+ final Locale locale = new Locale(localeParam);
+ getDepartment().getDepartmentDescription().putValue(locale, value);
+ itemRepo.save(getDepartment());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @GET
+ @Path("/description/edit/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String editDescriptionValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ descriptionModel.setSelectedLocale(
+ new Locale(localeParam).toString()
+ );
+
+ return "org/scientificcms/contenttypes/scidepartment/ui/description/edit.xhtml";
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/description/edit/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String editDescriptionValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final Locale locale = new Locale(localeParam);
+ getDepartment().getDepartmentDescription().putValue(locale, value);
+ itemRepo.save(getDepartment());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/description/remove/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String removeDescriptionValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final Locale locale = new Locale(localeParam);
+ getDepartment().getDepartmentDescription().removeValue(locale);
+ itemRepo.save(getDepartment());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @GET
+ @Path("/texts/view/{textKey}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String viewDepartmentText(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("textKey")
+ final String textKey
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ textsModel.setSelectedText(textKey);
+
+ return "org/scientificcms/contenttypes/scidepartment/ui/texts/view-values.xhtml";
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @GET
+ @Path("/texts/view/{textKey}/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String viewDepartmentText(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("textKey") final String textKey,
+ @PathParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ textsModel.setSelectedText(textKey);
+ textsModel.setSelectedLocale(new Locale(localeParam).toString());
+
+ return "org/scientificcms/contenttypes/scidepartment/ui/texts/view-text.xhtml";
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/texts/add")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String addText(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("textKey") final String textKey,
+ @FormParam("locale") final String localeParam,
+ @FormParam("textValue") final String textValue
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final Locale locale = new Locale(localeParam);
+ final LocalizedString text = new LocalizedString();
+ text.putValue(locale, textValue);
+
+ departmentManager.addText(text, getDepartment(), textKey);
+ itemRepo.save(getDepartment());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/texts/add/{textKey}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String addTextValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("textKey") final String textKey,
+ @FormParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ if (!getDepartment().getAdditionalTexts().containsKey(textKey)) {
+ models.put("dpartmentTextNotFound", textKey);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ final DepartmentText departmentText = getDepartment()
+ .getAdditionalTexts()
+ .get(textKey);
+
+ final String value;
+ if (departmentText.getText().getAvailableLocales().isEmpty()) {
+ value = "";
+ } else {
+ value = globalizationHelper.getValueFromLocalizedString(
+ departmentText.getText()
+ );
+ }
+ final Locale locale = new Locale(localeParam);
+ departmentText.getText().putValue(locale, value);
+ departmentTextRepo.save(departmentText);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @GET
+ @Path("/texts/edit/{textKey}/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String editTextValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("textKey") final String textKey,
+ @PathParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ if (!getDepartment().getAdditionalTexts().containsKey(textKey)) {
+ models.put("dpartmentTextNotFound", textKey);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ textsModel.setSelectedText(textKey);
+ textsModel.setSelectedLocale(
+ new Locale(localeParam).toString()
+ );
+
+ return "org/scientificcms/contenttypes/scidepartment/ui/texts/edit-text.xhtml";
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/texts/edit/{textKey}/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String editTextValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("textKey") final String textKey,
+ @PathParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ if (!getDepartment().getAdditionalTexts().containsKey(textKey)) {
+ models.put("dpartmentTextNotFound", textKey);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ final DepartmentText departmentText = getDepartment()
+ .getAdditionalTexts()
+ .get(textKey);
+
+ final Locale locale = new Locale(localeParam);
+ departmentText.getText().putValue(locale, value);
+ departmentTextRepo.save(departmentText);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/texts/remove/{textKey}/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String removeTextValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("textKey") final String textKey,
+ @PathParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ if (!getDepartment().getAdditionalTexts().containsKey(textKey)) {
+ models.put("dpartmentTextNotFound", textKey);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ final DepartmentText departmentText = getDepartment()
+ .getAdditionalTexts()
+ .get(textKey);
+
+ final Locale locale = new Locale(localeParam);
+ departmentText.getText().removeValue(locale);
+ departmentTextRepo.save(departmentText);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/texts/remove/{textKey}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String removeTextValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("textKey") final String textKey
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ if (!getDepartment().getAdditionalTexts().containsKey(textKey)) {
+ models.put("dpartmentTextNotFound", textKey);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ departmentManager.removeText(getDepartment(), textKey);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/contacts/add")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String addContact(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("contactableUuid")
+ final String contactableUuid,
+ @FormParam("type")
+ final String type
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final Optional result;
+ final Identifier identifier = identifierParser.parseIdentifier(
+ contactableUuid
+ );
+ switch (identifier.getType()) {
+ case ID:
+ result = assetRepo.findById(
+ Long.parseLong(identifier.getIdentifier())
+ );
+ break;
+ case UUID:
+ result = assetRepo.findByUuid(
+ identifier.getIdentifier()
+ );
+ break;
+ default:
+ models.put("contactableNotFound", contactableUuid);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ if (!result.isPresent()
+ || !(result.get() instanceof ContactableEntity)) {
+ models.put("contactableNotFound", contactableUuid);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ final ContactableEntity contactable = (ContactableEntity) result
+ .get();
+ departmentManager.addContact(contactable, getDepartment(), type);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/contacts/edit/{contactId}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String editContact(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("contactId")
+ final String contactId,
+ @FormParam("type")
+ final String type
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final Optional result = getDepartment()
+ .getContacts()
+ .stream()
+ .filter(
+ contact -> Long
+ .toString(contact.getContactId())
+ .equals(contactId)
+ )
+ .findFirst();
+
+ if (!result.isPresent()) {
+ models.put("contactNotFound", contactId);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ final Contact contact = result.get();
+ contact.setContactType(type);
+ contactRepo.save(contact);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/contacts/{contactId}/remove")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String removeContact(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("contactId")
+ final String contactId
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final Optional result = getDepartment()
+ .getContacts()
+ .stream()
+ .filter(
+ contact -> Long
+ .toString(contact.getContactId())
+ .equals(contactId)
+ )
+ .findFirst();
+
+ if (result.isPresent()) {
+ departmentManager.removeContact(
+ result.get().getContactable(),
+ getDepartment()
+ );
+ }
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/members/add")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String addMembership(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("personUuid")
+ final String personUuid,
+ @FormParam("role")
+ final String role,
+ @FormParam("status")
+ final String statusParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final Optional result;
+ final Identifier personIdentifier = identifierParser
+ .parseIdentifier(personUuid);
+ switch (personIdentifier.getType()) {
+ case ID:
+ result = assetRepo.findById(
+ Long.parseLong(personIdentifier.getIdentifier()),
+ Person.class
+ );
+ break;
+ case UUID:
+ result = assetRepo
+ .findByUuidAndType(
+ personIdentifier.getIdentifier(),
+ Person.class
+ );
+ break;
+ default:
+ models.put("personNotFound", personUuid);
+ return showStep(sectionIdentifier, documentPath);
+
+ }
+
+ if (!result.isPresent()) {
+ models.put("personNotFound", personUuid);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ final Person person = result.get();
+ final MembershipStatus status;
+ try {
+ status = MembershipStatus.valueOf(statusParam);
+ } catch (IllegalArgumentException ex) {
+ models.put("illegalStatusValue", statusParam);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ departmentManager.addMember(person, getDepartment(), role, status);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/members/edit/{membershipId}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String editMembership(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("membershipId")
+ final String membershipId,
+ @FormParam("role")
+ final String role,
+ @FormParam("status")
+ final String statusParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final Optional result = getDepartment()
+ .getMembers()
+ .stream()
+ .filter(
+ member -> Long
+ .toString(member.getMembershipId())
+ .equals(membershipId)
+ )
+ .findFirst();
+
+ if (!result.isPresent()) {
+ models.put("membershipNotFound", membershipId);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ final Membership membership = result.get();
+ membership.setRole(role);
+ membership.setStatus(MembershipStatus.valueOf(statusParam));
+ membershipRepo.save(membership);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/members/remove/{membershipId}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String removeMembership(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("membershipId")
+ final String membershipId
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDepartment())) {
+ final Optional result = getDepartment()
+ .getMembers()
+ .stream()
+ .filter(
+ member -> Long
+ .toString(member.getMembershipId())
+ .equals(membershipId)
+ )
+ .findFirst();
+
+ if (result.isPresent()) {
+ departmentManager.removeMember(
+ result.get().getMember(),
+ getDepartment()
+ );
+ }
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDepartment(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ @Override
+ public void init() throws ContentSectionNotFoundException,
+ DocumentNotFoundException {
+ super.init();
+
+ final boolean canEdit = itemPermissionChecker.canEditItem(
+ getDepartment()
+ );
+ if (canEdit) {
+ descriptionModel.setCanEdit(canEdit);
+ descriptionModel.setDescriptionValues(
+ getDepartment()
+ .getDepartmentDescription()
+ .getValues()
+ .entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ entry -> entry.getKey().toString(),
+ Map.Entry::getValue
+ )
+ )
+ );
+ descriptionModel.setVariants(
+ getDepartment()
+ .getDepartmentDescription()
+ .getValues()
+ .entrySet()
+ .stream()
+ .map(CmsEditorUtil::buildVariantRow)
+ .collect(Collectors.toList())
+ );
+ final Set descriptionLocales = getDepartment()
+ .getDepartmentDescription()
+ .getAvailableLocales();
+ descriptionModel.setUnusedLocales(
+ globalizationHelper
+ .getAvailableLocales()
+ .stream()
+ .filter(locale -> !descriptionLocales.contains(locale))
+ .map(Locale::toString)
+ .collect(Collectors.toList())
+ );
+
+ textsModel.setCanEdit(canEdit);
+ textsModel.setTexts(
+ getDepartment()
+ .getAdditionalTexts()
+ .entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ entry -> entry.getKey(),
+ entry -> buildTextModel(entry.getValue())
+ )
+ )
+ );
+
+ contactsModel.setCanEdit(canEdit);
+ contactsModel.setContacts(
+ getDepartment()
+ .getContacts()
+ .stream()
+ .map(this::buildContactModel)
+ .collect(Collectors.toList())
+ );
+ contactsModel.setBaseUrl(baseUrl.getBaseUrl(request));
+
+ membersModel.setCanEdit(canEdit);
+ membersModel.setMembers(
+ getDepartment()
+ .getMembers()
+ .stream()
+ .map(this::buildMembershipModel)
+ .collect(Collectors.toList())
+ );
+ membersModel.setStatusValues(
+ Arrays
+ .stream(MembershipStatus.values())
+ .collect(
+ Collectors.toMap(
+ status -> status.toString(),
+ status -> messageBundle.getMessage(
+ String.format(
+ "members.status.%s",
+ status.toString().toLowerCase()
+ )
+ ),
+ (value1, value2) -> value1,
+ LinkedHashMap::new
+ )
+ )
+ );
+ membersModel.setBaseUrl(baseUrl.getBaseUrl(request));
+ }
+ }
+
+ private SciDepartment getDepartment() {
+ return (SciDepartment) getDocument();
+ }
+
+ private SciDepartmentContactModel buildContactModel(final Contact contact) {
+ final SciDepartmentContactModel model = new SciDepartmentContactModel();
+ model.setContactId(contact.getContactId());
+ model.setContactType(contact.getContactType());
+ model.setContactable(
+ contact.getContactable().getTitle().getValue(
+ globalizationHelper.getNegotiatedLocale()
+ )
+ );
+ model.setOrder(contact.getOrder());
+
+ return model;
+ }
+
+ private SciDepartmentMembershipModel buildMembershipModel(
+ final Membership membership
+ ) {
+ final SciDepartmentMembershipModel model
+ = new SciDepartmentMembershipModel();
+ model.setGivenName(
+ membership.getMember().getPersonName().getGivenName()
+ );
+ model.setMembershipId(membership.getMembershipId());
+ model.setPrefix(
+ membership.getMember().getPersonName().getPrefix()
+ );
+ model.setRole(membership.getRole());
+ model.setStatus(Objects.toString(membership.getStatus()));
+ model.setSuffix(
+ membership.getMember().getPersonName().getSuffix()
+ );
+ model.setSurname(
+ membership.getMember().getPersonName().getSurname()
+ );
+
+ return model;
+ }
+
+ private SciDepartmentTextModel buildTextModel(final DepartmentText text) {
+ final SciDepartmentTextModel model = new SciDepartmentTextModel();
+ model.setTextValues(
+ text
+ .getText()
+ .getValues()
+ .entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ entry -> entry.getKey().toString(),
+ entry -> entry.getValue()
+ )
+ )
+ );
+ model.setUnusedLocales(
+ globalizationHelper
+ .getAvailableLocales()
+ .stream()
+ .filter(
+ locale -> !text.getText().getAvailableLocales().contains(
+ locale
+ )
+ )
+ .map(Locale::toString)
+ .collect(Collectors.toList())
+ );
+ model.setVariants(
+ text
+ .getText()
+ .getValues()
+ .entrySet()
+ .stream()
+ .map(CmsEditorUtil::buildVariantRow)
+ .collect(Collectors.toList())
+ );
+
+ return model;
+ }
+
}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStepResources.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStepResources.java
new file mode 100644
index 0000000..383b41d
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStepResources.java
@@ -0,0 +1,123 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.librecms.contentsection.ContentItem;
+import org.librecms.contentsection.ContentItemRepository;
+import org.librecms.contentsection.ContentSection;
+import org.librecms.ui.contentsections.ContentSectionsUi;
+import org.librecms.ui.contentsections.ItemPermissionChecker;
+import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
+import org.scientificcms.contenttypes.scidepartment.SciDepartment;
+
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+import javax.ws.rs.ForbiddenException;
+import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Path(MvcAuthoringSteps.PATH_PREFIX + "scidepartment-description-resources")
+public class SciDepartmentDescriptionStepResources {
+
+ @Inject
+ private ContentItemRepository itemRepo;
+
+ @Inject
+ private ContentSectionsUi sectionsUi;
+
+ @Inject
+ private ItemPermissionChecker itemPermissionChecker;
+
+ @GET
+ @Path("/department-description/wordcount/{locale}")
+ @Produces(MediaType.TEXT_HTML)
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String getDepartmentDescriptionWordCount(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPathParam,
+ @PathParam("locale") final String localeParam
+ ) {
+ final ContentSection contentSection = sectionsUi
+ .findContentSection(sectionIdentifier)
+ .orElseThrow(
+ () -> new NotFoundException()
+ );
+
+ final ContentItem document = itemRepo
+ .findByPath(contentSection, documentPathParam)
+ .orElseThrow(
+ () -> new NotFoundException()
+ );
+
+ if (!(document instanceof SciDepartment)) {
+ throw new NotFoundException();
+ }
+
+ final SciDepartment department = (SciDepartment) document;
+ if (itemPermissionChecker.canEditItem(department)) {
+ final String text = department
+ .getDepartmentDescription()
+ .getValue(new Locale(localeParam));
+ final Document jsoupDoc = Jsoup.parseBodyFragment(text);
+ final long result = new StringTokenizer(
+ jsoupDoc.body().text()
+ ).countTokens();
+ return Long.toString(result);
+ } else {
+ throw new ForbiddenException();
+ }
+ }
+
+ @GET
+ @Path("/department-description/{locale}")
+ @Produces(MediaType.TEXT_HTML)
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String viewDepartmentDescriptionValue(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPathParam,
+ @PathParam("locale") final String localeParam
+ ) {
+ final ContentSection contentSection = sectionsUi
+ .findContentSection(sectionIdentifier)
+ .orElseThrow(
+ () -> new NotFoundException()
+ );
+
+ final ContentItem document = itemRepo
+ .findByPath(contentSection, documentPathParam)
+ .orElseThrow(
+ () -> new NotFoundException()
+ );
+
+ if (!(document instanceof SciDepartment)) {
+ throw new NotFoundException();
+ }
+
+ final SciDepartment department = (SciDepartment) document;
+ if (itemPermissionChecker.canEditItem(department)) {
+ return department.getDepartmentDescription().getValue(
+ new Locale(localeParam)
+ );
+ } else {
+ throw new ForbiddenException();
+ }
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStepService.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStepService.java
new file mode 100644
index 0000000..f914d36
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentDescriptionStepService.java
@@ -0,0 +1,130 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import org.librecms.contentsection.ContentItem;
+import org.librecms.contentsection.ContentItemRepository;
+import org.librecms.contentsection.ContentSection;
+import org.librecms.ui.contentsections.ContentSectionsUi;
+import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
+import org.scientificcms.contenttypes.scidepartment.Contact;
+import org.scientificcms.contenttypes.scidepartment.ContactRepository;
+import org.scientificcms.contenttypes.scidepartment.SciDepartment;
+
+import java.util.List;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Path(MvcAuthoringSteps.PATH_PREFIX + "scidepartment-description-service")
+public class SciDepartmentDescriptionStepService {
+
+ @Inject
+ private ContactRepository contactRepo;
+
+ @Inject
+ private ContentItemRepository itemRepo;
+
+ @Inject
+ private ContentSectionsUi sectionsUi;
+
+ @POST
+ @Path("/contacts/save-order")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Transactional(Transactional.TxType.REQUIRED)
+ public Response saveContactsOrder(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ final List contactsOrder
+ ) {
+ final ContentSection contentSection = sectionsUi
+ .findContentSection(sectionIdentifier)
+ .orElseThrow(
+ () -> new NotFoundException(
+ String.format(
+ "No content identifed by %s found.",
+ sectionIdentifier
+ )
+ )
+ );
+
+ final ContentItem document = itemRepo
+ .findByPath(contentSection, documentPath)
+ .orElseThrow(
+ () -> new NotFoundException(
+ String.format(
+ "No document for path %s in section %s.",
+ documentPath,
+ contentSection.getLabel()
+ )
+ )
+ );
+
+ if (!(document instanceof SciDepartment)) {
+ throw new BadRequestException(
+ String.format(
+ "Document %s is not a %s.",
+ documentPath,
+ SciDepartment.class.getSimpleName()
+ )
+ );
+ }
+
+ final SciDepartment department = (SciDepartment) document;
+
+ final List contacts = department.getContacts();
+
+ if (contactsOrder.size() != contacts.size()) {
+ throw new BadRequestException(
+ String.format(
+ "Number of contacts of the SciDepartment %s does "
+ + "not match the number of values in the order "
+ + "list. Number of contactas: %d, number of values in "
+ + "the contacts order list: %d",
+ documentPath,
+ contacts.size(),
+ contactsOrder.size()
+ )
+ );
+ }
+
+ for (int i = 0; i < contactsOrder.size(); i++) {
+ final String contactIdParam = contactsOrder.get(i);
+ final long contactId = Long.parseLong(contactIdParam);
+ final Contact contact = contacts
+ .stream()
+ .filter(con -> con.getContactId() == contactId)
+ .findAny()
+ .orElseThrow(
+ () -> new BadRequestException(
+ String.format(
+ "contactsOrder has an entry for contact with "
+ + "ID %d, but there is not contact with that "
+ + "ID.",
+ contactId
+ )
+ )
+ );
+
+ contact.setOrder(i);
+ contactRepo.save(contact);
+ }
+
+ return Response.ok().build();
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentExtendedPropertiesStep.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentExtendedPropertiesStep.java
deleted file mode 100644
index 2de024b..0000000
--- a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentExtendedPropertiesStep.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.scientificcms.contenttypes.scidepartment.ui;
-
-import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;
-import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
-import org.scientificcms.contenttypes.scidepartment.SciDepartment;
-
-import javax.enterprise.context.RequestScoped;
-import javax.mvc.Controller;
-import javax.ws.rs.Path;
-
-/**
- *
- * @author Jens Pelzetter
- */
-@RequestScoped
-@Path(MvcAuthoringSteps.PATH_PREFIX + "scidepartment-extendedproperties")
-@Controller
-@MvcAuthoringStepDef(
- bundle = SciDepartmentStepsConstants.BUNDLE,
- descriptionKey = "authoringsteps.extendedproperties.description",
- labelKey = "authoringsteps.extendedproperties.label",
- supportedDocumentType = SciDepartment.class
-)
-public class SciDepartmentExtendedPropertiesStep {
-
-}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentMembershipModel.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentMembershipModel.java
new file mode 100644
index 0000000..db39d13
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentMembershipModel.java
@@ -0,0 +1,143 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import org.scientificcms.contenttypes.scidepartment.Membership;
+import org.scientificcms.contenttypes.scidepartment.SciDepartment;
+
+/**
+ * DTO providing the information about a {@link Membership} of a
+ * {@link SciDepartment} in an form that easy usable from a MVC template.
+ *
+ * @author Jens Pelzetter
+ */
+public class SciDepartmentMembershipModel {
+
+ /**
+ * The ID of the {@link Membership}.
+ */
+ private long membershipId;
+
+ /**
+ * The role of the member.
+ *
+ * @see Membership#role
+ */
+ private String role;
+
+ /**
+ * The status of the membership.
+ *
+ * @see Membership#status
+ */
+ private String status;
+
+ /**
+ * The given name of the member.
+ *
+ * @see PersonName#givenName
+ */
+ private String givenName;
+
+ /**
+ * The surname of the member.
+ *
+ * @see PersonName#surname
+ */
+ private String surname;
+
+ /**
+ * An optional prefix for the name of the member.
+ *
+ * @see PersonName#prefix
+ */
+ private String prefix;
+
+ /**
+ * An optional suffix for the name of the member.
+ *
+ * @see PersonName#suffix
+ */
+ private String suffix;
+
+ public long getMembershipId() {
+ return membershipId;
+ }
+
+ public void setMembershipId(final long membershipId) {
+ this.membershipId = membershipId;
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public void setRole(final String role) {
+ this.role = role;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(final String status) {
+ this.status = status;
+ }
+
+ public String getName() {
+ final StringBuilder builder = new StringBuilder();
+ if (prefix != null && !prefix.isBlank()) {
+ builder.append(prefix);
+ builder.append(" ");
+ }
+ if (surname != null && !surname.isBlank()) {
+ builder.append(surname);
+ }
+ if (surname != null
+ && !surname.isBlank()
+ && givenName != null
+ && !givenName.isBlank()) {
+ builder.append(", ");
+ }
+ if (givenName != null && !givenName.isBlank()) {
+ builder.append(givenName);
+ }
+ if (suffix != null && !suffix.isBlank()) {
+ builder.append(" ");
+ builder.append(suffix);
+ }
+
+ return builder.toString();
+ }
+
+ public String getGivenName() {
+ return givenName;
+ }
+
+ public void setGivenName(final String givenName) {
+ this.givenName = givenName;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(final String surname) {
+ this.surname = surname;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public void setPrefix(final String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getSuffix() {
+ return suffix;
+ }
+
+ public void setSuffix(final String suffix) {
+ this.suffix = suffix;
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentMessageBundle.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentMessageBundle.java
new file mode 100644
index 0000000..8f0e840
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentMessageBundle.java
@@ -0,0 +1,21 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import org.libreccm.ui.AbstractMessagesBean;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Named("SciDepartmentMessageBundle")
+public class SciDepartmentMessageBundle extends AbstractMessagesBean {
+
+ @Override
+ protected String getMessageBundle() {
+ return SciDepartmentStepsConstants.BUNDLE;
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentPropertiesStep.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentPropertiesStep.java
index 9092fb3..e894add 100644
--- a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentPropertiesStep.java
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentPropertiesStep.java
@@ -1,12 +1,33 @@
package org.scientificcms.contenttypes.scidepartment.ui;
+import org.libreccm.l10n.GlobalizationHelper;
+import org.libreccm.l10n.LocalizedString;
+import org.libreccm.security.AuthorizationRequired;
+import org.librecms.contentsection.ContentItemRepository;
+import org.librecms.ui.contentsections.ContentSectionNotFoundException;
+import org.librecms.ui.contentsections.ItemPermissionChecker;
+import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep;
+import org.librecms.ui.contentsections.documents.DocumentNotFoundException;
+import org.librecms.ui.contentsections.documents.DocumentUi;
import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
import org.scientificcms.contenttypes.scidepartment.SciDepartment;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
+
import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
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;
import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
/**
*
@@ -21,6 +42,451 @@ import javax.ws.rs.Path;
labelKey = "authoringsteps.basicproperties.label",
supportedDocumentType = SciDepartment.class
)
-public class SciDepartmentPropertiesStep {
+public class SciDepartmentPropertiesStep extends AbstractMvcAuthoringStep {
+
+ @Inject
+ private SciDepartmentMessageBundle messageBundle;
+
+ /**
+ * Used for retrieving and saving the departments.
+ */
+ @Inject
+ private ContentItemRepository itemRepo;
+
+ @Inject
+ private DocumentUi documentUi;
+
+ /**
+ * Provides functions for working with {@link LocalizedString}s.
+ */
+ @Inject
+ private GlobalizationHelper globalizationHelper;
+
+ @Inject
+ private ItemPermissionChecker itemPermissionChecker;
+
+ @Inject
+ private SciDepartmentPropertiesStepModel propertiesStepModel;
+
+ @Inject
+ private Models models;
+
+ @Override
+ public Class getStepClass() {
+ return SciDepartmentPropertiesStep.class;
+ }
+
+ @Override
+ @Transactional(Transactional.TxType.REQUIRED)
+ protected void init() throws ContentSectionNotFoundException,
+ DocumentNotFoundException {
+ super.init();
+
+ propertiesStepModel.setName(getDocument().getDisplayName());
+
+ final Set titleLocales = getDocument()
+ .getTitle()
+ .getAvailableLocales();
+
+ propertiesStepModel.setTitleValues(
+ getDocument()
+ .getTitle()
+ .getValues()
+ .entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ entry -> entry.getKey().toString(),
+ entry -> entry.getValue()
+ )
+ )
+ );
+
+ propertiesStepModel.setUnusedTitleLocales(
+ globalizationHelper
+ .getAvailableLocales()
+ .stream()
+ .filter(locale -> !titleLocales.contains(locale))
+ .map(Locale::toString)
+ .collect(Collectors.toList())
+ );
+
+ final SciDepartment department = (SciDepartment) getDocument();
+
+ propertiesStepModel.setShortDescriptionValues(
+ department
+ .getShortDescription()
+ .getValues()
+ .entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ entry -> entry.getKey().toString(),
+ entry -> entry.getValue()
+ )
+ )
+ );
+ final Set shortDescriptionLocales = department
+ .getShortDescription()
+ .getAvailableLocales();
+
+ propertiesStepModel.setUnusedShortDescriptionLocales(
+ globalizationHelper
+ .getAvailableLocales()
+ .stream()
+ .filter(locale -> !shortDescriptionLocales.contains(locale))
+ .map(Locale::toString)
+ .collect(Collectors.toList())
+ );
+ }
+
+ @GET
+ @Path("/")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String showStep(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+ if (itemPermissionChecker.canEditItem(getDocument())) {
+ return "org/scientificcms/contenttypes/scidepartment/ui/scidepartment-basic-properties.xhtml";
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ messageBundle.getMessage("scidepartment.edit.denied")
+ );
+ }
+ }
+
+ /**
+ * Updates the name of the current department.
+ *
+ * @param sectionIdentifier
+ * @param documentPath
+ * @param name
+ *
+ * @return A redirect to this authoring step.
+ */
+ @POST
+ @Path("/name")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String updateName(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("name") @DefaultValue("") final String name
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDocument())) {
+ if (name.isBlank()) {
+ models.put("nameMissing", true);
+
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ getDocument().setDisplayName(name);
+ itemRepo.save(getDocument());
+
+ updateDocumentPath();
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Updates a localized title of the department.
+ *
+ * @param sectionIdentifier
+ * @param documentPath
+ * @param localeParam The locale to update.
+ * @param value The updated title value.
+ *
+ * @return A redirect to this authoring step.
+ */
+ @POST
+ @Path("/title/@add")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String addTitle(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDocument())) {
+ final Locale locale = new Locale(localeParam);
+ getDocument().getTitle().putValue(locale, value);
+ itemRepo.save(getDocument());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Updates a localized title of the department.
+ *
+ * @param sectionIdentifier
+ * @param documentPath
+ * @param localeParam The locale to update.
+ * @param value The updated title value.
+ *
+ * @return A redirect to this authoring step.
+ */
+ @POST
+ @Path("/title/@edit/{locale}")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String editTitle(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDocument())) {
+ final Locale locale = new Locale(localeParam);
+ getDocument().getTitle().putValue(locale, value);
+ itemRepo.save(getDocument());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Removes a localized title of the department.
+ *
+ * @param sectionIdentifier
+ * @param documentPath
+ * @param localeParam The locale to remove.
+ *
+ * @return A redirect to this authoring step.
+ */
+ @POST
+ @Path("/title/@remove/{locale}")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String removeTitle(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDocument())) {
+ final Locale locale = new Locale(localeParam);
+ getDocument().getTitle().removeValue(locale);
+ itemRepo.save(getDocument());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Adds a localized short description to the department.
+ *
+ * @param sectionIdentifier
+ * @param documentPath
+ * @param localeParam The locale of the description.
+ * @param value The description value.
+ *
+ * @return A redirect to this authoring step.
+ */
+ @POST
+ @Path("/short-description/@add")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String addShortDescription(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDocument())) {
+ final Locale locale = new Locale(localeParam);
+ final SciDepartment department = (SciDepartment) getDocument();
+ department.getShortDescription().putValue(locale, value);
+
+ itemRepo.save(department);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Updates a localized short description to the department.
+ *
+ * @param sectionIdentifier
+ * @param documentPath
+ * @param localeParam The locale to update.
+ * @param value The description value.
+ *
+ * @return A redirect to this authoring step.
+ */
+ @POST
+ @Path("/short-description/@edit/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String editShortDescription(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDocument())) {
+ final Locale locale = new Locale(localeParam);
+ final SciDepartment department = (SciDepartment) getDocument();
+ department.getShortDescription().putValue(locale, value);
+
+ itemRepo.save(department);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Removes a localized short description from the department.
+ *
+ * @param sectionIdentifier
+ * @param documentPath
+ * @param localeParam The locale to remove.
+ *
+ * @return A redirect to this authoring step.
+ */
+ @POST
+ @Path("/short-description/@remove/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ public String removeShortDescription(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam
+ ) {
+ try {
+ init();
+ } catch (ContentSectionNotFoundException ex) {
+ return ex.showErrorMessage();
+ } catch (DocumentNotFoundException ex) {
+ return ex.showErrorMessage();
+ }
+
+ if (itemPermissionChecker.canEditItem(getDocument())) {
+ final Locale locale = new Locale(localeParam);
+ final SciDepartment department = (SciDepartment) getDocument();
+ department.getShortDescription().removeValue(locale);
+ itemRepo.save(department);
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentPropertiesStepModel.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentPropertiesStepModel.java
new file mode 100644
index 0000000..ebc788f
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentPropertiesStepModel.java
@@ -0,0 +1,76 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Named("SciDepartmentPropertiesStep")
+public class SciDepartmentPropertiesStepModel {
+
+ private String name;
+
+ private Map titleValues;
+
+ private List unusedTitleLocales;
+
+ private Map shortDescriptionValues;
+
+ private List unusedShortDescriptionLocales;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public Map getTitleValues() {
+ return Collections.unmodifiableMap(titleValues);
+ }
+
+ public void setTitleValues(final Map titleValues) {
+ this.titleValues = new HashMap<>(titleValues);
+ }
+
+ public List getUnusedTitleLocales() {
+ return Collections.unmodifiableList(unusedTitleLocales);
+ }
+
+ public void setUnusedTitleLocales(final List unusedTitleLocales) {
+ this.unusedTitleLocales = new ArrayList<>(unusedTitleLocales);
+ }
+
+ public Map getShortDescriptionValues() {
+ return Collections.unmodifiableMap(shortDescriptionValues);
+ }
+
+ public void setShortDescriptionValues(
+ final Map shortDescriptionValues
+ ) {
+ this.shortDescriptionValues = new HashMap<>(shortDescriptionValues);
+ }
+
+ public List getUnusedShortDescriptionLocales() {
+ return Collections.unmodifiableList(unusedShortDescriptionLocales);
+ }
+
+ public void setUnusedShortDescriptionLocales(
+ final List unusedShortDescriptionLocales
+ ) {
+ this.unusedShortDescriptionLocales = new ArrayList<>(
+ unusedShortDescriptionLocales
+ );
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentTextModel.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentTextModel.java
new file mode 100644
index 0000000..b250d98
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentTextModel.java
@@ -0,0 +1,84 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow;
+import org.scientificcms.contenttypes.scidepartment.DepartmentText;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * DTO providing the data of a {@link DepartmentText} in a form that is easy
+ * usable from the view.
+ *
+ * @author Jens Pelzetter
+ */
+public class SciDepartmentTextModel {
+
+ private Map textValues;
+
+ private List variants;
+
+ private List unusedLocales;
+
+ private long order;
+
+ public Map getTextValues() {
+ return Optional
+ .ofNullable(textValues)
+ .map(Collections::unmodifiableMap)
+ .orElse(Collections.emptyMap());
+ }
+
+ protected void setTextValues(
+ final Map textValues
+ ) {
+ this.textValues = Optional
+ .ofNullable(textValues)
+ .map(values -> new HashMap<>(values))
+ .map(values -> (Map) values)
+ .orElse(Collections.emptyMap());
+ }
+
+ public List getVariants() {
+ return Optional
+ .ofNullable(variants)
+ .map(Collections::unmodifiableList)
+ .orElse(Collections.emptyList());
+ }
+
+ protected void setVariants(final List variants) {
+ this.variants = Optional
+ .ofNullable(variants)
+ .map(list -> new ArrayList<>(list))
+ .map(list -> (List) list)
+ .orElse(Collections.emptyList());
+ }
+
+ public List getUnusedLocales() {
+ return Optional
+ .ofNullable(unusedLocales)
+ .map(Collections::unmodifiableList)
+ .orElse(Collections.emptyList());
+ }
+
+ protected void setUnusedLocales(final List unusedLocales) {
+ this.unusedLocales = Optional
+ .ofNullable(unusedLocales)
+ .map(list -> new ArrayList<>(list))
+ .map(list -> (List) list)
+ .orElse(Collections.emptyList());
+ }
+
+ public long getOrder() {
+ return order;
+ }
+
+ public void setOrder(final long order) {
+ this.order = order;
+ }
+
+}
diff --git a/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentTextsModel.java b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentTextsModel.java
new file mode 100644
index 0000000..e7f7b9d
--- /dev/null
+++ b/sci-types-department/src/main/java/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentTextsModel.java
@@ -0,0 +1,53 @@
+package org.scientificcms.contenttypes.scidepartment.ui;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class SciDepartmentTextsModel {
+
+ private boolean canEdit;
+
+ private Map texts;
+
+ private String selectedText;
+
+ private String selectedLocale;
+
+ public boolean getCanEdit() {
+ return canEdit;
+ }
+
+ protected void setCanEdit(final boolean canEdit) {
+ this.canEdit = canEdit;
+ }
+
+ public Map getTexts() {
+ return Collections.unmodifiableMap(texts);
+ }
+
+ protected void setTexts(final Map texts) {
+ this.texts = new HashMap<>(texts);
+ }
+
+ public String getSelectedText() {
+ return selectedText;
+ }
+
+ public void setSelectedText(final String selectedText) {
+ this.selectedText = selectedText;
+ }
+
+ public String getSelectedLocale() {
+ return selectedLocale;
+ }
+
+ protected void setSelectedLocale(final String selectedLocale) {
+ this.selectedLocale = selectedLocale;
+ }
+
+}
diff --git a/sci-types-department/src/main/resources/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentBundle.properties b/sci-types-department/src/main/resources/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentBundle.properties
new file mode 100644
index 0000000..5e37325
--- /dev/null
+++ b/sci-types-department/src/main/resources/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentBundle.properties
@@ -0,0 +1,7 @@
+
+createstep.description=Creates a new SciDepartment.
+authoringsteps.description.description=Description of the department.
+authoringsteps.description.label=Description
+scidepartment.edit.denied=Access denied.
+authoringsteps.basicproperties.description=Basicproperties of the department.
+authoringsteps.basicproperties.label=Basic Properties
diff --git a/sci-types-department/src/main/resources/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentBundle_de.properties b/sci-types-department/src/main/resources/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentBundle_de.properties
new file mode 100644
index 0000000..c7805e8
--- /dev/null
+++ b/sci-types-department/src/main/resources/org/scientificcms/contenttypes/scidepartment/ui/SciDepartmentBundle_de.properties
@@ -0,0 +1,7 @@
+
+createstep.description=Erstellt eine neue Abteilung.
+authoringsteps.description.description=Beschreibung der Abteilung.
+authoringsteps.description.label=Beschreibung
+scidepartment.edit.denied=Zugriff verweigert.
+authoringsteps.basicproperties.description=Basiseigenschaften der Abteilung.
+authoringsteps.basicproperties.label=Basiseigenschaften
diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepService.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepService.java
index ae66eac..35f9e92 100644
--- a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepService.java
+++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepService.java
@@ -76,7 +76,7 @@ public class SciProjectDescriptionStepService {
)
);
- if ((document instanceof SciProject)) {
+ if (!(document instanceof SciProject)) {
throw new BadRequestException(
String.format(
"Document %s is not a %s.",
diff --git a/scicms-bundle-devel-wildfly/.gitignore b/scicms-bundle-devel-wildfly/.gitignore
new file mode 100644
index 0000000..bae7835
--- /dev/null
+++ b/scicms-bundle-devel-wildfly/.gitignore
@@ -0,0 +1 @@
+runtime.properties
diff --git a/scicms-bundle-devel-wildfly/runtime.properties b/scicms-bundle-devel-wildfly/runtime.properties
deleted file mode 100644
index a702584..0000000
--- a/scicms-bundle-devel-wildfly/runtime.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-libreccm.debug.suspend=n
-
-libreccm.database.host=localhost
-libreccm.database.port=5432
-libreccm.database.name=scicms-devel
-libreccm.database.user=ccm
-libreccm.database.password=ccm47web