diff --git a/ccm-core/pom.xml b/ccm-core/pom.xml
index c586fff46..b6a45760d 100644
--- a/ccm-core/pom.xml
+++ b/ccm-core/pom.xml
@@ -48,7 +48,7 @@
org.hibernate
hibernate-envers
- provided
+
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTab.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTab.java
index b04b2cc9b..5f7580f37 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTab.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTab.java
@@ -43,33 +43,44 @@ public class CategoriesTab extends LayoutPanel {
protected static final String DOMAINS_FILTER = "domainsFilter";
private final StringParameter domainIdParameter;
+ private final StringParameter languageParameter;
private final ParameterSingleSelectionModel selectedDomainId;
+ private final ParameterSingleSelectionModel selectedLanguage;
private final Label domainsFilterFormHeader;
private final Form domainsFilterForm;
private final BoxPanel domainsTablePanel;
-
+
private final DomainForm domainForm;
+ private final DomainDetails domainDetails;
+ private final DomainTitleForm domainTitleForm;
+ private final DomainDescriptionForm domainDescriptionForm;
+
public CategoriesTab() {
super();
setClassAttr("sidebarNavPanel");
domainIdParameter = new StringParameter("selected_domain_id");
- selectedDomainId = new ParameterSingleSelectionModel<>(domainIdParameter);
+ selectedDomainId
+ = new ParameterSingleSelectionModel<>(domainIdParameter);
+
+ languageParameter = new StringParameter("selected_language");
+ selectedLanguage
+ = new ParameterSingleSelectionModel<>(languageParameter);
domainsFilterFormHeader = new Label(new GlobalizedMessage(
- "ui.admin.categories.domains.table.filter.header",
- ADMIN_BUNDLE));
+ "ui.admin.categories.domains.table.filter.header",
+ ADMIN_BUNDLE));
domainsFilterForm = new Form("domainFilterForm");
final TextField domainsFilter = new TextField(DOMAINS_FILTER);
domainsFilterForm.add(domainsFilter);
domainsFilterForm.add(new Submit(new GlobalizedMessage(
- "ui.admin.categories.domains.table.filter", ADMIN_BUNDLE)));
+ "ui.admin.categories.domains.table.filter", ADMIN_BUNDLE)));
final ActionLink clearLink = new ActionLink(new GlobalizedMessage(
- "ui.admin.categories.domains.table.filter.clear",
- ADMIN_BUNDLE));
+ "ui.admin.categories.domains.table.filter.clear",
+ ADMIN_BUNDLE));
clearLink.addActionListener(e -> {
final PageState state = e.getPageState();
domainsFilter.setValue(state, null);
@@ -80,29 +91,43 @@ public class CategoriesTab extends LayoutPanel {
left.addSegment(domainsFilterFormHeader, domainsFilterForm);
setLeft(left);
-
+
final BoxPanel body = new BoxPanel(BoxPanel.VERTICAL);
final DomainsTable domainsTable = new DomainsTable(
- selectedDomainId, domainsFilter);
+ this, selectedDomainId, domainsFilter);
domainsTable.setStyleAttr("min-width: 30em;");
domainsTablePanel = new BoxPanel(BoxPanel.VERTICAL);
domainsTablePanel.add(domainsTable);
final ActionLink addDomain = new ActionLink(new GlobalizedMessage(
- "ui.admin.categories.domains.create_new", ADMIN_BUNDLE));
+ "ui.admin.categories.domains.create_new", ADMIN_BUNDLE));
addDomain.addActionListener(e -> {
- showNewDomainForm(e.getPageState());
+ showDomainForm(e.getPageState());
});
domainsTablePanel.add(addDomain);
-
+
body.add(domainsTablePanel);
-
+
domainForm = new DomainForm(this, selectedDomainId);
body.add(domainForm);
-
+
+ domainDetails = new DomainDetails(this,
+ selectedDomainId,
+ selectedLanguage);
+ body.add(domainDetails);
+
+ domainTitleForm = new DomainTitleForm(this,
+ selectedDomainId,
+ selectedLanguage);
+ body.add(domainTitleForm);
+
+ domainDescriptionForm = new DomainDescriptionForm(this,
+ selectedDomainId,
+ selectedLanguage);
+ body.add(domainDescriptionForm);
+
setBody(body);
-
-
+
}
@Override
@@ -110,11 +135,15 @@ public class CategoriesTab extends LayoutPanel {
super.register(page);
page.addGlobalStateParam(domainIdParameter);
-
+ page.addGlobalStateParam(languageParameter);
+
page.setVisibleDefault(domainsFilterFormHeader, true);
page.setVisibleDefault(domainsFilterForm, true);
page.setVisibleDefault(domainsTablePanel, true);
page.setVisibleDefault(domainForm, false);
+ page.setVisibleDefault(domainDetails, false);
+ page.setVisibleDefault(domainTitleForm, false);
+ page.setVisibleDefault(domainDescriptionForm, false);
}
protected void showDomainsTable(final PageState state) {
@@ -122,20 +151,88 @@ public class CategoriesTab extends LayoutPanel {
domainsFilterForm.setVisible(state, true);
domainsTablePanel.setVisible(state, true);
domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
}
- protected void showNewDomainForm(final PageState state) {
+ protected void showDomainForm(final PageState state) {
domainsFilterFormHeader.setVisible(state, false);
domainsFilterForm.setVisible(state, false);
domainsTablePanel.setVisible(state, false);
domainForm.setVisible(state, true);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
}
- protected void hideNewDomainForm(final PageState state) {
+ protected void hideDomainForm(final PageState state) {
+ if (selectedDomainId.getSelectedKey(state) == null) {
+ domainsFilterFormHeader.setVisible(state, true);
+ domainsFilterForm.setVisible(state, true);
+ domainsTablePanel.setVisible(state, true);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
+ } else {
+ showDomainDetails(state);
+ }
+
+ }
+
+ protected void showDomainDetails(final PageState state) {
+ domainsFilterFormHeader.setVisible(state, false);
+ domainsFilterForm.setVisible(state, false);
+ domainsTablePanel.setVisible(state, false);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, true);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
+ }
+
+ protected void hideDomainDetails(final PageState state) {
+ selectedDomainId.clearSelection(state);
+
domainsFilterFormHeader.setVisible(state, true);
domainsFilterForm.setVisible(state, true);
domainsTablePanel.setVisible(state, true);
domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
+ }
+
+ protected void showDomainTitleForm(final PageState state) {
+ domainsFilterFormHeader.setVisible(state, false);
+ domainsFilterForm.setVisible(state, false);
+ domainsTablePanel.setVisible(state, false);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, true);
+ domainDescriptionForm.setVisible(state, false);
+ }
+
+ protected void hideDomainTitleForm(final PageState state) {
+ selectedLanguage.clearSelection(state);
+
+ showDomainDetails(state);
+ }
+
+ protected void showDomainDescriptionForm(final PageState state) {
+ domainsFilterFormHeader.setVisible(state, false);
+ domainsFilterForm.setVisible(state, false);
+ domainsTablePanel.setVisible(state, false);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, true);
+ }
+
+ protected void hideDomainDescriptionForm(final PageState state) {
+ selectedLanguage.clearSelection(state);
+
+ showDomainDetails(state);
}
}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionForm.java
new file mode 100644
index 000000000..4d2cf3327
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionForm.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.BoxPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.form.TextArea;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+import org.apache.logging.log4j.util.Strings;
+import org.libreccm.categorization.Domain;
+import org.libreccm.categorization.DomainRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import java.util.Locale;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class DomainDescriptionForm extends Form {
+
+ private static final String LOCALIZED_DOMAIN_DESC = "description";
+
+ private final CategoriesTab categoriesTab;
+
+ private final TextArea description;
+ private final SaveCancelSection saveCancelSection;
+
+ public DomainDescriptionForm(
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedDomainId,
+ final ParameterSingleSelectionModel selectedLanguage) {
+
+ super("domainDescriptionForm", new BoxPanel(BoxPanel.VERTICAL));
+
+ this.categoriesTab = categoriesTab;
+
+ final ActionLink backLink = new ActionLink(new GlobalizedMessage(
+ "ui.admin.categories.domain.description.edit.back", ADMIN_BUNDLE));
+ backLink.addActionListener(e -> {
+ categoriesTab.hideDomainTitleForm(e.getPageState());
+ });
+ add(backLink);
+
+ final Label heading = new Label(e -> {
+ final PageState state = e.getPageState();
+
+ final DomainRepository domainRepository = CdiUtil.createCdiUtil()
+ .findBean(DomainRepository.class);
+ final Domain selectedDomain = domainRepository.findById(
+ Long.parseLong(selectedDomainId.getSelectedKey(state)));
+
+ final Locale selectedLocale = new Locale(selectedLanguage
+ .getSelectedKey(state));
+
+ final Label target = (Label) e.getTarget();
+
+ if (selectedDomain.getTitle().hasValue(selectedLocale)) {
+ target.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.domain.description.edit_for_lang",
+ ADMIN_BUNDLE,
+ new String[]{selectedDomain.getDomainKey(),
+ selectedLocale.toString()}));
+ } else {
+ target.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.domain.description.add_for_lang",
+ ADMIN_BUNDLE,
+ new String[]{selectedDomain.getDomainKey(),
+ selectedLocale.toString()}));
+ }
+ });
+ heading.setClassAttr("heading");
+ add(heading);
+
+ description = new TextArea(LOCALIZED_DOMAIN_DESC);
+ description.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.domain.description.label", ADMIN_BUNDLE));
+ description.setCols(60);
+ description.setRows(10);
+ add(description);
+
+ saveCancelSection = new SaveCancelSection();
+ add(saveCancelSection);
+
+ addInitListener(e -> {
+ final PageState state = e.getPageState();
+
+ final DomainRepository domainRepository = CdiUtil.createCdiUtil()
+ .findBean(DomainRepository.class);
+ final Domain selectedDomain = domainRepository.findById(
+ Long.parseLong(selectedDomainId.getSelectedKey(state)));
+
+ final Locale selectedLocale = new Locale(selectedLanguage
+ .getSelectedKey(state));
+
+ if (selectedDomain.getTitle().hasValue(selectedLocale)) {
+ description.setValue(state, selectedDomain.getDescription()
+ .getValue(selectedLocale));
+ }
+ });
+
+ addValidationListener(e -> {
+
+ if (saveCancelSection.getSaveButton().isSelected(
+ e.getPageState())) {
+ final FormData data = e.getFormData();
+
+ final String titleData = data.getString(LOCALIZED_DOMAIN_DESC);
+
+ if (Strings.isBlank(titleData)) {
+ data.addError(
+ LOCALIZED_DOMAIN_DESC,
+ new GlobalizedMessage(
+ "ui.admin.categories.domain.description.error.not_blank",
+ ADMIN_BUNDLE));
+ }
+ }
+ });
+
+ addProcessListener(e -> {
+ final PageState state = e.getPageState();
+
+ if (saveCancelSection.getSaveButton().isSelected(state)) {
+ final DomainRepository domainRepository = CdiUtil
+ .createCdiUtil()
+ .findBean(DomainRepository.class);
+ final Domain selectedDomain = domainRepository.findById(
+ Long.parseLong(selectedDomainId.getSelectedKey(state)));
+
+ final Locale selectedLocale = new Locale(selectedLanguage
+ .getSelectedKey(state));
+
+ final String titleData = e.getFormData().getString(
+ LOCALIZED_DOMAIN_DESC);
+
+ selectedDomain.getDescription().addValue(selectedLocale,
+ titleData);
+ domainRepository.save(selectedDomain);
+ }
+
+ categoriesTab.hideDomainDescriptionForm(state);
+
+ });
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionTable.java
new file mode 100644
index 000000000..53d9f2e6a
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionTable.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.Text;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.LockableImpl;
+
+import org.libreccm.categorization.Domain;
+import org.libreccm.categorization.DomainRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class DomainDescriptionTable extends Table {
+
+ private static final int COL_LOCALE = 0;
+ private static final int COL_VALUE = 1;
+ private static final int COL_DEL = 2;
+
+ private final CategoriesTab categoriesTab;
+ private final ParameterSingleSelectionModel selectedDomainId;
+ private final ParameterSingleSelectionModel selectedLanguage;
+
+ public DomainDescriptionTable(
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedDomainId,
+ final ParameterSingleSelectionModel selectedLanguage) {
+
+ super();
+
+ this.categoriesTab = categoriesTab;
+ this.selectedDomainId = selectedDomainId;
+ this.selectedLanguage = selectedLanguage;
+
+ setIdAttr("domainDescriptionTable");
+
+ setEmptyView(new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.description.none",
+ ADMIN_BUNDLE)));
+
+ final TableColumnModel columnModel = getColumnModel();
+ columnModel.add(new TableColumn(
+ COL_LOCALE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.description.col_lang",
+ ADMIN_BUNDLE))));
+ columnModel.add(new TableColumn(
+ COL_VALUE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.description.col_value",
+ ADMIN_BUNDLE))));
+ columnModel.add(new TableColumn(
+ COL_DEL,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.description.col_del",
+ ADMIN_BUNDLE))));
+
+ columnModel.get(COL_LOCALE).setCellRenderer(new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ return new ControlLink((String) value);
+ }
+
+ });
+
+ columnModel.get(COL_DEL).setCellRenderer(new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ if (value == null) {
+ return new Text("");
+ } else {
+ final ControlLink link = new ControlLink((Component) value);
+ link.setConfirmation(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.description"
+ + ".del_confirm",
+ ADMIN_BUNDLE));
+ return link;
+ }
+ }
+
+ });
+
+ addTableActionListener(new TableActionListener() {
+
+ @Override
+ public void cellSelected(final TableActionEvent event) {
+ final PageState state = event.getPageState();
+
+ switch (event.getColumn()) {
+ case COL_LOCALE:
+ selectedLanguage.setSelectedKey(state,
+ event.getRowKey());
+ categoriesTab.showDomainDescriptionForm(state);
+ break;
+ case COL_DEL:
+ final Locale locale = new Locale((String) event
+ .getRowKey());
+ final DomainRepository domainRepository = CdiUtil
+ .createCdiUtil().findBean(DomainRepository.class);
+ final Domain domain = domainRepository.findById(
+ Long.parseLong(selectedDomainId
+ .getSelectedKey(state)));
+ domain.getDescription().removeValue(locale);
+
+ domainRepository.save(domain);
+
+ break;
+ }
+ }
+
+ @Override
+ public void headSelected(final TableActionEvent event) {
+ //Nothing
+ }
+
+ });
+
+ setModelBuilder(new DomainDescriptionTableModelBuilder());
+
+ }
+
+ private class DomainDescriptionTableModelBuilder
+ extends LockableImpl
+ implements TableModelBuilder {
+
+ @Override
+ public TableModel makeModel(final Table table,
+ final PageState state) {
+ table.getRowSelectionModel().clearSelection(state);
+
+ return new DomainDescriptionTableModel(state);
+ }
+
+ }
+
+ private class DomainDescriptionTableModel implements TableModel {
+
+ private final Domain selectedDomain;
+ private final List locales;
+ private int index = -1;
+
+ public DomainDescriptionTableModel(final PageState state) {
+ final DomainRepository domainRepository = CdiUtil.createCdiUtil()
+ .findBean(DomainRepository.class);
+ selectedDomain = domainRepository.findById(
+ Long.parseLong(selectedDomainId.getSelectedKey(state)));
+
+ locales = new ArrayList<>();
+ locales.addAll(selectedDomain.getDescription()
+ .getAvailableLocales());
+ locales.sort((l1, l2) -> {
+ return l1.toString().compareTo(l2.toString());
+ });
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+
+ @Override
+ public boolean nextRow() {
+ index++;
+ return index < locales.size();
+ }
+
+ @Override
+ public Object getElementAt(final int columnIndex) {
+ final Locale locale = locales.get(index);
+
+ switch (columnIndex) {
+ case COL_LOCALE:
+ return locale.toString();
+ case COL_VALUE:
+ return selectedDomain.getDescription().getValue(locale);
+ case COL_DEL:
+ return new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.description.del",
+ ADMIN_BUNDLE));
+ default:
+ throw new IllegalArgumentException(
+ "Not a valid column index");
+ }
+ }
+
+ @Override
+ public Object getKeyAt(final int columnIndex) {
+ return locales.get(index);
+ }
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDetails.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDetails.java
new file mode 100644
index 000000000..a49ff25f8
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDetails.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.BoxPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.PropertySheet;
+import com.arsdigita.bebop.SegmentedPanel;
+import com.arsdigita.bebop.Text;
+import com.arsdigita.bebop.form.Option;
+import com.arsdigita.bebop.form.SingleSelect;
+import com.arsdigita.bebop.form.Submit;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.kernel.KernelConfig;
+import com.arsdigita.util.UncheckedWrapperException;
+
+import org.libreccm.categorization.Domain;
+import org.libreccm.categorization.DomainRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TooManyListenersException;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+import static org.bouncycastle.asn1.x500.style.RFC4519Style.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class DomainDetails extends SegmentedPanel {
+
+ private final CategoriesTab categoriesTab;
+ private final ParameterSingleSelectionModel selectedDomainId;
+ private final ParameterSingleSelectionModel selectedLanguage;
+ private final DomainTitleAddForm domainTitleAddForm;
+ private final DomainDescriptionAddForm domainDescriptionAddForm;
+
+ public DomainDetails(
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedDomainId,
+ final ParameterSingleSelectionModel selectedLanguage) {
+
+ this.categoriesTab = categoriesTab;
+ this.selectedDomainId = selectedDomainId;
+ this.selectedLanguage = selectedLanguage;
+
+ final ActionLink backLink = new ActionLink(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.back", ADMIN_BUNDLE));
+ backLink.addActionListener(e -> {
+ final PageState state = e.getPageState();
+ categoriesTab.hideDomainDetails(state);
+ });
+ addSegment("domain-details-back", backLink);
+
+ final BoxPanel propertiesPanel = new BoxPanel(BoxPanel.VERTICAL);
+ propertiesPanel.add(new PropertySheet(
+ new DomainPropertySheetModelBuilder(selectedDomainId)));
+ final ActionLink editBasicPropertiesLink = new ActionLink(
+ new GlobalizedMessage(
+ "ui.admin.categories.domain_details.basic_properties.edit",
+ ADMIN_BUNDLE));
+ editBasicPropertiesLink.addActionListener(e -> {
+ final PageState state = e.getPageState();
+ categoriesTab.showDomainForm(state);
+ });
+ propertiesPanel.add(editBasicPropertiesLink);
+ addSegment(
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.basic_properties",
+ ADMIN_BUNDLE)),
+ propertiesPanel);
+
+ final BoxPanel titlesPanel = new BoxPanel(BoxPanel.VERTICAL);
+ titlesPanel.add(new DomainTitleTable(categoriesTab,
+ selectedDomainId,
+ selectedLanguage));
+ domainTitleAddForm = new DomainTitleAddForm();
+ titlesPanel.add(domainTitleAddForm);
+ addSegment(
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.domain_title",
+ ADMIN_BUNDLE)),
+ titlesPanel);
+
+ final BoxPanel descPanel = new BoxPanel(BoxPanel.VERTICAL);
+ descPanel.add(new DomainDescriptionTable(categoriesTab,
+ selectedDomainId,
+ selectedLanguage));
+ domainDescriptionAddForm = new DomainDescriptionAddForm();
+ descPanel.add(domainDescriptionAddForm);
+ addSegment(
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.description",
+ ADMIN_BUNDLE)),
+ descPanel);
+
+ addSegment(
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.mappings",
+ ADMIN_BUNDLE)),
+ new Text("domain_mappings_placeholder"));
+ }
+
+ private class DomainTitleAddForm extends Form {
+
+ private static final String TITLE_SELECT_LANG = "titleSelectLang";
+
+ public DomainTitleAddForm() {
+ super("domainAddTitleLang", new BoxPanel(BoxPanel.HORIZONTAL));
+
+ final SingleSelect titleSelectLang = new SingleSelect(
+ TITLE_SELECT_LANG);
+ titleSelectLang.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.domain_title.add.label",
+ ADMIN_BUNDLE));
+ try {
+ titleSelectLang.addPrintListener(e -> {
+ final PageState state = e.getPageState();
+
+ final DomainRepository domainRepository = CdiUtil
+ .createCdiUtil().findBean(DomainRepository.class);
+ final Domain domain = domainRepository.findById(Long
+ .parseLong(
+ selectedDomainId.getSelectedKey(state)));
+ final KernelConfig kernelConfig = KernelConfig.getConfig();
+ final Set supportedLanguages = kernelConfig
+ .getSupportedLanguages();
+ final Set assignedLanguages = new HashSet<>();
+ domain.getTitle().getAvailableLocales().forEach(l -> {
+ assignedLanguages.add(l.toString());
+ });
+
+ final SingleSelect target = (SingleSelect) e.getTarget();
+
+ target.clearOptions();
+
+ supportedLanguages.forEach(l -> {
+ if (!assignedLanguages.contains(l)) {
+ target.addOption(new Option(l, new Text(l)));
+ }
+ });
+ });
+ } catch (TooManyListenersException ex) {
+ throw new UncheckedWrapperException(ex);
+ }
+
+ add(titleSelectLang);
+ add(new Submit(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.domain_title.add.submit",
+ ADMIN_BUNDLE)));
+
+ addProcessListener(e -> {
+ final PageState state = e.getPageState();
+ final FormData data = e.getFormData();
+
+ final String language = data.getString(TITLE_SELECT_LANG);
+ selectedLanguage.setSelectedKey(state, language);
+
+ categoriesTab.showDomainTitleForm(state);
+ });
+ }
+
+ @Override
+ public boolean isVisible(final PageState state) {
+ if (super.isVisible(state)) {
+
+ final DomainRepository domainRepository = CdiUtil
+ .createCdiUtil().findBean(DomainRepository.class);
+ final Domain domain = domainRepository.findById(Long
+ .parseLong(
+ selectedDomainId.getSelectedKey(state)));
+ final KernelConfig kernelConfig = KernelConfig.getConfig();
+ final Set supportedLanguages = kernelConfig
+ .getSupportedLanguages();
+ final Set assignedLanguages = new HashSet<>();
+ domain.getTitle().getAvailableLocales().forEach(l -> {
+ assignedLanguages.add(l.toString());
+ });
+
+ //If all supported languages are assigned the form is not
+ //visible
+ return !assignedLanguages.equals(supportedLanguages);
+
+ } else {
+ return false;
+ }
+ }
+
+ }
+
+ private class DomainDescriptionAddForm extends Form {
+
+ private static final String DESC_SELECT_LANG = "descSelectLang";
+
+ public DomainDescriptionAddForm() {
+ super("domainAddDescLang", new BoxPanel(BoxPanel.HORIZONTAL));
+
+ final SingleSelect descSelectLang = new SingleSelect(
+ DESC_SELECT_LANG);
+ descSelectLang.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.domain_desc.add.label",
+ ADMIN_BUNDLE));
+ try {
+ descSelectLang.addPrintListener(e -> {
+ final PageState state = e.getPageState();
+
+ final DomainRepository domainRepository = CdiUtil
+ .createCdiUtil().findBean(DomainRepository.class);
+ final Domain domain = domainRepository.findById(Long
+ .parseLong(
+ selectedDomainId.getSelectedKey(state)));
+ final KernelConfig kernelConfig = KernelConfig.getConfig();
+ final Set supportedLanguages = kernelConfig
+ .getSupportedLanguages();
+ final Set assignedLanguages = new HashSet<>();
+ domain.getDescription().getAvailableLocales().forEach(l -> {
+ assignedLanguages.add(l.toString());
+ });
+
+ final SingleSelect target = (SingleSelect) e.getTarget();
+
+ target.clearOptions();
+
+ supportedLanguages.forEach(l -> {
+ if (!assignedLanguages.contains(l)) {
+ target.addOption(new Option(l, new Text(l)));
+ }
+ });
+ });
+ } catch (TooManyListenersException ex) {
+ throw new UncheckedWrapperException(ex);
+ }
+
+ add(descSelectLang);
+ add(new Submit(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.domain_desc.add.submit",
+ ADMIN_BUNDLE)));
+
+ addProcessListener(e -> {
+ final PageState state = e.getPageState();
+ final FormData data = e.getFormData();
+
+ final String language = data.getString(DESC_SELECT_LANG);
+ selectedLanguage.setSelectedKey(state, language);
+
+ categoriesTab.showDomainDescriptionForm(state);
+
+ });
+ }
+
+ @Override
+ public boolean isVisible(final PageState state) {
+ if (super.isVisible(state)) {
+
+ final DomainRepository domainRepository = CdiUtil
+ .createCdiUtil().findBean(DomainRepository.class);
+ final Domain domain = domainRepository.findById(Long
+ .parseLong(
+ selectedDomainId.getSelectedKey(state)));
+ final KernelConfig kernelConfig = KernelConfig.getConfig();
+ final Set supportedLanguages = kernelConfig
+ .getSupportedLanguages();
+ final Set assignedLanguages = new HashSet<>();
+ domain.getDescription().getAvailableLocales().forEach(l -> {
+ assignedLanguages.add(l.toString());
+ });
+
+ //If all supported languages are assigned the form is not
+ //visible
+ return !assignedLanguages.equals(supportedLanguages);
+
+ } else {
+ return false;
+ }
+ }
+ }
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainForm.java
index 96cf2516c..06566f260 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainForm.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainForm.java
@@ -35,6 +35,8 @@ import org.libreccm.categorization.DomainManager;
import org.libreccm.categorization.DomainRepository;
import org.libreccm.cdi.utils.CdiUtil;
+import java.util.Locale;
+
import static com.arsdigita.ui.admin.AdminUiConstants.*;
/**
@@ -211,7 +213,7 @@ public class DomainForm extends Form {
domainRepository.save(domain);
}
- categoriesTab.hideNewDomainForm(state);
+ categoriesTab.hideDomainForm(state);
});
}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainPropertySheetModel.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainPropertySheetModel.java
new file mode 100644
index 000000000..507cece99
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainPropertySheetModel.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.PropertySheetModel;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+import org.libreccm.categorization.Domain;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class DomainPropertySheetModel implements PropertySheetModel {
+
+ private static enum DomainProperty {
+ DOMAIN_KEY,
+ URI,
+ VERSION,
+ RELEASED
+ }
+
+ private final Domain selectedDomain;
+ private final Iterator propertyIterator;
+ private DomainProperty currentProperty;
+
+ public DomainPropertySheetModel(final Domain selectedDomain) {
+ this.selectedDomain = selectedDomain;
+ propertyIterator = Arrays.asList(DomainProperty.values()).iterator();
+ }
+
+ @Override
+ public boolean nextRow() {
+ if (selectedDomain == null) {
+ return false;
+ }
+
+ if (propertyIterator.hasNext()) {
+ currentProperty = propertyIterator.next();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public String getLabel() {
+ return currentProperty.toString();
+ }
+
+ private GlobalizedMessage generatedGlobalizedLabel(
+ final DomainProperty property) {
+
+ final String key = String.join(
+ "",
+ "ui.admin.categories.domain.property_sheet.",
+ property.toString().toLowerCase());
+ return new GlobalizedMessage(key, ADMIN_BUNDLE);
+ }
+
+ @Override
+ public GlobalizedMessage getGlobalizedLabel() {
+ return generatedGlobalizedLabel(currentProperty);
+ }
+
+ @Override
+ public String getValue() {
+ switch (currentProperty) {
+ case DOMAIN_KEY:
+ return selectedDomain.getDomainKey();
+ case URI:
+ return selectedDomain.getUri();
+ case VERSION:
+ return selectedDomain.getVersion();
+ case RELEASED:
+ if (selectedDomain.getReleased() == null) {
+ return "";
+ } else {
+ return String.format("%tY-%Jens Pelzetter
+ */
+public class DomainPropertySheetModelBuilder
+ extends LockableImpl
+ implements PropertySheetModelBuilder {
+
+ private final ParameterSingleSelectionModel selectedDomainId;
+
+ public DomainPropertySheetModelBuilder(
+ final ParameterSingleSelectionModel selectedDomainId) {
+
+ this.selectedDomainId = selectedDomainId;
+
+ }
+
+ @Override
+ public PropertySheetModel makeModel(final PropertySheet sheet,
+ final PageState state) {
+ final String domainIdStr = selectedDomainId.getSelectedKey(state);
+ final Domain selectedDomain;
+ if (Strings.isBlank(domainIdStr)) {
+ selectedDomain = null;
+ } else {
+ final DomainRepository domainRepository = CdiUtil.createCdiUtil()
+ .findBean(DomainRepository.class);
+ selectedDomain = domainRepository.findById(Long.parseLong(
+ domainIdStr));
+ }
+
+ return new DomainPropertySheetModel(selectedDomain);
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainTitleForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainTitleForm.java
new file mode 100644
index 000000000..a8a3c592c
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainTitleForm.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.BoxPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+import org.apache.logging.log4j.util.Strings;
+import org.libreccm.categorization.Domain;
+import org.libreccm.categorization.DomainRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import java.util.Locale;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class DomainTitleForm extends Form {
+
+ private static final String LOCALIZED_DOMAIN_TITLE = "title";
+
+ private final CategoriesTab categoriesTab;
+
+ private final TextField title;
+ private final SaveCancelSection saveCancelSection;
+
+ public DomainTitleForm(
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedDomainId,
+ final ParameterSingleSelectionModel selectedLanguage) {
+
+ super("domainTitleForm", new BoxPanel(BoxPanel.VERTICAL));
+
+ this.categoriesTab = categoriesTab;
+
+ final ActionLink backLink = new ActionLink(new GlobalizedMessage(
+ "ui.admin.categories.domain.title.edit.back", ADMIN_BUNDLE));
+ backLink.addActionListener(e -> {
+ categoriesTab.hideDomainTitleForm(e.getPageState());
+ });
+ add(backLink);
+
+ final Label heading = new Label(e -> {
+ final PageState state = e.getPageState();
+
+ final DomainRepository domainRepository = CdiUtil.createCdiUtil()
+ .findBean(DomainRepository.class);
+ final Domain selectedDomain = domainRepository.findById(
+ Long.parseLong(selectedDomainId.getSelectedKey(state)));
+
+ final Locale selectedLocale = new Locale(selectedLanguage
+ .getSelectedKey(state));
+
+ final Label target = (Label) e.getTarget();
+
+ if (selectedDomain.getTitle().hasValue(selectedLocale)) {
+ target.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.domain.title.edit_for_lang",
+ ADMIN_BUNDLE,
+ new String[]{selectedDomain.getDomainKey(),
+ selectedLocale.toString()}));
+ } else {
+ target.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.domain.title.add_for_lang",
+ ADMIN_BUNDLE,
+ new String[]{selectedDomain.getDomainKey(),
+ selectedLocale.toString()}));
+ }
+ });
+ heading.setClassAttr("heading");
+ add(heading);
+
+ title = new TextField(LOCALIZED_DOMAIN_TITLE);
+ title.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.domain.title.label", ADMIN_BUNDLE));
+ add(title);
+
+ saveCancelSection = new SaveCancelSection();
+ add(saveCancelSection);
+
+ addInitListener(e -> {
+ final PageState state = e.getPageState();
+
+ final DomainRepository domainRepository = CdiUtil.createCdiUtil()
+ .findBean(DomainRepository.class);
+ final Domain selectedDomain = domainRepository.findById(
+ Long.parseLong(selectedDomainId.getSelectedKey(state)));
+
+ final Locale selectedLocale = new Locale(selectedLanguage
+ .getSelectedKey(state));
+
+ if (selectedDomain.getTitle().hasValue(selectedLocale)) {
+ title.setValue(state, selectedDomain.getTitle().getValue(
+ selectedLocale));
+ }
+ });
+
+ addValidationListener(e -> {
+
+ if (saveCancelSection.getSaveButton().isSelected(
+ e.getPageState())) {
+ final FormData data = e.getFormData();
+
+ final String titleData = data.getString(LOCALIZED_DOMAIN_TITLE);
+
+ if (Strings.isBlank(titleData)) {
+ data.addError(
+ LOCALIZED_DOMAIN_TITLE,
+ new GlobalizedMessage(
+ "ui.admin.categories.domain.title.error.not_blank",
+ ADMIN_BUNDLE));
+ }
+ }
+ });
+
+ addProcessListener(e -> {
+ final PageState state = e.getPageState();
+
+ if (saveCancelSection.getSaveButton().isSelected(state)) {
+ final DomainRepository domainRepository = CdiUtil
+ .createCdiUtil()
+ .findBean(DomainRepository.class);
+ final Domain selectedDomain = domainRepository.findById(
+ Long.parseLong(selectedDomainId.getSelectedKey(state)));
+
+ final Locale selectedLocale = new Locale(selectedLanguage
+ .getSelectedKey(state));
+
+ final String titleData = e.getFormData().getString(
+ LOCALIZED_DOMAIN_TITLE);
+
+ selectedDomain.getTitle().addValue(selectedLocale, titleData);
+ domainRepository.save(selectedDomain);
+ }
+
+ categoriesTab.hideDomainTitleForm(state);
+ });
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainTitleTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainTitleTable.java
new file mode 100644
index 000000000..80341533b
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainTitleTable.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.Text;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.LockableImpl;
+
+import org.libreccm.categorization.Domain;
+import org.libreccm.categorization.DomainRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class DomainTitleTable extends Table {
+
+ private static final int COL_LOCALE = 0;
+ private static final int COL_VALUE = 1;
+ private static final int COL_DEL = 2;
+
+ private final CategoriesTab categoriesTab;
+ private final ParameterSingleSelectionModel selectedDomainId;
+ private final ParameterSingleSelectionModel selectedLanguage;
+
+ public DomainTitleTable(
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedDomainId,
+ final ParameterSingleSelectionModel selectedLanguage) {
+
+ super();
+
+ this.categoriesTab = categoriesTab;
+ this.selectedDomainId = selectedDomainId;
+ this.selectedLanguage = selectedLanguage;
+
+ setIdAttr("domainTitleTable");
+
+ setEmptyView(new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.title.none", ADMIN_BUNDLE)));
+
+ final TableColumnModel columnModel = getColumnModel();
+ columnModel.add(new TableColumn(
+ COL_LOCALE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.title.col_lang",
+ ADMIN_BUNDLE))));
+ columnModel.add(new TableColumn(
+ COL_VALUE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.title.col_value",
+ ADMIN_BUNDLE))));
+ columnModel.add(new TableColumn(
+ COL_DEL,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.title.col_del",
+ ADMIN_BUNDLE))));
+
+ columnModel.get(COL_LOCALE).setCellRenderer(new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ return new ControlLink((String) value);
+ }
+
+ });
+
+ columnModel.get(COL_DEL).setCellRenderer(new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ if (value == null) {
+ return new Text("");
+ } else {
+ final ControlLink link = new ControlLink((Component) value);
+ link.setConfirmation(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.title.del_confirm",
+ ADMIN_BUNDLE));
+ return link;
+ }
+ }
+
+ });
+
+ addTableActionListener(new TableActionListener() {
+
+ @Override
+ public void cellSelected(final TableActionEvent event) {
+ final PageState state = event.getPageState();
+
+ switch (event.getColumn()) {
+ case COL_LOCALE:
+ selectedLanguage.setSelectedKey(state,
+ event.getRowKey());
+ categoriesTab.showDomainTitleForm(state);
+ break;
+ case COL_DEL:
+ final Locale locale = new Locale((String) event
+ .getRowKey());
+ final DomainRepository domainRepository = CdiUtil
+ .createCdiUtil().findBean(DomainRepository.class);
+ final Domain domain = domainRepository.findById(
+ Long.parseLong(selectedDomainId
+ .getSelectedKey(state)));
+ domain.getTitle().removeValue(locale);
+
+ domainRepository.save(domain);
+
+ break;
+ }
+ }
+
+ @Override
+ public void headSelected(final TableActionEvent e) {
+ //Nothing
+ }
+
+ });
+
+ setModelBuilder(new DomainTitleTableModelBuilder());
+ }
+
+ private class DomainTitleTableModelBuilder
+ extends LockableImpl
+ implements TableModelBuilder {
+
+ @Override
+ public TableModel makeModel(final Table table, final PageState state) {
+ table.getRowSelectionModel().clearSelection(state);
+
+ return new DomainTitleTableModel(state);
+ }
+
+ }
+
+ private class DomainTitleTableModel implements TableModel {
+
+ private final Domain selectedDomain;
+ private final List locales;
+ private int index = -1;
+
+ public DomainTitleTableModel(final PageState state) {
+ final DomainRepository domainRepository = CdiUtil.createCdiUtil()
+ .findBean(DomainRepository.class);
+ selectedDomain = domainRepository.findById(
+ Long.parseLong(selectedDomainId.getSelectedKey(state)));
+
+ locales = new ArrayList<>();
+ locales.addAll(selectedDomain.getTitle().getAvailableLocales());
+ locales.sort((l1, l2) -> {
+ return l1.toString().compareTo(l2.toString());
+ });
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+
+ @Override
+ public boolean nextRow() {
+ index++;
+ return index < locales.size();
+ }
+
+ @Override
+ public Object getElementAt(final int columnIndex) {
+ final Locale locale = locales.get(index);
+
+ switch (columnIndex) {
+ case COL_LOCALE:
+ return locale.toString();
+ case COL_VALUE:
+ return selectedDomain.getTitle().getValue(locale);
+ case COL_DEL:
+ return new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.title.del",
+ ADMIN_BUNDLE
+ ));
+ default:
+ throw new IllegalArgumentException(
+ "Not a valid column index");
+ }
+ }
+
+ @Override
+ public Object getKeyAt(final int columnIndex) {
+ return locales.get(index);
+ }
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainsTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainsTable.java
index 42310a7b2..cdcf8a1cd 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainsTable.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainsTable.java
@@ -18,6 +18,7 @@
*/
package com.arsdigita.ui.admin.categories;
+import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Label;
@@ -35,7 +36,9 @@ import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.table.TableModelBuilder;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.util.LockableImpl;
+
import java.util.List;
+
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.util.Strings;
@@ -46,6 +49,8 @@ import org.libreccm.configuration.ConfigurationConstants;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.l10n.LocalizedString;
+import javax.swing.text.html.StyleSheet;
+
import static com.arsdigita.ui.admin.AdminUiConstants.*;
/**
@@ -55,55 +60,74 @@ import static com.arsdigita.ui.admin.AdminUiConstants.*;
public class DomainsTable extends Table {
private final static Logger LOGGER = LogManager.getLogger(
- DomainsTable.class);
+ DomainsTable.class);
private static final int COL_DOMAIN_KEY = 0;
private static final int COL_DOMAIN_URI = 1;
private static final int COL_DOMAIN_TITLE = 2;
private static final int COL_DOMAIN_DEL = 3;
+ private final CategoriesTab categoriesTab;
private final ParameterSingleSelectionModel selectedDomainId;
-
private final TextField domainsFilter;
public DomainsTable(
- final ParameterSingleSelectionModel selectedDomainId,
- final TextField domainsFilter) {
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedDomainId,
+ final TextField domainsFilter) {
super();
setIdAttr("domainsTable");
+ this.categoriesTab = categoriesTab;
this.selectedDomainId = selectedDomainId;
this.domainsFilter = domainsFilter;
setEmptyView(new Label(new GlobalizedMessage(
- "ui.admin.categories.domains.none",
- ADMIN_BUNDLE)));
+ "ui.admin.categories.domains.none",
+ ADMIN_BUNDLE)));
final TableColumnModel columnModel = getColumnModel();
columnModel.add(new TableColumn(
- COL_DOMAIN_KEY,
- new Label(new GlobalizedMessage(
- "ui,admin.categories.domains.table.col_key",
- ADMIN_BUNDLE))));
+ COL_DOMAIN_KEY,
+ new Label(new GlobalizedMessage(
+ "ui,admin.categories.domains.table.col_key",
+ ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
- COL_DOMAIN_URI,
- new Label(new GlobalizedMessage(
- "ui,admin.categories.domains.table.col_uri",
- ADMIN_BUNDLE))));
+ COL_DOMAIN_URI,
+ new Label(new GlobalizedMessage(
+ "ui,admin.categories.domains.table.col_uri",
+ ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
- COL_DOMAIN_TITLE,
- new Label(new GlobalizedMessage(
- "ui,admin.categories.domains.table.col_title",
- ADMIN_BUNDLE))));
+ COL_DOMAIN_TITLE,
+ new Label(new GlobalizedMessage(
+ "ui,admin.categories.domains.table.col_title",
+ ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
- COL_DOMAIN_DEL,
- new Label(new GlobalizedMessage(
- "ui,admin.categories.domains.table.col_del",
- ADMIN_BUNDLE))));
+ COL_DOMAIN_DEL,
+ new Label(new GlobalizedMessage(
+ "ui,admin.categories.domains.table.col_del",
+ ADMIN_BUNDLE))));
+
+ columnModel.get(COL_DOMAIN_KEY).setCellRenderer(
+ new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ return new ControlLink((String) value);
+ }
+
+ });
columnModel.get(COL_DOMAIN_TITLE).setCellRenderer(
- new TableCellRenderer() {
+ new TableCellRenderer() {
+
@Override
public Component getComponent(final Table table,
final PageState state,
@@ -114,14 +138,16 @@ public class DomainsTable extends Table {
final int column) {
final LocalizedString title = (LocalizedString) value;
final GlobalizationHelper globalizationHelper = CdiUtil.
- createCdiUtil().findBean(GlobalizationHelper.class);
+ createCdiUtil().findBean(GlobalizationHelper.class);
return new Text(title.getValue(globalizationHelper.
- getNegotiatedLocale()));
+ getNegotiatedLocale()));
}
+
});
columnModel.get(COL_DOMAIN_DEL).setCellRenderer(
- new TableCellRenderer() {
+ new TableCellRenderer() {
+
@Override
public Component getComponent(final Table table,
final PageState state,
@@ -135,30 +161,43 @@ public class DomainsTable extends Table {
} else {
final ControlLink link = new ControlLink((Component) value);
link.setConfirmation(new GlobalizedMessage(
- "ui.admin.categories.domains.table.del_confirm",
- ADMIN_BUNDLE));
+ "ui.admin.categories.domains.table.del_confirm",
+ ADMIN_BUNDLE));
return link;
}
}
+
});
addTableActionListener(new TableActionListener() {
+
@Override
public void cellSelected(final TableActionEvent event) {
- //ToDo
+ final PageState state = event.getPageState();
+
+ switch (event.getColumn()) {
+ case COL_DOMAIN_KEY:
+ selectedDomainId.setSelectedKey(state,
+ event.getRowKey());
+ categoriesTab.showDomainDetails(state);
+ break;
+ case COL_DOMAIN_DEL:
+ break;
+ }
}
@Override
public void headSelected(final TableActionEvent event) {
//Nothing
}
+
});
setModelBuilder(new DomainsTableModelBuilder());
}
private class DomainsTableModelBuilder extends LockableImpl
- implements TableModelBuilder {
+ implements TableModelBuilder {
@Override
public TableModel makeModel(final Table table,
@@ -180,7 +219,7 @@ public class DomainsTable extends Table {
final String filterTerm = (String) domainsFilter.getValue(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final DomainRepository domainRepository = cdiUtil.findBean(
- DomainRepository.class);
+ DomainRepository.class);
if (Strings.isBlank(filterTerm)) {
domains = domainRepository.findAll("Domain.withOwners");
LOGGER.debug("Found {} domains in the database.",
@@ -188,7 +227,7 @@ public class DomainsTable extends Table {
} else {
domains = domainRepository.search(filterTerm);
LOGGER.debug("Found {} domain which match the "
- + "filter \"{}\".",
+ + "filter \"{}\".",
domains.size(),
filterTerm);
}
@@ -221,26 +260,26 @@ public class DomainsTable extends Table {
case COL_DOMAIN_DEL:
if (isDeleteable(domain)) {
return new Label(new GlobalizedMessage(
- "ui.admin.categories.domains.table.del",
- ADMIN_BUNDLE));
+ "ui.admin.categories.domains.table.del",
+ ADMIN_BUNDLE));
} else {
return null;
}
default:
throw new IllegalArgumentException(
- "Not a valid column index");
+ "Not a valid column index");
}
}
@Override
public Object getKeyAt(final int columnIndex) {
- return domains.get(index).getUuid();
+ return domains.get(index).getObjectId();
}
private boolean isDeleteable(final Domain domain) {
if (ConfigurationConstants.REGISTRY_DOMAIN.equals(domain.
- getDomainKey())) {
+ getDomainKey())) {
return false;
}
@@ -250,6 +289,7 @@ public class DomainsTable extends Table {
return true;
}
+
}
}
diff --git a/ccm-core/src/main/java/org/libreccm/categorization/DomainRepository.java b/ccm-core/src/main/java/org/libreccm/categorization/DomainRepository.java
index 9f0dbcefc..6a9ba1331 100644
--- a/ccm-core/src/main/java/org/libreccm/categorization/DomainRepository.java
+++ b/ccm-core/src/main/java/org/libreccm/categorization/DomainRepository.java
@@ -31,6 +31,7 @@ import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
+import javax.transaction.Transactional;
/**
* A repository for executing CRUD operations on {@link Domain} objects.
@@ -59,6 +60,7 @@ public class DomainRepository extends AbstractEntityRepository {
}
@Override
+ @Transactional(Transactional.TxType.REQUIRED)
public List findAll() {
if (getEntityClass().isAnnotationPresent(DefaultEntityGraph.class)) {
return findAll(getEntityClass().getAnnotation(
@@ -71,6 +73,7 @@ public class DomainRepository extends AbstractEntityRepository {
}
@Override
+ @Transactional(Transactional.TxType.REQUIRED)
public List findAll(final String entityGraphName) {
@SuppressWarnings("unchecked")
final EntityGraph entityGraph = (EntityGraph) entityManager.
@@ -79,6 +82,7 @@ public class DomainRepository extends AbstractEntityRepository {
}
@Override
+ @Transactional(Transactional.TxType.REQUIRED)
public List findAll(final EntityGraph entityGraph) {
final TypedQuery query = getEntityManager()
.createNamedQuery("Domain.findAll", Domain.class);
diff --git a/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java b/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java
index 9516ba600..7e9c1176f 100644
--- a/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java
+++ b/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java
@@ -170,6 +170,7 @@ public abstract class AbstractEntityRepository {
* @return The entity identified by the provided ID of {@code null} if there
* is no such entity.
*/
+ @Transactional(Transactional.TxType.REQUIRED)
public E findById(final K entityId) {
if (getEntityClass().isAnnotationPresent(DefaultEntityGraph.class)) {
return findById(entityId, getEntityClass().getAnnotation(
@@ -179,6 +180,7 @@ public abstract class AbstractEntityRepository {
}
}
+ @Transactional(Transactional.TxType.REQUIRED)
public E findById(final K entityId, final String entityGraphName) {
@SuppressWarnings("unchecked")
final EntityGraph entityGraph = (EntityGraph) entityManager.
@@ -186,6 +188,7 @@ public abstract class AbstractEntityRepository {
return findById(entityId, entityGraph);
}
+ @Transactional(Transactional.TxType.REQUIRED)
public E findById(final K entityId, final EntityGraph entityGraph) {
final Map hints = new HashMap<>();
hints.put(FETCH_GRAPH_HINT_KEY, entityGraph);
@@ -199,12 +202,14 @@ public abstract class AbstractEntityRepository {
* @return The list of entities in the database which are of the type
* provided by {@link #getEntityClass()}.
*/
+ @Transactional(Transactional.TxType.REQUIRED)
public List findAll() {
// We are using the Critiera API here because otherwise we can't
// pass the type of the entity dynmacially.
return executeCriteriaQuery(createCriteriaQuery());
}
+ @Transactional(Transactional.TxType.REQUIRED)
public List findAll(final String entityGraphName) {
@SuppressWarnings("unchecked")
final EntityGraph entityGraph = (EntityGraph) entityManager
@@ -213,6 +218,7 @@ public abstract class AbstractEntityRepository {
return findAll(entityGraph);
}
+ @Transactional(Transactional.TxType.REQUIRED)
public List findAll(final EntityGraph entityGraph) {
// We are using the Critiera API here because otherwise we can't
// pass the type of the entity dynmacially.
diff --git a/ccm-core/src/main/java/org/libreccm/l10n/LocalizedString.java b/ccm-core/src/main/java/org/libreccm/l10n/LocalizedString.java
index be8405ce6..1da900a57 100644
--- a/ccm-core/src/main/java/org/libreccm/l10n/LocalizedString.java
+++ b/ccm-core/src/main/java/org/libreccm/l10n/LocalizedString.java
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
@@ -58,6 +59,7 @@ public class LocalizedString implements Serializable {
@ElementCollection(fetch = FetchType.EAGER)
@MapKeyColumn(name = "LOCALE")
@Column(name = "LOCALIZED_VALUE")
+ @Basic
@Lob
@XmlElementWrapper(name = "values", namespace = L10N_XML_NS)
@XmlElement(name = "value", namespace = L10N_XML_NS)
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
index 53ff818f0..385910262 100644
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
@@ -361,3 +361,39 @@ ui.admin.categories.domain_form.fields.released=Released
ui.admin.categories.domain_form.errors.domain_key_blank=The key of a domain can't be blank.
ui.admin.categories.domain_form.errors.version_blank=The version of domain can't be blank.
ui.admin.categories.domain_form.fields.root_category_name=Name of root category
+ui.admin.categories.domain_details.back=Back to list of domains
+ui.admin.categories.domain_details.basic_properties.edit=Edit basic properties
+ui.admin.categories.domain_details.basic_properties=Basic properties
+ui.admin.categories.domain_details.domain_title=Localized title of domain
+ui.admin.categories.domain_details.description=Description of domain
+ui.admin.categories.domain_details.mappings=Mappings
+ui.admin.categories.domain.property_sheet.domain_key=Key
+ui.admin.categories.domain.property_sheet.uri=URI
+ui.admin.categories.domain.property_sheet.version=Version
+ui.admin.categories.domain.property_sheet.released=Released
+ui.admin.categories.domain_details.title.none=No localized titles for this domain.
+ui.admin.categories.domain_details.title.col_lang=Language
+ui.admin.categories.domain_details.title.col_value=Localised title
+ui.admin.categories.domain_details.title.col_del=Delete
+ui.admin.categories.domain_details.title.del_confirm=Are you sure to delete this localised title?
+ui.admin.categories.domain_details.title.del=Delete
+ui.admin.categories.domain_details.domain_title.add.label=Add domain title for
+ui.admin.categories.domain_details.domain_title.add.submit=Add
+ui.admin.categories.domain.title.edit_for_lang=Edit title of domain {0} for language {1}
+ui.admin.categories.domain.title.add_for_lang=Add title for lanuage {1} to domain {0}
+ui.admin.categories.domain.title.error.not_blank=The localised title of a domain can't be empty.
+ui.admin.categories.domain.title.label=Localized title
+ui.admin.categories.domain.title.edit.back=Back to domain
+ui.admin.categories.domain_details.description.none=No description for this domain.
+ui.admin.categories.domain_details.description.col_lang=Language
+ui.admin.categories.domain_details.description.col_value=Description
+ui.admin.categories.domain_details.description.col_del=Delete
+ui.admin.categories.domain_details.description.del_confirm=Are you sure to delete this description?
+ui.admin.categories.domain_details.description.del=Delete
+ui.admin.categories.domain.description.edit.back=Back to domain
+ui.admin.categories.domain.description.edit_for_lang=Edit description of domain {0} for language {1}
+ui.admin.categories.domain.description.add_for_lang=Add description of domain {0} for language {1}
+ui.admin.categories.domain.description.label=Description
+ui.admin.categories.domain.description.error.not_blank=The description of a domain can't be blank.
+ui.admin.categories.domain_details.domain_desc.add.label=Add description for language
+ui.admin.categories.domain_details.domain_desc.add.submit=Add
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
index 16eb8cb7e..006184c8b 100644
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
@@ -364,3 +364,39 @@ ui.admin.categories.domain_form.fields.released=Freigegeben
ui.admin.categories.domain_form.errors.domain_key_blank=Der Key einer Domain darf nicht leer sein.
ui.admin.categories.domain_form.errors.version_blank=Die Version einer Domain darf nicht leer sein.
ui.admin.categories.domain_form.fields.root_category_name=Name der Wurzelkategorie
+ui.admin.categories.domain_details.back=Zur\u00fcck zur List der Domains
+ui.admin.categories.domain_details.basic_properties.edit=Basiseigenschaften bearbeiten
+ui.admin.categories.domain_details.basic_properties=Basiseigenschaften
+ui.admin.categories.domain_details.domain_title=Lokalisierter Titel der Domain
+ui.admin.categories.domain_details.description=Beschreibung der Domain
+ui.admin.categories.domain_details.mappings=Mappings
+ui.admin.categories.domain.property_sheet.domain_key=Key
+ui.admin.categories.domain.property_sheet.uri=URI
+ui.admin.categories.domain.property_sheet.version=Version
+ui.admin.categories.domain.property_sheet.released=Freigegeben
+ui.admin.categories.domain_details.title.none=Keine lokalisierten Titel f\u00fcr diese Domain.
+ui.admin.categories.domain_details.title.col_lang=Sprache
+ui.admin.categories.domain_details.title.col_value=Lokalisierter Titel
+ui.admin.categories.domain_details.title.col_del=L\u00f6schen
+ui.admin.categories.domain_details.title.del_confirm=Sind Sie sicher, dass Sie diesen lokalisierten Titel l\u00f6schen wollen?
+ui.admin.categories.domain_details.title.del=L\u00f6schen
+ui.admin.categories.domain_details.domain_title.add.label=Titel f\u00fcr
+ui.admin.categories.domain_details.domain_title.add.submit=hinzuf\u00fcgen
+ui.admin.categories.domain.title.edit_for_lang=Titel der Domain {0} f\u00fcr Sprache {1} bearbeiten
+ui.admin.categories.domain.title.add_for_lang=Titel f\u00fcr Sprache {1} zur Domain {0} hinzuf\u00fcgen
+ui.admin.categories.domain.title.error.not_blank=Der lokalisierte Titel einer Domain darf nicht leer sein.
+ui.admin.categories.domain.title.label=Lokalisierter Titel
+ui.admin.categories.domain.title.edit.back=Zur\u00fcck zur Domain
+ui.admin.categories.domain_details.description.none=Keine Beschreibung f\u00fcr diese Domain.
+ui.admin.categories.domain_details.description.col_lang=Sprache
+ui.admin.categories.domain_details.description.col_value=Beschreibung
+ui.admin.categories.domain_details.description.col_del=L\u00f6schen
+ui.admin.categories.domain_details.description.del_confirm=Sind Sie sicher, dass Sie diese Beschreibung l\u00f6schen wollen?
+ui.admin.categories.domain_details.description.del=L\u00f6schen
+ui.admin.categories.domain.description.edit.back=Zur\u00fcck zur Domain
+ui.admin.categories.domain.description.edit_for_lang=Beschreibung der Domain {0} f\u00fcr {1} bearbeiten
+ui.admin.categories.domain.description.add_for_lang=Beschreibung der Domain {0} f\u00fcr Sprache {1} hinzuf\u00fcgen
+ui.admin.categories.domain.description.label=Beschreibung
+ui.admin.categories.domain.description.error.not_blank=Die Beschreibung einer Domain darf nicht leer sein.
+ui.admin.categories.domain_details.domain_desc.add.label=Beschreibung f\u00fcr Sprache
+ui.admin.categories.domain_details.domain_desc.add.submit=hinzuf\u00fcgen
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
index 19479f5de..8f8aee0d0 100755
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
@@ -337,3 +337,39 @@ ui.admin.categories.domain_form.fields.released=Released
ui.admin.categories.domain_form.errors.domain_key_blank=The key of a domain can't be blank.
ui.admin.categories.domain_form.errors.version_blank=The version of domain can't be blank.
ui.admin.categories.domain_form.fields.root_category_name=Name of root category
+ui.admin.categories.domain_details.back=Back to list of domains
+ui.admin.categories.domain_details.basic_properties.edit=Edit basic properties
+ui.admin.categories.domain_details.basic_properties=Basic properties
+ui.admin.categories.domain_details.domain_title=Localized title of domain
+ui.admin.categories.domain_details.description=Description of domain
+ui.admin.categories.domain_details.mappings=Mappings
+ui.admin.categories.domain.property_sheet.domain_key=Key
+ui.admin.categories.domain.property_sheet.uri=URI
+ui.admin.categories.domain.property_sheet.version=Version
+ui.admin.categories.domain.property_sheet.released=Released
+ui.admin.categories.domain_details.title.none=No localized titles for this domain.
+ui.admin.categories.domain_details.title.col_lang=Language
+ui.admin.categories.domain_details.title.col_value=Localised title
+ui.admin.categories.domain_details.title.col_del=Delete
+ui.admin.categories.domain_details.title.del_confirm=Are you sure to delete this localised title?
+ui.admin.categories.domain_details.title.del=Delete
+ui.admin.categories.domain_details.domain_title.add.label=Add domain title for
+ui.admin.categories.domain_details.domain_title.add.submit=Add
+ui.admin.categories.domain.title.edit_for_lang=Edit title of domain {0} for language {1}
+ui.admin.categories.domain.title.add_for_lang=Add title for lanuage {1} to domain {0}
+ui.admin.categories.domain.title.error.not_blank=The localised title of a domain can't be empty.
+ui.admin.categories.domain.title.label=Localized title
+ui.admin.categories.domain.title.edit.back=Back to domain
+ui.admin.categories.domain_details.description.none=No description for this domain.
+ui.admin.categories.domain_details.description.col_lang=Language
+ui.admin.categories.domain_details.description.col_value=Description
+ui.admin.categories.domain_details.description.col_del=Delete
+ui.admin.categories.domain_details.description.del_confirm=Are you sure to delete this description?
+ui.admin.categories.domain_details.description.del=Delete
+ui.admin.categories.domain.description.edit.back=Back to domain
+ui.admin.categories.domain.description.edit_for_lang=Edit description of domain {0} for language {1}
+ui.admin.categories.domain.description.add_for_lang=Add description of domain {0} for language {1}
+ui.admin.categories.domain.description.label=Description
+ui.admin.categories.domain.description.error.not_blank=The description of a domain can't be blank.
+ui.admin.categories.domain_details.domain_desc.add.label=Add description for language
+ui.admin.categories.domain_details.domain_desc.add.submit=Add
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
index 22049db9b..cd40f34a8 100755
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
@@ -328,3 +328,39 @@ ui.admin.categories.domain_form.fields.released=Released
ui.admin.categories.domain_form.errors.domain_key_blank=The key of a domain can't be blank.
ui.admin.categories.domain_form.errors.version_blank=The version of domain can't be blank.
ui.admin.categories.domain_form.fields.root_category_name=Name of root category
+ui.admin.categories.domain_details.back=Back to list of domains
+ui.admin.categories.domain_details.basic_properties.edit=Edit basic properties
+ui.admin.categories.domain_details.basic_properties=Basic properties
+ui.admin.categories.domain_details.domain_title=Localized title of domain
+ui.admin.categories.domain_details.description=Description of domain
+ui.admin.categories.domain_details.mappings=Mappings
+ui.admin.categories.domain.property_sheet.domain_key=Key
+ui.admin.categories.domain.property_sheet.uri=URI
+ui.admin.categories.domain.property_sheet.version=Version
+ui.admin.categories.domain.property_sheet.released=Released
+ui.admin.categories.domain_details.title.none=No localized titles for this domain.
+ui.admin.categories.domain_details.title.col_lang=Language
+ui.admin.categories.domain_details.title.col_value=Localised title
+ui.admin.categories.domain_details.title.col_del=Delete
+ui.admin.categories.domain_details.title.del_confirm=Are you sure to delete this localised title?
+ui.admin.categories.domain_details.title.del=Delete
+ui.admin.categories.domain_details.domain_title.add.label=Add domain title for
+ui.admin.categories.domain_details.domain_title.add.submit=Add
+ui.admin.categories.domain.title.edit_for_lang=Edit title of domain {0} for language {1}
+ui.admin.categories.domain.title.add_for_lang=Add title for lanuage {1} to domain {0}
+ui.admin.categories.domain.title.error.not_blank=The localised title of a domain can't be empty.
+ui.admin.categories.domain.title.label=Localized title
+ui.admin.categories.domain.title.edit.back=Back to domain
+ui.admin.categories.domain_details.description.none=No description for this domain.
+ui.admin.categories.domain_details.description.col_lang=Language
+ui.admin.categories.domain_details.description.col_value=Description
+ui.admin.categories.domain_details.description.col_del=Delete
+ui.admin.categories.domain_details.description.del_confirm=Are you sure to delete this description?
+ui.admin.categories.domain_details.description.del=Delete
+ui.admin.categories.domain.description.edit.back=Back to domain
+ui.admin.categories.domain.description.edit_for_lang=Edit description of domain {0} for language {1}
+ui.admin.categories.domain.description.add_for_lang=Add description of domain {0} for language {1}
+ui.admin.categories.domain.description.label=Description
+ui.admin.categories.domain.description.error.not_blank=The description of a domain can't be blank.
+ui.admin.categories.domain_details.domain_desc.add.label=Add description for language
+ui.admin.categories.domain_details.domain_desc.add.submit=Add