From 133f39e2333a02b421bc83462cabf543fab201c3 Mon Sep 17 00:00:00 2001 From: jensp Date: Wed, 6 Dec 2017 15:25:58 +0000 Subject: [PATCH] CCM NG: Admin UI for Pages Vaadin variant git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5156 8810af33-2d31-482b-a856-94f89814c4df --- .../cms/ui/contentcenter/PagesForm.java | 19 +- .../ui/contentcenter/PagesPaneController.java | 4 +- .../main/java/org/librecms/ui/CmsView.java | 1 + .../org/librecms/ui/CmsViewController.java | 13 + .../ui/PageModelSelectDataProvider.java | 81 ++++++ .../ui/PagesCategoryTreeDataProvider.java | 127 +++++++++ .../java/org/librecms/ui/PagesController.java | 165 +++++++++++ .../java/org/librecms/ui/PagesDetails.java | 260 ++++++++++++++++++ .../java/org/librecms/ui/PagesEditor.java | 184 +++++++++++++ .../PagesEditorDomainSelectDataProvider.java | 100 +++++++ .../ui/PagesEditorSiteSelectDataProvider.java | 100 +++++++ .../librecms/ui/PagesGridDataProvider.java | 58 ++++ .../main/java/org/librecms/ui/PagesTab.java | 200 ++++++++++++++ .../org/librecms/CmsResources.properties | 7 + .../org/librecms/CmsResources_de.properties | 7 + .../org/librecms/CmsResources_fr.properties | 7 + 16 files changed, 1327 insertions(+), 6 deletions(-) create mode 100644 ccm-cms/src/main/java/org/librecms/ui/PageModelSelectDataProvider.java create mode 100644 ccm-cms/src/main/java/org/librecms/ui/PagesCategoryTreeDataProvider.java create mode 100644 ccm-cms/src/main/java/org/librecms/ui/PagesController.java create mode 100644 ccm-cms/src/main/java/org/librecms/ui/PagesDetails.java create mode 100644 ccm-cms/src/main/java/org/librecms/ui/PagesEditor.java create mode 100644 ccm-cms/src/main/java/org/librecms/ui/PagesEditorDomainSelectDataProvider.java create mode 100644 ccm-cms/src/main/java/org/librecms/ui/PagesEditorSiteSelectDataProvider.java create mode 100644 ccm-cms/src/main/java/org/librecms/ui/PagesGridDataProvider.java create mode 100644 ccm-cms/src/main/java/org/librecms/ui/PagesTab.java diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/PagesForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/PagesForm.java index 0528db3f0..e35335fef 100644 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/PagesForm.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/PagesForm.java @@ -131,7 +131,7 @@ class PagesForm extends Form { target.addOption(new Option(Long.toString(site.getObjectId()), label)); } - + if (selectedPages.getSelectedKey(event.getPageState()) != null) { target.setDisabled(); } @@ -153,7 +153,7 @@ class PagesForm extends Form { target.addOption(new Option(Long.toString(domain.getObjectId()), new Text(domain.getDomainKey()))); } - + if (selectedPages.getSelectedKey(event.getPageState()) != null) { target.setDisabled(); } @@ -243,7 +243,20 @@ class PagesForm extends Form { final FormData data = event.getFormData(); - final String primaryUrl = data.getString(PRIMARY_URL_FIELD); + final String primaryUrl; + if (data.getString(PRIMARY_URL_FIELD).startsWith("/") + && data.getString(PRIMARY_URL_FIELD).endsWith("/")) { + primaryUrl = data.getString(PRIMARY_URL_FIELD); + } else if(data.getString(PRIMARY_URL_FIELD).startsWith("/")) { + primaryUrl = String.format("%s/", + data.getString(PRIMARY_URL_FIELD)); + } else if(data.getString(PRIMARY_URL_FIELD).endsWith("/")) { + primaryUrl = String.format("/%s", + data.getString(PRIMARY_URL_FIELD)); + } else { + primaryUrl = String.format("/%s/", + data.getString(PRIMARY_URL_FIELD)); + } final String selectedSiteId = data.getString(SITE_SELECT); final String selectedDomainId = data.getString( CATEGORY_DOMAIN_SELECT); diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/PagesPaneController.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/PagesPaneController.java index f39c37c9e..0bb6a530d 100644 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/PagesPaneController.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/PagesPaneController.java @@ -32,8 +32,6 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.transaction.Transactional; -import static org.primefaces.component.calendar.Calendar.PropertyKeys.*; - /** * * @author Jens Pelzetter @@ -90,7 +88,7 @@ class PagesPaneController { pagesId))); pages.setPrimaryUrl(primaryUrl); - + pagesRepo.save(pages); } diff --git a/ccm-cms/src/main/java/org/librecms/ui/CmsView.java b/ccm-cms/src/main/java/org/librecms/ui/CmsView.java index 1dd49b246..0a14330df 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/CmsView.java +++ b/ccm-cms/src/main/java/org/librecms/ui/CmsView.java @@ -50,6 +50,7 @@ class CmsView extends CustomComponent implements View { final ContentSectionsGrid sectionsGrid = new ContentSectionsGrid(controller); sectionsGrid.setWidth("100%"); tabSheet.addTab(sectionsGrid, "Content Section"); + tabSheet.addTab(new PagesTab(controller), "Pages"); tabSheet.addTab(new Label("Placeholder"), "Search"); tabSheet.addTab(new Label("Placeholder"), "My tasks"); diff --git a/ccm-cms/src/main/java/org/librecms/ui/CmsViewController.java b/ccm-cms/src/main/java/org/librecms/ui/CmsViewController.java index 6c89ce0cf..be252c5cd 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/CmsViewController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/CmsViewController.java @@ -22,6 +22,10 @@ import com.vaadin.cdi.ViewScoped; import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.security.PermissionChecker; import org.libreccm.security.PermissionManager; +import org.librecms.pages.PageManager; +import org.librecms.pages.PageRepository; +import org.librecms.pages.PagesManager; +import org.librecms.pages.PagesRepository; import javax.inject.Inject; @@ -35,6 +39,10 @@ class CmsViewController { @Inject private GlobalizationHelper globalizationHelper; + @Inject + private PagesController pagesController; + + @Inject private PermissionManager permissionManager; @@ -48,6 +56,11 @@ class CmsViewController { return globalizationHelper; } + + protected PagesController getPagesController() { + return pagesController; + } + protected PermissionManager getPermissionManager() { return permissionManager; } diff --git a/ccm-cms/src/main/java/org/librecms/ui/PageModelSelectDataProvider.java b/ccm-cms/src/main/java/org/librecms/ui/PageModelSelectDataProvider.java new file mode 100644 index 000000000..b2b675f40 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PageModelSelectDataProvider.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import com.vaadin.cdi.ViewScoped; +import com.vaadin.data.provider.AbstractBackEndDataProvider; +import com.vaadin.data.provider.Query; +import org.libreccm.pagemodel.PageModel; + +import java.util.stream.Stream; + +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +/** + * + * @author Jens Pelzetter + */ +@ViewScoped +class PageModelSelectDataProvider + extends AbstractBackEndDataProvider { + + private static final long serialVersionUID = 3102935928982631262L; + + @Inject + private EntityManager entityManager; + + @Override + protected Stream fetchFromBackEnd( + final Query query) { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(PageModel.class); + final Root from = criteriaQuery.from(PageModel.class); + criteriaQuery.select(from); + + return entityManager + .createQuery(criteriaQuery) + .setFirstResult(query.getOffset()) + .setMaxResults(query.getLimit()) + .getResultList() + .stream(); + } + + @Override + protected int sizeInBackEnd(final Query query) { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(Long.class); + final Root from = criteriaQuery.from(PageModel.class); + + criteriaQuery.select(builder.count(from)); + + return entityManager + .createQuery(criteriaQuery) + .getSingleResult() + .intValue(); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesCategoryTreeDataProvider.java b/ccm-cms/src/main/java/org/librecms/ui/PagesCategoryTreeDataProvider.java new file mode 100644 index 000000000..455bd5452 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesCategoryTreeDataProvider.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import com.vaadin.cdi.ViewScoped; +import com.vaadin.data.provider.AbstractBackEndHierarchicalDataProvider; +import com.vaadin.data.provider.HierarchicalQuery; +import org.libreccm.categorization.Category; +import org.libreccm.categorization.Domain; + +import java.util.stream.Stream; + +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@ViewScoped +class PagesCategoryTreeDataProvider + extends AbstractBackEndHierarchicalDataProvider { + + private static final long serialVersionUID = -4953505403671944088L; + + + @Inject + private EntityManager entityManager; + + + private Domain domain; + + protected Domain getDomain() { + return domain; + } + + protected void setDomain(final Domain domain) { + this.domain = domain; + } + + @Transactional(Transactional.TxType.REQUIRED) + @Override + protected Stream fetchChildrenFromBackEnd( + final HierarchicalQuery query) { + + if (query.getParentOptional().isPresent()) { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(Category.class); + + final Root from = criteriaQuery.from(Category.class); + criteriaQuery.where(builder.equal(from.get("parentCategory"), + query.getParentOptional().get())); + final TypedQuery entityQuery = entityManager + .createQuery(criteriaQuery); + return entityQuery + .setFirstResult(query.getOffset()) + .setMaxResults(query.getLimit()) + .getResultList() + .stream(); + } else { + + return Stream.of(domain.getRoot()); + } + } + + @Transactional(Transactional.TxType.REQUIRED) + @Override + public int getChildCount( + final HierarchicalQuery query) { + + if (query.getParentOptional().isPresent()) { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(Long.class); + + final Root from = criteriaQuery.from(Category.class); + criteriaQuery.select(builder.count(from)); + criteriaQuery.where(builder.equal(from.get("parentCategory"), + query.getParentOptional().get())); + final TypedQuery entityQuery = entityManager + .createQuery(criteriaQuery); + return entityQuery.getSingleResult().intValue(); + } else { + return 1; + } + } + + @Transactional(Transactional.TxType.REQUIRED) + @Override + public boolean hasChildren(final Category item) { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(Long.class); + + final Root from = criteriaQuery.from(Category.class); + criteriaQuery.select(builder.count(from)); + criteriaQuery.where(builder.equal(from.get("parentCategory"), item)); + final TypedQuery entityQuery = entityManager + .createQuery(criteriaQuery); + return entityQuery.getSingleResult().intValue() > 0; + } +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesController.java b/ccm-cms/src/main/java/org/librecms/ui/PagesController.java new file mode 100644 index 000000000..790d93dbc --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesController.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import com.vaadin.cdi.ViewScoped; +import org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryRepository; +import org.libreccm.categorization.Domain; +import org.libreccm.categorization.DomainRepository; +import org.libreccm.sites.Site; +import org.libreccm.sites.SiteRepository; +import org.librecms.pages.Page; +import org.librecms.pages.PageManager; +import org.librecms.pages.PageRepository; +import org.librecms.pages.Pages; +import org.librecms.pages.PagesManager; +import org.librecms.pages.PagesRepository; + +import java.util.Objects; +import java.util.Optional; + +import javax.inject.Inject; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@ViewScoped +class PagesController { + + @Inject + private CategoryRepository categoryRepo; + + @Inject + private DomainRepository domainRepo; + + @Inject + private PageModelSelectDataProvider pageModelSelectDataProvider; + + @Inject + private PageManager pageManager; + + @Inject + private PageRepository pageRepo; + + @Inject + private PagesCategoryTreeDataProvider pagesCategoryTreeDataProvider; + + @Inject + private PagesEditorDomainSelectDataProvider pagesEditorDomainSelectDataProvider; + + @Inject + private PagesEditorSiteSelectDataProvider pagesEditorSiteSelectDataProvider; + + @Inject + private PagesGridDataProvider pagesGridDataProvider; + + @Inject + private PagesManager pagesManager; + + @Inject + private PagesRepository pagesRepo; + + @Inject + private SiteRepository siteRepo; + + protected PageModelSelectDataProvider getPageModelSelectDataProvider() { + return pageModelSelectDataProvider; + } + + protected PageManager getPageManager() { + return pageManager; + } + + protected PageRepository getPageRepo() { + return pageRepo; + } + + protected PagesCategoryTreeDataProvider getPagesCategoryTreeDataProvider() { + return pagesCategoryTreeDataProvider; + } + + protected PagesEditorDomainSelectDataProvider getPagesEditorDomainSelectDataProvider() { + return pagesEditorDomainSelectDataProvider; + } + + protected PagesEditorSiteSelectDataProvider getPagesEditorSiteSelectDataProvider() { + return pagesEditorSiteSelectDataProvider; + } + + protected PagesGridDataProvider getPagesGridDataProvider() { + return pagesGridDataProvider; + } + + protected PagesManager getPagesManager() { + return pagesManager; + } + + protected PagesRepository getPagesRepo() { + return pagesRepo; + } + + @Transactional(Transactional.TxType.REQUIRED) + protected Optional findPage(final Category category) { + + Objects.requireNonNull(category); + + final Category theCategory = categoryRepo + .findById(category.getObjectId()) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No Category with ID %d in the database.", + category.getObjectId()))); + + return pageRepo.findPageForCategory(theCategory); + } + + @Transactional(Transactional.TxType.REQUIRED) + protected Pages createPages(final String name, + final Site site, + final Domain domain) { + + Objects.requireNonNull(name); + Objects.requireNonNull(site); + Objects.requireNonNull(domain); + + if (name.isEmpty() + || name.matches("\\s*")) { + + throw new IllegalArgumentException( + "The name of a Pages instance can't be empty."); + } + + final Site forSite = siteRepo + .findById(site.getObjectId()) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No Site with ID %d in the database.", + site.getObjectId()))); + + final Domain withDomain = domainRepo + .findById(domain.getObjectId()) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No Domain with ID %d in the database.", + domain.getObjectId()))); + + return pagesManager.createPages(name, forSite, withDomain); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesDetails.java b/ccm-cms/src/main/java/org/librecms/ui/PagesDetails.java new file mode 100644 index 000000000..02b153078 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesDetails.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import com.vaadin.event.selection.SingleSelectionEvent; +import com.vaadin.ui.Button; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.HorizontalSplitPanel; +import com.vaadin.ui.Panel; +import com.vaadin.ui.Tree; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; +import com.vaadin.ui.themes.ValoTheme; +import org.libreccm.categorization.Category; +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.l10n.LocalizedTextsUtil; +import org.libreccm.pagemodel.PageModel; +import org.librecms.CmsConstants; +import org.librecms.pages.Page; +import org.librecms.pages.PageManager; +import org.librecms.pages.Pages; + +import java.util.Objects; +import java.util.Optional; + +/** + * + * @author Jens Pelzetter + */ +class PagesDetails extends Window { + + private static final long serialVersionUID = 6306677625483502088L; + + private final CmsViewController controller; + private final Pages pages; + + private final GlobalizationHelper globalizationHelper; + private final LocalizedTextsUtil textsUtil; + + private Category selectedCategory; + + private final Panel panel; + private final ComboBox indexPageModelSelect; + private final ComboBox itemPageModelSelect; + + private final Button saveButton; + private final Button cancelButton; + + public PagesDetails(final Pages pages, final CmsViewController controller) { + + super(); + + globalizationHelper = controller.getGlobalizationHelper(); + textsUtil = globalizationHelper + .getLocalizedTextsUtil(CmsConstants.CMS_BUNDLE); + + this.pages = pages; + this.controller = controller; + + final PagesCategoryTreeDataProvider treeDataProvider = controller + .getPagesController() + .getPagesCategoryTreeDataProvider(); + treeDataProvider.setDomain(pages.getCategoryDomain()); + final Tree categoryTree = new Tree<>(); + categoryTree.setDataProvider(treeDataProvider); + categoryTree.addItemClickListener(this::categoryTreeClicked); + categoryTree.setItemCaptionGenerator(this::createCategoryTreeCaption); + + indexPageModelSelect = new ComboBox<>(textsUtil + .getText("cms.ui.pages.pagemodels.index_page")); + indexPageModelSelect.setDataProvider(controller + .getPagesController() + .getPageModelSelectDataProvider()); + indexPageModelSelect + .setItemCaptionGenerator(this::createPageModelCaption); + indexPageModelSelect.setTextInputAllowed(false); + indexPageModelSelect.setEmptySelectionAllowed(true); + indexPageModelSelect.setEmptySelectionCaption(textsUtil + .getText("cms.ui.pages.assigned_page_model.inherit")); + indexPageModelSelect + .setItemCaptionGenerator(this::createPageModelCaption); + + itemPageModelSelect = new ComboBox<>(textsUtil + .getText("cms.ui.pages.pagemodels.item_page")); + itemPageModelSelect.setDataProvider(controller + .getPagesController() + .getPageModelSelectDataProvider()); + itemPageModelSelect + .setItemCaptionGenerator(this::createPageModelCaption); + itemPageModelSelect.setTextInputAllowed(false); + itemPageModelSelect.setEmptySelectionAllowed(true); + itemPageModelSelect.setEmptySelectionCaption(textsUtil + .getText("cms.ui.pages.assigned_page_model.inherit")); + + indexPageModelSelect.addSelectionListener(this::selectionChange); + itemPageModelSelect.addSelectionListener(this::selectionChange); + + saveButton = new Button(textsUtil + .getText("cms.ui.pages.pagemodels.save")); + saveButton.addStyleName(ValoTheme.BUTTON_PRIMARY); + saveButton.addClickListener(this::saveButtonClicked); + + cancelButton = new Button(textsUtil + .getText("cms.ui.pages.pagemodels.cancel")); + cancelButton.addStyleName(ValoTheme.BUTTON_DANGER); + cancelButton.addClickListener(this::cancelButtonClicked); + + saveButton.setEnabled(false); + cancelButton.setEnabled(false); + + super.setCaption(textsUtil.getText("cms.ui.pages.title", + new String[]{pages.getPrimaryUrl()})); + + panel = new Panel(new VerticalLayout( + new FormLayout(indexPageModelSelect, + itemPageModelSelect), + new HorizontalLayout(saveButton, cancelButton))); + final HorizontalSplitPanel splitPanel = new HorizontalSplitPanel( + categoryTree, panel); + splitPanel.setSplitPosition(25.0f); + super.setContent(splitPanel); + init(); + } + + private void init() { + + selectedCategory = pages.getCategoryDomain().getRoot(); + updateWidgets(selectedCategory); + } + + private String createCategoryTreeCaption(final Category category) { + + if (category.getTitle().getValues().isEmpty()) { + return category.getName(); + } else { + + return globalizationHelper + .getValueFromLocalizedString(category.getTitle()); + } + } + + private String createPageModelCaption(final PageModel pageModel) { + + if (pageModel.getTitle().getValues().isEmpty()) { + return pageModel.getName(); + } else { + return globalizationHelper + .getValueFromLocalizedString(pageModel.getTitle()); + } + } + + private void categoryTreeClicked( + final Tree.ItemClick event) { + + final Category category = event.getItem(); + selectedCategory = category; + updateWidgets(category); + } + + private void selectionChange(final SingleSelectionEvent event) { + + saveButton.setEnabled(true); + cancelButton.setEnabled(true); + } + + private void updateWidgets(final Category category) { + + Objects.requireNonNull(category); + + final Optional page = controller + .getPagesController() + .findPage(category); + + if (page.isPresent()) { + panel.setCaption(textsUtil + .getText("cms.ui.pages.page_config_for_category", + new String[]{globalizationHelper + .getValueFromLocalizedString(category + .getTitle())})); + indexPageModelSelect.setSelectedItem(page.get().getIndexPageModel()); + itemPageModelSelect.setSelectedItem(page.get().getItemPageModel()); +// indexPageModelSelect.setValue(page.get().getIndexPageModel()); +// itemPageModelSelect.setValue(page.get().getItemPageModel()); + } else { + indexPageModelSelect.setSelectedItem(null); + itemPageModelSelect.setSelectedItem(null); + } + + saveButton.setEnabled(false); + cancelButton.setEnabled(false); + } + + private void saveButtonClicked(final Button.ClickEvent event) { + + final Page page = findOrCreatePage(); + + final Optional selectedIndexPageModel + = indexPageModelSelect + .getSelectedItem(); + if (selectedIndexPageModel.isPresent()) { + page.setIndexPageModel(selectedIndexPageModel.get()); + } else { + page.setIndexPageModel(null); + } + + final Optional selectedItemPageModel + = itemPageModelSelect + .getSelectedItem(); + if (selectedItemPageModel.isPresent()) { + page.setItemPageModel(selectedItemPageModel.get()); + } else { + page.setItemPageModel(null); + } + + controller.getPagesController().getPageRepo().save(page); + updateWidgets(selectedCategory); + } + + private Page findOrCreatePage() { + + final Optional page = controller + .getPagesController() + .findPage(selectedCategory); + + if (page.isPresent()) { + return page.get(); + } else { + + final PageManager pageManager = controller + .getPagesController() + .getPageManager(); + return pageManager.createPageForCategory(selectedCategory); + } + + } + + private void cancelButtonClicked(final Button.ClickEvent event) { + + updateWidgets(selectedCategory); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesEditor.java b/ccm-cms/src/main/java/org/librecms/ui/PagesEditor.java new file mode 100644 index 000000000..21a2ea346 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesEditor.java @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import com.vaadin.server.UserError; +import com.vaadin.ui.Button; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; +import com.vaadin.ui.themes.ValoTheme; +import org.libreccm.categorization.Domain; +import org.libreccm.l10n.LocalizedTextsUtil; +import org.libreccm.sites.Site; +import org.librecms.CmsConstants; +import org.librecms.pages.Pages; +import org.librecms.pages.PagesManager; + +/** + * + * @author Jens Pelzetter + */ +class PagesEditor extends Window { + + private static final long serialVersionUID = -7895690663139812879L; + + private final CmsViewController controller; + private final LocalizedTextsUtil textsUtil; + + private Pages pages; + + private final TextField nameField; + private final ComboBox siteSelect; + private final ComboBox categorySystemSelect; + + PagesEditor(final CmsViewController controller) { + + super(); + + this.controller = controller; + + textsUtil = controller + .getGlobalizationHelper() + .getLocalizedTextsUtil(CmsConstants.CMS_BUNDLE); + + nameField = new TextField(textsUtil + .getText("cms.ui.pages.form.primary_url_field.label")); + + siteSelect = new ComboBox<>(textsUtil + .getText("cms.ui.pages.form.site_select.error")); + siteSelect.setDataProvider(controller + .getPagesController() + .getPagesEditorSiteSelectDataProvider()); + siteSelect.setEmptySelectionAllowed(false); + siteSelect.setItemCaptionGenerator(this::buildSiteCaption); + + categorySystemSelect = new ComboBox<>(textsUtil + .getText("cms.ui.pages.form.category_domain_select.label")); + categorySystemSelect.setEmptySelectionAllowed(false); + categorySystemSelect.setDataProvider(controller + .getPagesController() + .getPagesEditorDomainSelectDataProvider()); + categorySystemSelect.setItemCaptionGenerator(Domain::getDomainKey); + + final FormLayout formLayout = new FormLayout(nameField, + siteSelect, + categorySystemSelect); + + final Button saveButton = new Button(textsUtil + .getText("cms.ui.pages.editor.save")); + saveButton.addStyleName(ValoTheme.BUTTON_PRIMARY); + saveButton.addClickListener(this::saveButtonClicked); + + final Button cancelButton = new Button(textsUtil + .getText("cms.ui.pages.editor.cancel")); + cancelButton.addStyleName(ValoTheme.BUTTON_DANGER); + cancelButton.addClickListener(event -> close()); + + super.setContent(new VerticalLayout(formLayout, + new HorizontalLayout(saveButton, + cancelButton))); + } + + PagesEditor(final Pages pages, + final CmsViewController controller) { + + this(controller); + + this.pages = pages; + + nameField.setValue(pages.getPrimaryUrl()); + siteSelect.setEnabled(false); + categorySystemSelect.setEnabled(false); + } + + private String buildSiteCaption(final Site site) { + + if (site.isDefaultSite()) { + return String.format("%s *", + site.getDomainOfSite()); + } else { + return site.getDomainOfSite(); + } + } + + private void saveButtonClicked(final Button.ClickEvent event) { + + if (nameField.getValue() == null + || nameField.getValue().isEmpty() + || nameField.getValue().matches("\\s*")) { + + nameField.setComponentError(new UserError(textsUtil + .getText("cms.ui.pages.form.primary_url_field.error"))); + return; + } + + if (pages == null + && !siteSelect.getSelectedItem().isPresent()) { + + siteSelect.setComponentError(new UserError(textsUtil + .getText("cms.ui.pages.form.site_select.error"))); + + return; + } + + if (pages == null + && !categorySystemSelect.getSelectedItem().isPresent()) { + + categorySystemSelect.setComponentError(new UserError(textsUtil + .getText("cms.ui.pages.form.category_domain_select.error"))); + + return; + } + + if (pages == null) { + final PagesController pagesController = controller + .getPagesController(); + + pages = pagesController + .createPages(generatePrimaryUrl(nameField.getValue()), + siteSelect.getValue(), + categorySystemSelect.getValue()); + } else { + + pages.setPrimaryUrl(generatePrimaryUrl(nameField.getValue())); + controller.getPagesController().getPagesRepo().save(pages); + } + + controller.getPagesController().getPagesGridDataProvider().refreshAll(); + close(); + } + + private String generatePrimaryUrl(final String name) { + + if (name.startsWith("/") && name.endsWith("/")) { + return name; + } else if (name.startsWith("/") && !name.endsWith("/")) { + return String.format("%s/", name); + } else if (!name.startsWith("/") && name.endsWith("/")) { + return String.format("/%s", name); + } else { + return String.format("/%s/", name); + } + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesEditorDomainSelectDataProvider.java b/ccm-cms/src/main/java/org/librecms/ui/PagesEditorDomainSelectDataProvider.java new file mode 100644 index 000000000..76f026737 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesEditorDomainSelectDataProvider.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import com.vaadin.cdi.ViewScoped; +import com.vaadin.data.provider.AbstractBackEndDataProvider; +import com.vaadin.data.provider.Query; +import org.libreccm.categorization.Domain; + +import java.util.stream.Stream; + +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +/** + * + * @author Jens Pelzetter + */ +@ViewScoped +class PagesEditorDomainSelectDataProvider + extends AbstractBackEndDataProvider { + + private static final long serialVersionUID = 7172310455833118907L; + + @Inject + private EntityManager entityManager; + + @Override + protected Stream fetchFromBackEnd( + final Query query) { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(Domain.class); + + final Root from = criteriaQuery.from(Domain.class); + if (query.getFilter().isPresent()) { + criteriaQuery.where(builder.like(from.get("domainKey"), + ":filter%")); + } + + final TypedQuery entityQuery = entityManager + .createQuery(criteriaQuery); + + if (query.getFilter().isPresent()) { + entityQuery.setParameter("filter", query.getFilter().get()); + } + + return entityQuery + .setFirstResult(query.getOffset()) + .setMaxResults(query.getLimit()) + .getResultList() + .stream(); + } + + @Override + protected int sizeInBackEnd(final Query query) { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(Long.class); + + final Root from = criteriaQuery.from(Domain.class); + criteriaQuery.select(builder.count(from)); + if (query.getFilter().isPresent()) { + criteriaQuery.where(builder.like(from.get("domainKey"), + ":filter%")); + } + + final TypedQuery entityQuery = entityManager + .createQuery(criteriaQuery); + + if (query.getFilter().isPresent()) { + entityQuery.setParameter("filter", query.getFilter().get()); + } + + return entityQuery.getSingleResult().intValue(); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesEditorSiteSelectDataProvider.java b/ccm-cms/src/main/java/org/librecms/ui/PagesEditorSiteSelectDataProvider.java new file mode 100644 index 000000000..d1f143f23 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesEditorSiteSelectDataProvider.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import com.vaadin.cdi.ViewScoped; +import com.vaadin.data.provider.AbstractBackEndDataProvider; +import com.vaadin.data.provider.Query; +import org.libreccm.sites.Site; + +import java.util.stream.Stream; + +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +/** + * + * @author Jens Pelzetter + */ +@ViewScoped +public class PagesEditorSiteSelectDataProvider extends AbstractBackEndDataProvider { + + private static final long serialVersionUID = 8334700797163099258L; + + @Inject + private EntityManager entityManager; + + @Override + protected Stream fetchFromBackEnd(final Query query) { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(Site.class); + + final Root from = criteriaQuery.from(Site.class); + + if (query.getFilter().isPresent()) { + criteriaQuery.where(builder.like(from.get("domainOfSite"), + ":filter%")); + } + + final TypedQuery entityQuery = entityManager + .createQuery(criteriaQuery); + + if (query.getFilter().isPresent()) { + entityQuery.setParameter("filter", query.getFilter().get()); + } + + return entityQuery + .setFirstResult(query.getOffset()) + .setMaxResults(query.getLimit()) + .getResultList() + .stream(); + } + + @Override + protected int sizeInBackEnd(final Query query) { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(Long.class); + + final Root from = criteriaQuery.from(Site.class); + criteriaQuery.select(builder.count(from)); + + if (query.getFilter().isPresent()) { + criteriaQuery.where(builder.like(from.get("domainOfSite"), + ":filter%")); + } + + final TypedQuery entityQuery = entityManager + .createQuery(criteriaQuery); + + if (query.getFilter().isPresent()) { + entityQuery.setParameter("filter", query.getFilter().get()); + } + + return entityQuery.getSingleResult().intValue(); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesGridDataProvider.java b/ccm-cms/src/main/java/org/librecms/ui/PagesGridDataProvider.java new file mode 100644 index 000000000..5b1ec0ce9 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesGridDataProvider.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import com.vaadin.cdi.ViewScoped; +import com.vaadin.data.provider.AbstractBackEndDataProvider; +import com.vaadin.data.provider.Query; +import org.librecms.pages.Pages; +import org.librecms.pages.PagesRepository; + +import java.util.stream.Stream; + +import javax.inject.Inject; + +/** + * + * @author Jens Pelzetter + */ +@ViewScoped +public class PagesGridDataProvider + extends AbstractBackEndDataProvider { + + private static final long serialVersionUID = -2388748600960614488L; + + @Inject + private PagesRepository pagesRepo; + + @Override + protected Stream fetchFromBackEnd(final Query query) { + + return pagesRepo + .findAll() + .stream(); + } + + @Override + protected int sizeInBackEnd(final Query query) { + + return pagesRepo.findAll().size(); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesTab.java b/ccm-cms/src/main/java/org/librecms/ui/PagesTab.java new file mode 100644 index 000000000..75ed2beb3 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesTab.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import com.vaadin.icons.VaadinIcons; +import com.vaadin.ui.Button; +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Grid; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.components.grid.HeaderCell; +import com.vaadin.ui.components.grid.HeaderRow; +import com.vaadin.ui.themes.ValoTheme; +import org.libreccm.l10n.LocalizedTextsUtil; +import org.libreccm.ui.ConfirmDialog; +import org.librecms.CmsConstants; +import org.librecms.pages.Pages; +import org.librecms.pages.PagesRepository; + + +/** + * + * @author Jens Pelzetter + */ +class PagesTab extends CustomComponent { + + private static final long serialVersionUID = 8237082714759130342L; + + private static final String COL_NAME = "name"; + private static final String COL_SITE = "site"; + private static final String COL_EDIT = "edit"; + private static final String COL_DEL = "del"; + + private final CmsViewController controller; + private final LocalizedTextsUtil textsUtil; + + PagesTab(final CmsViewController controller) { + + super(); + + this.controller = controller; + + textsUtil = controller + .getGlobalizationHelper() + .getLocalizedTextsUtil(CmsConstants.CMS_BUNDLE); + + final Grid pagesGrid = new Grid<>(); +// pagesGrid +// .addColumn(Pages::getPrimaryUrl) +// .setCaption("cms.ui.contentcenter.pagestable.columns.name.header") +// .setId(COL_NAME); + pagesGrid + .addComponentColumn(this::buildDetailsLink) + .setCaption(textsUtil + .getText("cms.ui.contentcenter.pagestable.columns.name.header")) + .setId(COL_NAME); + pagesGrid + .addColumn(pages -> pages.getSite().getDomainOfSite()) + .setCaption(textsUtil + .getText("cms.ui.contentcenter.pagestable.columns.site.header")) + .setId(COL_SITE); + pagesGrid + .addComponentColumn(this::buildEditButton) + .setCaption(textsUtil + .getText("cms.ui.contentcenter.pagestable.columns.edit.header")) + .setId(COL_EDIT); + pagesGrid + .addComponentColumn(this::buildDeleteButton) + .setCaption(textsUtil + .getText("cms.ui.contentcenter.pagestable.columns.delete.header")) + .setId(COL_DEL); + + final Button addPagesButton = new Button(textsUtil + .getText("cms.ui.contentcenter.pages.add_link")); + addPagesButton.addStyleName(ValoTheme.BUTTON_TINY); + addPagesButton.setIcon(VaadinIcons.PLUS_CIRCLE_O); + addPagesButton.addClickListener(this::addPagesButtonClicked); + final HeaderRow headerRow = pagesGrid.prependHeaderRow(); + final HeaderCell headerCell = headerRow + .join(COL_NAME, COL_SITE, COL_EDIT, COL_DEL); + headerCell.setComponent(new HorizontalLayout(addPagesButton)); + + pagesGrid.setDataProvider(controller + .getPagesController() + .getPagesGridDataProvider()); + pagesGrid.setWidth("100%"); + + super.setCompositionRoot(new VerticalLayout(pagesGrid)); + } + + private Component buildDetailsLink(final Pages pages) { + + final Button button = new Button(pages.getPrimaryUrl()); + button.addStyleName(ValoTheme.BUTTON_LINK); + button.addClickListener(event -> detailsLinkClicked(event, pages)); + + return button; + } + + private Component buildEditButton(final Pages pages) { + + final Button button = new Button(textsUtil + .getText("cms.ui.contentcenter.pages.edit.label")); + button.setIcon(VaadinIcons.EDIT); + button.addStyleName(ValoTheme.BUTTON_TINY); + button.addClickListener(event -> editButtonClicked(event, pages)); + + return button; + } + + private Component buildDeleteButton(final Pages pages) { + + final Button button = new Button(textsUtil + .getText("cms.ui.contentcenter.pages.delete.label")); + button.setIcon(VaadinIcons.MINUS_CIRCLE_O); + button.addStyleNames(ValoTheme.BUTTON_TINY, + ValoTheme.BUTTON_DANGER); + button.addClickListener(event -> deleteButtonClicked(event, pages)); + + return button; + } + + private void addPagesButtonClicked(final Button.ClickEvent event) { + + final PagesEditor editor = new PagesEditor(controller); + editor.setModal(true); + editor.setWidth("40%"); + editor.setHeight("60%"); + + UI.getCurrent().addWindow(editor); + } + + private void detailsLinkClicked(final Button.ClickEvent event, + final Pages pages) { + + final PagesDetails pagesDetails = new PagesDetails(pages, controller); + pagesDetails.setModal(true); + pagesDetails.setWidth("90%"); + pagesDetails.setHeight("90%"); + + UI.getCurrent().addWindow(pagesDetails); + } + + private void editButtonClicked(final Button.ClickEvent event, + final Pages pages) { + + final PagesEditor pagesEditor = new PagesEditor(pages, controller); + pagesEditor.setModal(true); + pagesEditor.setWidth("40%"); + pagesEditor.setHeight("80%"); + + UI.getCurrent().addWindow(pagesEditor); + } + + private void deleteButtonClicked(final Button.ClickEvent event, + final Pages pages) { + + final ConfirmDialog confirmDialog + = new ConfirmDialog(() -> deletePages(pages)); + confirmDialog.setMessage(textsUtil + .getText("cms.ui.contentcenter.pages.delete.confirm")); + confirmDialog.setModal(true); + + UI.getCurrent().addWindow(confirmDialog); + } + + private Void deletePages(final Pages pages) { + + final PagesRepository pagesRepo = controller + .getPagesController() + .getPagesRepo(); + + pagesRepo.delete(pages); + controller + .getPagesController() + .getPagesGridDataProvider() + .refreshAll(); + + return null; + } + +} diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties index f5b79d227..eddd91888 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties @@ -496,3 +496,10 @@ cms.ui.pages.page_config_for_category=Page Configuration for category {0} cms.ui.pages.assigned_page_model.inherit=Inherit from parent cms.ui.pages.no_category_selected=No category selected pages_application.title=Pages +cms.ui.contentcenter.pagestable.columns.name.header=Name +cms.ui.pages.editor.save=Save +cms.ui.pages.editor.cancel=Cancel +cms.ui.pages.pagemodels.index_page=Index Page Model +cms.ui.pages.pagemodels.item_page=Item Page Model +cms.ui.pages.pagemodels.save=Save +cms.ui.pages.pagemodels.cancel=Cancel diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties index dbe8ea021..c141513e0 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties @@ -493,3 +493,10 @@ cms.ui.pages.page_config_for_category=Seiten-Konfiguration f\u00fcr Kategorie {0 cms.ui.pages.assigned_page_model.inherit=PageModel der \u00fcbergeordneten Seite verwenden cms.ui.pages.no_category_selected=Keine Kategorie ausgew\u00e4hlt pages_application.title=Pages +cms.ui.contentcenter.pagestable.columns.name.header=Name +cms.ui.pages.editor.save=Speichern +cms.ui.pages.editor.cancel=Abbrechen +cms.ui.pages.pagemodels.index_page=Index Page Model +cms.ui.pages.pagemodels.item_page=Item Page Model +cms.ui.pages.pagemodels.save=Speichern +cms.ui.pages.pagemodels.cancel=Abbrechen diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties index 12faa82b2..f64ce5a73 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties @@ -452,3 +452,10 @@ cms.ui.pages.page_config_for_category=Page Configuration for category {0} cms.ui.pages.assigned_page_model.inherit=Inherit from parent cms.ui.pages.no_category_selected=No category selected pages_application.title=Pages +cms.ui.contentcenter.pagestable.columns.name.header=Name +cms.ui.pages.editor.save=Save +cms.ui.pages.editor.cancel=Cancel +cms.ui.pages.pagemodels.index_page=Index Page Model +cms.ui.pages.pagemodels.item_page=Item Page Model +cms.ui.pages.pagemodels.save=Save +cms.ui.pages.pagemodels.cancel=Cancel