CCM NG: Several small bugfixes

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5146 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2017-11-28 19:35:02 +00:00
parent e40256c375
commit 35dd01d8e2
23 changed files with 547 additions and 166 deletions

View File

@ -68,6 +68,9 @@
<Logger name="org.libreccm.modules.CcmIntegrator" <Logger name="org.libreccm.modules.CcmIntegrator"
level="debug"> level="debug">
</Logger> </Logger>
<Logger name="org.libreccm.pagemodel.PageModelManager"
level="debug">
</Logger>
<Logger name="org.libreccm.security.OneTimeAuthTokenCleaner" <Logger name="org.libreccm.security.OneTimeAuthTokenCleaner"
level="debug"> level="debug">
</Logger> </Logger>
@ -92,7 +95,7 @@
<Logger name="org.librecms.contentsection.rs.Images" <Logger name="org.librecms.contentsection.rs.Images"
level="debug"> level="debug">
</Logger> </Logger>
<Logger name="com.arsdigita.web.DefaultApplicationFileResolver" <Logger name="com.arsdigita.web.DefaultApplicationFileResolver"
level="debug"> level="debug">
</Logger> </Logger>
</Loggers> </Loggers>

View File

@ -18,11 +18,22 @@
*/ */
package com.arsdigita.cms.ui.category; package com.arsdigita.cms.ui.category;
import com.arsdigita.bebop.*; import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.event.*; import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.List;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.ParameterSingleSelectionModel;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.Tree;
import com.arsdigita.bebop.event.ChangeEvent;
import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.parameters.ParameterModel; import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ui.BaseAdminPane; import com.arsdigita.cms.ui.BaseAdminPane;
import com.arsdigita.cms.ui.BaseDeleteForm; import com.arsdigita.cms.ui.BaseDeleteForm;
import com.arsdigita.cms.ui.BaseTree; import com.arsdigita.cms.ui.BaseTree;
@ -30,17 +41,18 @@ import com.arsdigita.cms.ui.VisibilityComponent;
import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.Section; import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.libreccm.categorization.Categorization; import org.libreccm.categorization.Categorization;
import org.libreccm.categorization.Category; import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryManager;
import org.libreccm.categorization.CategoryRepository; import org.libreccm.categorization.CategoryRepository;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.UnexpectedErrorException;
import org.libreccm.security.PermissionChecker; import org.libreccm.security.PermissionChecker;
import org.librecms.contentsection.privileges.AdminPrivileges; import org.librecms.contentsection.privileges.AdminPrivileges;
import java.math.BigDecimal;
/** /**
* A split pane for the Category Administration UI. * A split pane for the Category Administration UI.
@ -53,7 +65,7 @@ public final class CategoryAdminPane extends BaseAdminPane {
public static final String CONTEXT_SELECTED = "sel_context"; public static final String CONTEXT_SELECTED = "sel_context";
private static final String DEFAULT_USE_CONTEXT = "<default>"; private static final String DEFAULT_USE_CONTEXT = "<default>";
private static final Logger LOGGER = LogManager.getLogger( private static final Logger LOGGER = LogManager.getLogger(
CategoryAdminPane.class); CategoryAdminPane.class);
private final SingleSelectionModel m_contextModel; private final SingleSelectionModel m_contextModel;
private final Tree m_categoryTree; private final Tree m_categoryTree;
private final SingleSelectionModel m_model; private final SingleSelectionModel m_model;
@ -63,16 +75,18 @@ public final class CategoryAdminPane extends BaseAdminPane {
public CategoryAdminPane() { public CategoryAdminPane() {
super(); super();
m_contextModel = new UseContextSelectionModel(new StringParameter(CONTEXT_SELECTED)); m_contextModel = new UseContextSelectionModel(new StringParameter(
CONTEXT_SELECTED));
/* Left column */ /* Left column */
/* Use context section */ /* Use context section */
List list = new List(new CategoryUseContextModelBuilder()); List list = new List(new CategoryUseContextModelBuilder());
list.setSelectionModel(m_contextModel); list.setSelectionModel(m_contextModel);
list.addChangeListener(new ContextSelectionListener()); list.addChangeListener(new ContextSelectionListener());
/* Category tree section */ /* Category tree section */
m_categoryTree = new BaseTree(new CategoryTreeModelBuilder(m_contextModel)); m_categoryTree = new BaseTree(new CategoryTreeModelBuilder(
m_contextModel));
m_categoryTree.addChangeListener(new SelectionListener()); m_categoryTree.addChangeListener(new SelectionListener());
m_model = m_categoryTree.getSelectionModel(); m_model = m_categoryTree.getSelectionModel();
@ -87,11 +101,12 @@ public final class CategoryAdminPane extends BaseAdminPane {
contextGroup.setSubject(list); contextGroup.setSubject(list);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(PermissionChecker.class); final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
if (permissionChecker.isPermitted(AdminPrivileges.ADMINISTER_CATEGORIES)) { if (permissionChecker.isPermitted(AdminPrivileges.ADMINISTER_CATEGORIES)) {
ActionLink addContextAction = new ActionLink(new Label(gz( ActionLink addContextAction = new ActionLink(new Label(gz(
"cms.ui.category.add_use_context"))); "cms.ui.category.add_use_context")));
Form addContextForm = new AddUseContextForm(m_contextModel); Form addContextForm = new AddUseContextForm(m_contextModel);
getBody().add(addContextForm); getBody().add(addContextForm);
getBody().connect(addContextAction, addContextForm); getBody().connect(addContextAction, addContextForm);
@ -119,8 +134,9 @@ public final class CategoryAdminPane extends BaseAdminPane {
setEdit(gz("cms.ui.category.edit"), setEdit(gz("cms.ui.category.edit"),
new CategoryEditForm(m_parent, m_category)); new CategoryEditForm(m_parent, m_category));
setDelete(new DeleteLink(new Label(gz("cms.ui.category.delete"))), new DeleteForm( setDelete(new DeleteLink(new Label(gz("cms.ui.category.delete"))),
new SimpleContainer())); new DeleteForm(
new SimpleContainer()));
setIntroPane(new Label(gz("cms.ui.category.intro"))); setIntroPane(new Label(gz("cms.ui.category.intro")));
setItemPane(new CategoryItemPane(m_model, setItemPane(new CategoryItemPane(m_model,
@ -157,7 +173,6 @@ public final class CategoryAdminPane extends BaseAdminPane {
//String context = getUseContext(state); //String context = getUseContext(state);
//boolean isDefaultContext = //boolean isDefaultContext =
// (context == null) || DEFAULT_USE_CONTEXT.equals(context); // (context == null) || DEFAULT_USE_CONTEXT.equals(context);
//if (cat.isRoot() || !cat.getChildren().isEmpty()) { //if (cat.isRoot() || !cat.getChildren().isEmpty()) {
// m_alternativeLabel.generateXML(state, parent); // m_alternativeLabel.generateXML(state, parent);
//} else { //} else {
@ -175,8 +190,7 @@ public final class CategoryAdminPane extends BaseAdminPane {
Label catLabel = new Label(); Label catLabel = new Label();
catLabel.addPrintListener(pe -> { catLabel.addPrintListener(pe -> {
Label label = (Label) pe.getTarget(); Label label = (Label) pe.getTarget();
Category cat = Category cat = m_category.getCategory(pe.getPageState());
m_category.getCategory(pe.getPageState());
java.util.List<Category> descendants = cat.getSubCategories(); java.util.List<Category> descendants = cat.getSubCategories();
java.util.List<Categorization> catObjects = cat.getObjects(); java.util.List<Categorization> catObjects = cat.getObjects();
@ -191,7 +205,8 @@ public final class CategoryAdminPane extends BaseAdminPane {
sb.append(" descendant object(s). "); sb.append(" descendant object(s). ");
} }
if (descendants.size() > 0 || catObjects.size() > 0) { if (descendants.size() > 0 || catObjects.size() > 0) {
sb.append("Descendants will be orphaned, if this category is removed."); sb.append(
"Descendants will be orphaned, if this category is removed.");
} }
label.setLabel(gz(sb.toString())); label.setLabel(gz(sb.toString()));
}); });
@ -200,11 +215,13 @@ public final class CategoryAdminPane extends BaseAdminPane {
@Override @Override
public final void process(final FormSectionEvent e) public final void process(final FormSectionEvent e)
throws FormProcessException { throws FormProcessException {
final PageState state = e.getPageState(); final PageState state = e.getPageState();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(PermissionChecker.class); final PermissionChecker permissionChecker = cdiUtil.findBean(
final CategoryRepository repository = cdiUtil.findBean(CategoryRepository.class); PermissionChecker.class);
final CategoryRepository repository = cdiUtil.findBean(
CategoryRepository.class);
final Category category = m_category.getCategory(state); final Category category = m_category.getCategory(state);
if (category == null) { if (category == null) {
return; return;
@ -214,7 +231,8 @@ public final class CategoryAdminPane extends BaseAdminPane {
// category, // category,
// Kernel.getContext(). // Kernel.getContext().
// getParty())); // getParty()));
permissionChecker.checkPermission(AdminPrivileges.ADMINISTER_CATEGORIES, category); permissionChecker.checkPermission(
AdminPrivileges.ADMINISTER_CATEGORIES, category);
// if (category.isRoot()) { // if (category.isRoot()) {
// Category root = // Category root =
@ -226,8 +244,8 @@ public final class CategoryAdminPane extends BaseAdminPane {
// } // }
// m_contextModel.setSelectedKey(state, DEFAULT_USE_CONTEXT); // m_contextModel.setSelectedKey(state, DEFAULT_USE_CONTEXT);
// } else { // } else {
Category parent = category.getParentCategory(); Category parent = category.getParentCategory();
m_model.setSelectedKey(state, parent.getUniqueId()); m_model.setSelectedKey(state, parent.getUniqueId());
// } // }
//category.deleteCategoryAndOrphan(); //category.deleteCategoryAndOrphan();
@ -242,7 +260,8 @@ public final class CategoryAdminPane extends BaseAdminPane {
protected final Object initialValue(final PageState state) { protected final Object initialValue(final PageState state) {
final String id = m_model.getSelectedKey(state).toString(); final String id = m_model.getSelectedKey(state).toString();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CategoryRepository repository = cdiUtil.findBean(CategoryRepository.class); final CategoryRepository repository = cdiUtil.findBean(
CategoryRepository.class);
if (id == null) { if (id == null) {
return null; return null;
} else { } else {
@ -277,7 +296,6 @@ public final class CategoryAdminPane extends BaseAdminPane {
// } // }
// //
// } // }
private class UseContextSelectionModel extends ParameterSingleSelectionModel { private class UseContextSelectionModel extends ParameterSingleSelectionModel {
public UseContextSelectionModel(ParameterModel m) { public UseContextSelectionModel(ParameterModel m) {
@ -304,15 +322,26 @@ public final class CategoryAdminPane extends BaseAdminPane {
public class ContextSelectionListener implements ChangeListener { public class ContextSelectionListener implements ChangeListener {
public final void stateChanged(final ChangeEvent e) { public final void stateChanged(final ChangeEvent event) {
LOGGER.debug("Selection state changed; I may change " + "the body's visible pane"); LOGGER.debug("Selection state changed; I may change "
+ "the body's visible pane");
final PageState state = e.getPageState(); final PageState state = event.getPageState();
getBody().reset(state); getBody().reset(state);
if (m_contextModel.isSelected(state)) { if (m_contextModel.isSelected(state)) {
final Category root = (Category) m_contextModel.getSelectedKey(state);
final String rootCategoryId = (String) m_contextModel
.getSelectedKey(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CategoryRepository categoryRepo = cdiUtil
.findBean(CategoryRepository.class);
final Category root = categoryRepo
.findById(Long.parseLong(rootCategoryId))
.orElseThrow(() -> new UnexpectedErrorException(String
.format("No Category with ID %s in the database.",
rootCategoryId)));
if (root != null) { if (root != null) {
m_model.setSelectedKey(state, root.getUniqueId()); m_model.setSelectedKey(state, root.getUniqueId());
@ -321,11 +350,13 @@ public final class CategoryAdminPane extends BaseAdminPane {
} }
if (m_model.isSelected(state)) { if (m_model.isSelected(state)) {
LOGGER.debug("The selection model is selected; displaying " + "the item pane"); LOGGER.debug("The selection model is selected; displaying "
+ "the item pane");
getBody().push(state, getItemPane()); getBody().push(state, getItemPane());
} }
} }
} }
} }

View File

@ -109,32 +109,29 @@ public class ItemListComponentForm
final PageState state, final PageState state,
final FormData data) { final FormData data) {
final Object[] descendingValues = (Object[]) data.get(DESCENDING); final Object[] descendingValues = (Object[]) data.get(DESCENDING_BOX);
final String limitToTypeValue = data.getString(LIMIT_TO_TYPE); final String limitToTypeValue = data.getString(LIMIT_TO_TYPE);
final String pageSizeValue = data.getString(PAGE_SIZE); final String pageSizeValue = data.getString(PAGE_SIZE);
final String listOrderValue = data.getString(LIST_ORDER); final String listOrderValue = data.getString(LIST_ORDER);
final boolean descendingValue; final boolean descendingValue = isDescending(descendingValues);
if (descendingValues != null
&& descendingValues.length != 0
&& DESCENDING.equals(descendingValues[0])) {
descendingValue = true;
} else {
descendingValue = false;
}
final List<String> listOrder = Arrays final List<String> listOrder = Arrays
.stream(listOrderValue.split("\n")) .stream(listOrderValue.split("\n"))
.collect(Collectors.toList()); .collect(Collectors.toList());
componentModel.setDescending(descendingValue); componentModel.setDescending(descendingValue);
componentModel.setLimitToTypes(limitToTypeValue); componentModel.setLimitToType(limitToTypeValue);
componentModel.setPageSize(Integer.parseInt(pageSizeValue)); componentModel.setPageSize(Integer.parseInt(pageSizeValue));
componentModel.setListOrder(listOrder); componentModel.setListOrder(listOrder);
} }
private boolean isDescending(final Object[] descendingValues) {
return descendingValues != null
&& descendingValues.length != 0
&& DESCENDING.equals(descendingValues[0]);
}
@Override @Override
public void init(final FormSectionEvent event) public void init(final FormSectionEvent event)
throws FormProcessException { throws FormProcessException {
@ -145,21 +142,23 @@ public class ItemListComponentForm
final ItemListComponent component = getComponentModel(); final ItemListComponent component = getComponentModel();
final Object[] descendingValue; if (component != null) {
if (component.isDescending()) { final Object[] descendingValue;
descendingValue = new Object[]{DESCENDING}; if (component.isDescending()) {
} else { descendingValue = new Object[]{DESCENDING};
descendingValue = new Object[]{}; } else {
descendingValue = new Object[]{};
}
descendingBox.setValue(state, descendingValue);
limitToTypeField.setValue(state, component.getLimitToType());
pageSizeField.setValue(state, Integer.toString(component
.getPageSize()));
listOrderArea.setValue(state,
String.join("\n", component.getListOrder()));
} }
descendingBox.setValue(state, descendingValue);
limitToTypeField.setValue(state, component.getLimitToType());
pageSizeField.setValue(state, Integer.toString(component.getPageSize()));
listOrderArea.setValue(state,
String.join("\n", component.getListOrder()));
} }
@Override @Override
@ -186,4 +185,5 @@ public class ItemListComponentForm
} }
} }
} }
} }

View File

@ -21,7 +21,6 @@ package com.arsdigita.cms.ui.pages;
import com.arsdigita.bebop.BoxPanel; import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form; import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormData; import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormModel;
import com.arsdigita.bebop.FormProcessException; import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
@ -33,7 +32,6 @@ import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.Tree; import com.arsdigita.bebop.Tree;
import com.arsdigita.bebop.event.ActionEvent; import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ChangeEvent; import com.arsdigita.bebop.event.ChangeEvent;
import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.PrintEvent; import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.form.Option; import com.arsdigita.bebop.form.Option;
@ -241,7 +239,7 @@ public class PagesAdminPage extends Page {
final PageModelRepository pageModelRepo = cdiUtil final PageModelRepository pageModelRepo = cdiUtil
.findBean(PageModelRepository.class); .findBean(PageModelRepository.class);
final List<PageModel> pageModels = pageModelRepo final List<PageModel> pageModels = pageModelRepo
.findByApplication(pagesInstance); .findDraftByApplication(pagesInstance);
final GlobalizationHelper globalizationHelper = cdiUtil final GlobalizationHelper globalizationHelper = cdiUtil
.findBean(GlobalizationHelper.class); .findBean(GlobalizationHelper.class);

View File

@ -87,6 +87,7 @@ import java.util.Properties;
instanceForm = ApplicationInstanceForm.class, instanceForm = ApplicationInstanceForm.class,
settingsPane = SettingsPane.class, settingsPane = SettingsPane.class,
descBundle = CmsConstants.CMS_BUNDLE, descBundle = CmsConstants.CMS_BUNDLE,
titleKey = "pages_application.title",
creator = PagesCreator.class, creator = PagesCreator.class,
servletPath = "/templates/servlet/pages" servletPath = "/templates/servlet/pages"
) )

View File

@ -79,6 +79,10 @@ public class ItemListComponent extends ComponentModel {
@Column(name = "LIST_ORDER") @Column(name = "LIST_ORDER")
private List<String> listOrder; private List<String> listOrder;
public ItemListComponent() {
listOrder = new ArrayList<>();
}
public boolean isDescending() { public boolean isDescending() {
return descending; return descending;
} }
@ -91,7 +95,7 @@ public class ItemListComponent extends ComponentModel {
return limitToType; return limitToType;
} }
public void setLimitToTypes(final String limitToType) { public void setLimitToType(final String limitToType) {
this.limitToType = limitToType; this.limitToType = limitToType;
} }

View File

@ -495,3 +495,4 @@ cms.ui.pages.title=Administer pages
cms.ui.pages.page_config_for_category=Page Configuration for category {0} 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.assigned_page_model.inherit=Inherit from parent
cms.ui.pages.no_category_selected=No category selected cms.ui.pages.no_category_selected=No category selected
pages_application.title=Pages

View File

@ -492,3 +492,4 @@ cms.ui.pages.title=Seitenbaum verwalten
cms.ui.pages.page_config_for_category=Seiten-Konfiguration f\u00fcr Kategorie {0} 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.assigned_page_model.inherit=PageModel der \u00fcbergeordneten Seite verwenden
cms.ui.pages.no_category_selected=Keine Kategorie ausgew\u00e4hlt cms.ui.pages.no_category_selected=Keine Kategorie ausgew\u00e4hlt
pages_application.title=Pages

View File

@ -451,3 +451,4 @@ cms.ui.pages.title=Administer pages
cms.ui.pages.page_config_for_category=Page Configuration for category {0} 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.assigned_page_model.inherit=Inherit from parent
cms.ui.pages.no_category_selected=No category selected cms.ui.pages.no_category_selected=No category selected
pages_application.title=Pages

View File

@ -26,7 +26,7 @@ import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.ParameterSingleSelectionModel; import com.arsdigita.bebop.ParameterSingleSelectionModel;
import com.arsdigita.bebop.PropertySheet; import com.arsdigita.bebop.PropertySheet;
import com.arsdigita.bebop.event.FormProcessListener; import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.PrintEvent; import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener; import com.arsdigita.bebop.event.PrintListener;
@ -42,6 +42,7 @@ import org.libreccm.pagemodel.ComponentModel;
import org.libreccm.pagemodel.ComponentModels; import org.libreccm.pagemodel.ComponentModels;
import org.libreccm.pagemodel.PageModel; import org.libreccm.pagemodel.PageModel;
import org.libreccm.pagemodel.PageModelComponentModel; import org.libreccm.pagemodel.PageModelComponentModel;
import org.libreccm.pagemodel.PageModelManager;
import org.libreccm.pagemodel.PageModelRepository; import org.libreccm.pagemodel.PageModelRepository;
import java.util.List; import java.util.List;
@ -55,6 +56,10 @@ import java.util.TooManyListenersException;
*/ */
class PageModelDetails extends BoxPanel { class PageModelDetails extends BoxPanel {
private final PageModelsTab pageModelTab;
private final ParameterSingleSelectionModel<String> selectedModelId;
private final ParameterSingleSelectionModel<String> selectedComponentId;
public PageModelDetails( public PageModelDetails(
final PageModelsTab pageModelTab, final PageModelsTab pageModelTab,
final ParameterSingleSelectionModel<String> selectedModelId, final ParameterSingleSelectionModel<String> selectedModelId,
@ -62,6 +67,10 @@ class PageModelDetails extends BoxPanel {
super(BoxPanel.VERTICAL); super(BoxPanel.VERTICAL);
this.pageModelTab = pageModelTab;
this.selectedModelId = selectedModelId;
this.selectedComponentId = selectedComponentId;
final ActionLink backLink = new ActionLink(new GlobalizedMessage( final ActionLink backLink = new ActionLink(new GlobalizedMessage(
"ui.admin.pagemodels.details.back", "ui.admin.pagemodels.details.back",
AdminUiConstants.ADMIN_BUNDLE)); AdminUiConstants.ADMIN_BUNDLE));
@ -74,20 +83,7 @@ class PageModelDetails extends BoxPanel {
final Label heading = new Label(); final Label heading = new Label();
heading.setClassAttr("heading"); heading.setClassAttr("heading");
heading.addPrintListener(event -> { heading.addPrintListener(this::printHeading);
final PageState state = event.getPageState();
final Label target = (Label) event.getTarget();
final PageModelRepository pageModelRepo = CdiUtil
.createCdiUtil()
.findBean(PageModelRepository.class);
final PageModel pageModel = pageModelRepo
.findById(Long.parseLong(selectedModelId.getSelectedKey(state)))
.get();
target.setLabel(new GlobalizedMessage(
"ui.admin.pagemodels.details.heading",
AdminUiConstants.ADMIN_BUNDLE,
new String[]{pageModel.getName()}));
});
super.add(heading); super.add(heading);
final PropertySheet propertySheet = new PropertySheet( final PropertySheet propertySheet = new PropertySheet(
@ -100,7 +96,16 @@ class PageModelDetails extends BoxPanel {
editProperties.addActionListener(event -> { editProperties.addActionListener(event -> {
pageModelTab.showPageModelForm(event.getPageState()); pageModelTab.showPageModelForm(event.getPageState());
}); });
super.add(editProperties);
final ActionLink publishLink = new ActionLink(new GlobalizedMessage(
"ui.admin.pagemodels.details.publish",
AdminUiConstants.ADMIN_BUNDLE));
publishLink.addActionListener(this::publishPageModel);
final BoxPanel actionsPanel = new BoxPanel(BoxPanel.HORIZONTAL);
actionsPanel.add(editProperties);
actionsPanel.add(publishLink);
super.add(actionsPanel);
final AddComponentForm addComponentForm = new AddComponentForm( final AddComponentForm addComponentForm = new AddComponentForm(
pageModelTab); pageModelTab);
@ -112,13 +117,49 @@ class PageModelDetails extends BoxPanel {
super.add(componentsTable); super.add(componentsTable);
} }
private void printHeading(final PrintEvent event) {
final PageState state = event.getPageState();
final Label target = (Label) event.getTarget();
final PageModelRepository pageModelRepo = CdiUtil
.createCdiUtil()
.findBean(PageModelRepository.class);
final PageModel pageModel = pageModelRepo
.findById(Long.parseLong(selectedModelId.getSelectedKey(state)))
.get();
target.setLabel(new GlobalizedMessage(
"ui.admin.pagemodels.details.heading",
AdminUiConstants.ADMIN_BUNDLE,
new String[]{pageModel.getName()}));
}
private void publishPageModel(final ActionEvent event) {
final PageState state = event.getPageState();
final String selectedPageModelIdStr = selectedModelId
.getSelectedKey(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PageModelManager pageModelManager = cdiUtil
.findBean(PageModelManager.class);
final PageModelRepository pageModelRepo = cdiUtil
.findBean(PageModelRepository.class);
final PageModel pageModel = pageModelRepo
.findById(Long.parseLong(selectedPageModelIdStr))
.orElseThrow(() -> new UnexpectedErrorException(String
.format("No PageModel with ID %s in the database.",
selectedPageModelIdStr)));
final PageModel draftModel = pageModelManager.getDraftVersion(pageModel);
pageModelManager.publish(draftModel);
}
/** /**
* Form for selecting the type of {@link ComponentModel} to add to the * Form for selecting the type of {@link ComponentModel} to add to the
* {@link PageModel}. * {@link PageModel}.
*/ */
private class AddComponentForm private class AddComponentForm extends Form {
extends Form
implements FormProcessListener {
private final PageModelsTab pageModelTab; private final PageModelsTab pageModelTab;
private final SingleSelect selectType; private final SingleSelect selectType;
@ -152,10 +193,9 @@ class PageModelDetails extends BoxPanel {
AdminUiConstants.ADMIN_BUNDLE)); AdminUiConstants.ADMIN_BUNDLE));
super.add(submit); super.add(submit);
super.addProcessListener(this); super.addProcessListener(this::process);
} }
@Override
public void process(final FormSectionEvent event) public void process(final FormSectionEvent event)
throws FormProcessException { throws FormProcessException {

View File

@ -82,7 +82,7 @@ class PageModelsController implements Serializable {
protected List<PageModelsTableRow> findPageModels() { protected List<PageModelsTableRow> findPageModels() {
return pageModelRepo return pageModelRepo
.findAll() .findAllDraftModels()
.stream() .stream()
.map(this::buildRow) .map(this::buildRow)
.sorted() .sorted()
@ -109,7 +109,7 @@ class PageModelsController implements Serializable {
applicationId))); applicationId)));
return !pageModelRepo return !pageModelRepo
.findByApplicationAndName(application, name) .findLiveByApplicationAndName(application, name)
.isPresent(); .isPresent();
} }

View File

@ -23,6 +23,7 @@ import com.vaadin.data.provider.AbstractBackEndHierarchicalDataProvider;
import com.vaadin.data.provider.HierarchicalQuery; import com.vaadin.data.provider.HierarchicalQuery;
import org.libreccm.core.UnexpectedErrorException; import org.libreccm.core.UnexpectedErrorException;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.l10n.LocalizedTextsUtil;
import org.libreccm.web.ApplicationManager; import org.libreccm.web.ApplicationManager;
import org.libreccm.web.ApplicationRepository; import org.libreccm.web.ApplicationRepository;
import org.libreccm.web.ApplicationType; import org.libreccm.web.ApplicationType;
@ -99,10 +100,10 @@ class ApplicationTreeDataProvider
private ApplicationTreeNode buildApplicationTreeNode( private ApplicationTreeNode buildApplicationTreeNode(
final ApplicationType type) { final ApplicationType type) {
final ResourceBundle bundle = ResourceBundle final LocalizedTextsUtil textsUtil = globalizationHelper
.getBundle(type.descBundle()); .getLocalizedTextsUtil(type.descBundle());
final String title = bundle.getString(type.titleKey()); final String title = textsUtil.getText(type.titleKey());
final ApplicationTreeNode node = new ApplicationTreeNode(); final ApplicationTreeNode node = new ApplicationTreeNode();
node.setTitle(title); node.setTitle(title);
@ -155,8 +156,18 @@ class ApplicationTreeDataProvider
node.setNodeId(application.getUuid()); node.setNodeId(application.getUuid());
node.setNodeType(ApplicationTreeNodeType.APPLICATION_NODE); node.setNodeType(ApplicationTreeNodeType.APPLICATION_NODE);
node.setTitle(globalizationHelper final String title;
.getValueFromLocalizedString(application.getTitle())); if (globalizationHelper
.getValueFromLocalizedString(application.getTitle()) == null
|| globalizationHelper
.getValueFromLocalizedString(application.getTitle()).isEmpty()) {
title = application.getPrimaryUrl();
} else {
title =globalizationHelper
.getValueFromLocalizedString(application.getTitle());
}
node.setTitle(title);
return node; return node;
} }

View File

@ -26,6 +26,7 @@ import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent; import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Grid; import com.vaadin.ui.Grid;
import com.vaadin.ui.HorizontalSplitPanel; import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
import com.vaadin.ui.Tree; import com.vaadin.ui.Tree;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.VerticalLayout;
@ -33,9 +34,6 @@ import com.vaadin.ui.themes.ValoTheme;
import org.libreccm.l10n.LocalizedTextsUtil; import org.libreccm.l10n.LocalizedTextsUtil;
import org.libreccm.pagemodel.PageModel; import org.libreccm.pagemodel.PageModel;
import org.libreccm.ui.ConfirmDialog; import org.libreccm.ui.ConfirmDialog;
import org.libreccm.web.CcmApplication;
import java.util.concurrent.Callable;
/** /**
* *
@ -59,8 +57,8 @@ class PageModelsTab extends CustomComponent {
final Tree<ApplicationTreeNode> applicationTree = new Tree<>( final Tree<ApplicationTreeNode> applicationTree = new Tree<>(
adminViewController.getApplicationTreeDataProvider()); adminViewController.getApplicationTreeDataProvider());
applicationTree.addItemClickListener(event -> { applicationTree.setItemCaptionGenerator(ApplicationTreeNode::getTitle);
});
applicationTree.setItemCollapseAllowedProvider(node -> { applicationTree.setItemCollapseAllowedProvider(node -> {
return !node.getNodeType().equals(ApplicationTreeNodeType.ROOT_NODE); return !node.getNodeType().equals(ApplicationTreeNodeType.ROOT_NODE);
}); });
@ -102,9 +100,27 @@ class PageModelsTab extends CustomComponent {
adminViewController)) adminViewController))
.setId(COL_DELETE); .setId(COL_DELETE);
super.setCompositionRoot(new HorizontalSplitPanel(applicationTree, pageModelsGrid.setVisible(false);
pageModelsGrid));
final Label placeholder = new Label(localizedTextsUtil.getText(
"ui.admin.pagemodels.select_application"));
final VerticalLayout layout = new VerticalLayout(pageModelsGrid,
placeholder);
applicationTree.addItemClickListener(event -> {
final PageModelsTableDataProvider dataProvider
= (PageModelsTableDataProvider) pageModelsGrid
.getDataProvider();
dataProvider.setApplicationUuid(event.getItem().getNodeId());
pageModelsGrid.setVisible(true);
placeholder.setVisible(false);
});
final HorizontalSplitPanel panel = new HorizontalSplitPanel(
applicationTree, layout);
panel.setSplitPosition(33.0f);
super.setCompositionRoot(panel);
} }
private Component buildEditButton(final PageModelsTableRow row, private Component buildEditButton(final PageModelsTableRow row,

View File

@ -21,10 +21,12 @@ package org.libreccm.admin.ui;
import com.vaadin.cdi.ViewScoped; import com.vaadin.cdi.ViewScoped;
import com.vaadin.data.provider.AbstractBackEndDataProvider; import com.vaadin.data.provider.AbstractBackEndDataProvider;
import com.vaadin.data.provider.Query; import com.vaadin.data.provider.Query;
import org.libreccm.core.UnexpectedErrorException;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.pagemodel.PageModel; import org.libreccm.pagemodel.PageModel;
import org.libreccm.pagemodel.PageModelManager; import org.libreccm.pagemodel.PageModelManager;
import org.libreccm.pagemodel.PageModelVersion; import org.libreccm.pagemodel.PageModelVersion;
import org.libreccm.web.ApplicationRepository;
import org.libreccm.web.CcmApplication; import org.libreccm.web.CcmApplication;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -46,6 +48,9 @@ class PageModelsTableDataProvider
private static final long serialVersionUID = 8052894182508842905L; private static final long serialVersionUID = 8052894182508842905L;
@Inject
private ApplicationRepository applicationRepo;
@Inject @Inject
private EntityManager entityManager; private EntityManager entityManager;
@ -66,6 +71,16 @@ class PageModelsTableDataProvider
refreshAll(); refreshAll();
} }
@Transactional(Transactional.TxType.REQUIRED)
public void setApplicationUuid(final String uuid) {
application = applicationRepo
.findByUuid(uuid)
.orElseThrow(() -> new UnexpectedErrorException(String
.format("No Application with UUID %s in the database.",
uuid)));
refreshAll();
}
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
@Override @Override
protected Stream<PageModelsTableRow> fetchFromBackEnd( protected Stream<PageModelsTableRow> fetchFromBackEnd(
@ -86,8 +101,8 @@ class PageModelsTableDataProvider
.and(builder.equal(from.get("application"), application), .and(builder.equal(from.get("application"), application),
builder.equal(from.get("version"), builder.equal(from.get("version"),
PageModelVersion.DRAFT))) PageModelVersion.DRAFT)))
.orderBy(builder.asc(from.get("name"))) .orderBy(builder.asc(from.get("name")));
.orderBy(builder.asc(from.get("title"))); // .orderBy(builder.asc(from.get("title")));
return entityManager return entityManager
.createQuery(criteriaQuery) .createQuery(criteriaQuery)

View File

@ -50,8 +50,9 @@ import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
/** /**
* A {@link PageModel} is used by a {@link PageRenderer} implementation to render * A {@link PageModel} is used by a {@link PageRenderer} implementation to
* a page. The {@code PageModel} specifics which components are used on a page. * render a page. The {@code PageModel} specifics which components are used on a
* page.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* *
@ -63,6 +64,16 @@ import javax.persistence.Table;
@Inheritance(strategy = InheritanceType.JOINED) @Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "PAGE_MODELS", schema = CoreConstants.DB_SCHEMA) @Table(name = "PAGE_MODELS", schema = CoreConstants.DB_SCHEMA)
@NamedQueries({ @NamedQueries({
@NamedQuery(
name = "PageModel.findAllDraftModels",
query = "SELECT p FROM PageModel p "
+ "WHERE p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT")
,
@NamedQuery(
name = "PageModel.findAllLiveModels",
query = "SELECT p FROM PageModel p "
+ "WHERE p.version = org.libreccm.pagemodel.PageModelVersion.LIVE")
,
@NamedQuery( @NamedQuery(
name = "PageModel.findDraftVersion", name = "PageModel.findDraftVersion",
query = "SELECT p FROM PageModel p " query = "SELECT p FROM PageModel p "
@ -84,19 +95,47 @@ import javax.persistence.Table;
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE") + "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE")
, ,
@NamedQuery( @NamedQuery(
name = "PageModel.findByApplication", name = "PageModel.findDraftByApplication",
query = "SELECT p FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT"
)
,
@NamedQuery(
name = "PageModel.findDraftByApplicationAndName",
query = "SELECT p FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT"
)
,
@NamedQuery(
name = "PageModel.countDraftByApplicationAndName",
query = "SELECT COUNT(p) FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT"
)
,
@NamedQuery(
name = "PageModel.countDraftByApplication",
query = "SELECT COUNT(p) FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT"
)
,
@NamedQuery(
name = "PageModel.findLiveByApplication",
query = "SELECT p FROM PageModel p " query = "SELECT p FROM PageModel p "
+ "WHERE p.application = :application " + "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE") + "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE")
, ,
@NamedQuery( @NamedQuery(
name = "PageModel.countByApplication", name = "PageModel.countLiveByApplication",
query = "SELECT COUNT(p) FROM PageModel p " query = "SELECT COUNT(p) FROM PageModel p "
+ "WHERE p.application = :application " + "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE") + "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE")
, ,
@NamedQuery( @NamedQuery(
name = "PageModel.findByApplicationAndName", name = "PageModel.findLiveByApplicationAndName",
query = "SELECT p FROM PageModel p " query = "SELECT p FROM PageModel p "
+ "WHERE p.name = :name " + "WHERE p.name = :name "
+ "AND p.application = :application " + "AND p.application = :application "
@ -104,7 +143,7 @@ import javax.persistence.Table;
) )
, ,
@NamedQuery( @NamedQuery(
name = "PageModel.countByApplicationAndName", name = "PageModel.countLiveByApplicationAndName",
query = "SELECT COUNT(p) FROM PageModel p " query = "SELECT COUNT(p) FROM PageModel p "
+ "WHERE p.name = :name " + "WHERE p.name = :name "
+ "AND p.application = :application " + "AND p.application = :application "
@ -206,6 +245,7 @@ public class PageModel implements Serializable {
public PageModel() { public PageModel() {
title = new LocalizedString(); title = new LocalizedString();
description = new LocalizedString(); description = new LocalizedString();
components = new ArrayList<>();
} }
public long getPageModelId() { public long getPageModelId() {

View File

@ -46,6 +46,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.Set; import java.util.Set;
@ -114,7 +115,7 @@ public class PageModelManager {
/** /**
* Creates a new {@link PageModel} for the provided application. The method * Creates a new {@link PageModel} for the provided application. The method
* tries to retrieve the appropriate application by using * tries to retrieve the appropriate application by using
* {@link PageModelRepository#findByApplicationAndName(org.libreccm.web.CcmApplication, java.lang.String)}. * {@link PageModelRepository#findLiveByApplicationAndName(org.libreccm.web.CcmApplication, java.lang.String)}.
* Please note that this method will always return the * Please note that this method will always return the
* <strong>draft</strong> * <strong>draft</strong>
* version of the page model. * version of the page model.
@ -134,23 +135,24 @@ public class PageModelManager {
final CcmApplication application, final CcmApplication application,
final String type) { final String type) {
if (application == null) { Objects.requireNonNull(application,
"Can't create a page model for application null");
Objects.requireNonNull(name, "Then name of a Pagemodel can't be null.");
if (name.isEmpty()
|| name.matches("\\s*")) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Can't create a page model for application null"); "The name of a PageModel can't be empty.");
} }
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException(
"The name of a page model can't be null or empty.");
}
LOGGER.debug( LOGGER.debug(
"Creating new PageModel with name \"{}\" for application \"{}\" and type \"{}\".", "Creating new PageModel with name \"{}\" for application \"{}\" and type \"{}\".",
name, name,
application.getPrimaryUrl(), application.getPrimaryUrl(),
type); type);
final long count = pageModelRepo.countByApplicationAndName(application, final long count = pageModelRepo.countLiveByApplicationAndName(
name); application,
name);
if (count > 0) { if (count > 0) {
LOGGER.error("A page model with the name \"{}\" for the " LOGGER.error("A page model with the name \"{}\" for the "
@ -257,6 +259,11 @@ public class PageModelManager {
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public PageModel publish(final PageModel pageModel) { public PageModel publish(final PageModel pageModel) {
Objects.requireNonNull(pageModel, "Can't publish PageModel null.");
LOGGER.debug("Publishing PageModel \"{}\"...", pageModel.getName());
final PageModel draftModel = getDraftVersion(pageModel); final PageModel draftModel = getDraftVersion(pageModel);
final PageModel liveModel; final PageModel liveModel;
@ -266,6 +273,7 @@ public class PageModelManager {
liveModel = new PageModel(); liveModel = new PageModel();
} }
liveModel.setName(draftModel.getName());
liveModel.setVersion(PageModelVersion.LIVE); liveModel.setVersion(PageModelVersion.LIVE);
liveModel.setModelUuid(draftModel.getModelUuid()); liveModel.setModelUuid(draftModel.getModelUuid());
@ -274,7 +282,7 @@ public class PageModelManager {
liveModel.getTitle().addValue(entry.getKey(), entry.getValue()); liveModel.getTitle().addValue(entry.getKey(), entry.getValue());
} }
for (Map.Entry<Locale, String> entry : liveModel.getDescription() for (Map.Entry<Locale, String> entry : draftModel.getDescription()
.getValues().entrySet()) { .getValues().entrySet()) {
liveModel.getDescription().addValue(entry.getKey(), liveModel.getDescription().addValue(entry.getKey(),
entry.getValue()); entry.getValue());
@ -283,12 +291,16 @@ public class PageModelManager {
liveModel.setApplication(draftModel.getApplication()); liveModel.setApplication(draftModel.getApplication());
liveModel.setType(draftModel.getType()); liveModel.setType(draftModel.getType());
LOGGER.debug("Publishing ComponentModels of PageModel \"{}\"...",
draftModel.getName());
liveModel.clearComponents(); liveModel.clearComponents();
for (final ComponentModel draft : draftModel.getComponents()) { for (final ComponentModel draft : draftModel.getComponents()) {
final ComponentModel live = publishComponentModel(draft); final ComponentModel live = publishComponentModel(draft);
addComponentModel(liveModel, live); addComponentModel(liveModel, live);
} }
LOGGER.debug("Successfully published PageModel \"{}\".",
liveModel.getName());
return liveModel; return liveModel;
} }
@ -304,6 +316,11 @@ public class PageModelManager {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private ComponentModel publishComponentModel(final ComponentModel draftModel) { private ComponentModel publishComponentModel(final ComponentModel draftModel) {
Objects.requireNonNull(draftModel, "Can't publish ComponentModel null.");
LOGGER.debug("Publishing ComponentModel \"{}\"...",
draftModel.getKey());
final Class<? extends ComponentModel> clazz = draftModel.getClass(); final Class<? extends ComponentModel> clazz = draftModel.getClass();
final ComponentModel liveModel; final ComponentModel liveModel;
@ -324,6 +341,12 @@ public class PageModelManager {
for (final PropertyDescriptor propertyDescriptor : beanInfo. for (final PropertyDescriptor propertyDescriptor : beanInfo.
getPropertyDescriptors()) { getPropertyDescriptors()) {
LOGGER.debug(
"Publishing property \"{}\" of ComponentModel \"{}\"...",
propertyDescriptor.getName(),
draftModel.getKey());
final Class<?> propType = propertyDescriptor.getPropertyType(); final Class<?> propType = propertyDescriptor.getPropertyType();
final Method readMethod = propertyDescriptor.getReadMethod(); final Method readMethod = propertyDescriptor.getReadMethod();
final Method writeMethod = propertyDescriptor.getWriteMethod(); final Method writeMethod = propertyDescriptor.getWriteMethod();
@ -339,18 +362,18 @@ public class PageModelManager {
if (propType != null if (propType != null
&& propType.isAssignableFrom(List.class)) { && propType.isAssignableFrom(List.class)) {
final List<Object> source;
final List<Object> target;
try { try {
source = (List<Object>) readMethod.invoke(draftModel); final List<Object> source = (List<Object>) readMethod
target = (List<Object>) readMethod.invoke(liveModel); .invoke(draftModel);
final List<Object> target = new ArrayList<>();
target.addAll(source);
writeMethod.invoke(draftModel, target);
} catch (IllegalAccessException } catch (IllegalAccessException
| IllegalArgumentException | IllegalArgumentException
| InvocationTargetException ex) { | InvocationTargetException ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
target.addAll(source);
} else if (propType != null } else if (propType != null
&& propType.isAssignableFrom(Map.class)) { && propType.isAssignableFrom(Map.class)) {
@ -399,6 +422,8 @@ public class PageModelManager {
componentModelRepo.save(liveModel); componentModelRepo.save(liveModel);
LOGGER.debug("Successfully published ComponentModel \"{}\".",
liveModel.getKey());
return liveModel; return liveModel;
} }
@ -413,6 +438,7 @@ public class PageModelManager {
*/ */
private boolean propertyIsExcluded(final String name) { private boolean propertyIsExcluded(final String name) {
final String[] excluded = new String[]{ final String[] excluded = new String[]{
"class",
"uuid", "uuid",
"modelUuid" "modelUuid"
}; };

View File

@ -27,7 +27,9 @@ import org.libreccm.web.CcmApplication;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -39,6 +41,8 @@ import java.util.UUID;
@RequestScoped @RequestScoped
public class PageModelRepository extends AbstractEntityRepository<Long, PageModel> { public class PageModelRepository extends AbstractEntityRepository<Long, PageModel> {
private static final long serialVersionUID = -7240418542790568571L;
@Override @Override
public Class<PageModel> getEntityClass() { public Class<PageModel> getEntityClass() {
return PageModel.class; return PageModel.class;
@ -46,9 +50,8 @@ public class PageModelRepository extends AbstractEntityRepository<Long, PageMode
@Override @Override
public boolean isNew(final PageModel pageModel) { public boolean isNew(final PageModel pageModel) {
if (pageModel == null) {
throw new IllegalArgumentException("PageModel can't be null."); Objects.requireNonNull(pageModel);
}
return pageModel.getPageModelId() == 0; return pageModel.getPageModelId() == 0;
} }
@ -60,9 +63,8 @@ public class PageModelRepository extends AbstractEntityRepository<Long, PageMode
*/ */
@Override @Override
public void initNewEntity(final PageModel pageModel) { public void initNewEntity(final PageModel pageModel) {
if (pageModel == null) {
throw new IllegalArgumentException("PageModel can't be null."); Objects.requireNonNull(pageModel);
}
final String uuid = UUID.randomUUID().toString(); final String uuid = UUID.randomUUID().toString();
@ -82,24 +84,57 @@ public class PageModelRepository extends AbstractEntityRepository<Long, PageMode
} }
/** /**
* Finds the draft version of all {@link PageModel}s for the provided * Find all draft versions of {@link PageModel}s.
*
* @return A list with all draft versions of {@link PageModel}s.
*/
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public List<PageModel> findAllDraftModels() {
final TypedQuery<PageModel> query = getEntityManager()
.createNamedQuery("PageModel.findAllDraftModels", PageModel.class);
return query.getResultList();
}
/**
* Find all live versions of {@link PageModel}s.
*
* @return A list with all draft versions of {@link PageModel}s.
*/
@Transactional(Transactional.TxType.REQUIRED)
public List<PageModel> findAllLiveModels() {
final TypedQuery<PageModel> query = getEntityManager()
.createNamedQuery("PageModel.findAllLiveModels", PageModel.class);
return query.getResultList();
}
/**
* Finds the draft versions of all {@link PageModel}s for the provided
* application. * application.
* *
* @param application The application for which the {@link PageModel}s are * @param application The application for which the {@link PageModel}s are
* retrieved. * retrieved.
* *
* @return A list of the {@link PageModel}s defined for the provided { * @return A list of the {@link PageModel}s defined for the provided
* * {@code application}.
* @coded application}.
*/ */
public List<PageModel> findByApplication(final CcmApplication application) { @Transactional(Transactional.TxType.REQUIRED)
if (application == null) { @AuthorizationRequired
throw new IllegalArgumentException( @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
"Can't find page models for application null"); public List<PageModel> findDraftByApplication(
} final CcmApplication application) {
final TypedQuery<PageModel> query = getEntityManager().createNamedQuery( Objects.requireNonNull(application,
"PageModel.findByApplication", PageModel.class); "Can't find page models for application null");
final TypedQuery<PageModel> query = getEntityManager()
.createNamedQuery("PageModel.findDraftByApplication",
PageModel.class);
query.setParameter("application", application); query.setParameter("application", application);
return query.getResultList(); return query.getResultList();
@ -108,20 +143,22 @@ public class PageModelRepository extends AbstractEntityRepository<Long, PageMode
/** /**
* Counts the {@link PageModel}s (draft version) defined for a application. * Counts the {@link PageModel}s (draft version) defined for a application.
* *
* @param application The application for which the {@link PageLink}s are * @param application The application for which the {@link PageModels}s are
* counted. * counted.
* *
* @return The number of {@link PageModel}s defined for the provided * @return The number of {@link PageModel}s defined for the provided
* {@code application}. * {@code application}.
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public long countByApplication(final CcmApplication application) { public long countByApplication(final CcmApplication application) {
if (application == null) {
throw new IllegalArgumentException( Objects.requireNonNull(application,
"Can't count page models for application null"); "Can't count page models for application null");
}
final TypedQuery<Long> query = getEntityManager().createNamedQuery( final TypedQuery<Long> query = getEntityManager().createNamedQuery(
"PageModel.countByApplication", Long.class); "PageModel.countDraftByApplication", Long.class);
query.setParameter("application", application); query.setParameter("application", application);
return query.getSingleResult(); return query.getSingleResult();
@ -140,27 +177,27 @@ public class PageModelRepository extends AbstractEntityRepository<Long, PageMode
* there is no {@link PageModel} matching the criteria an empty * there is no {@link PageModel} matching the criteria an empty
* {@link Optional} is returned. * {@link Optional} is returned.
*/ */
public Optional<PageModel> findByApplicationAndName( public Optional<PageModel> findDraftByApplicationAndName(
final CcmApplication application, final CcmApplication application,
final String name) { final String name) {
if (application == null) { Objects.requireNonNull(application,
throw new IllegalArgumentException( "Can't find page models for application null");
"Can't find page models for application null"); Objects.requireNonNull(name,
} "The name of a page model can't be null or empty.");
if (name == null || name.trim().isEmpty()) { if (name.isEmpty() || name.matches("\\s*")) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The name of a page model can't be null or empty."); "The name of a page model can't be null or empty.");
} }
final long count = countByApplicationAndName(application, name); final long count = countLiveByApplicationAndName(application, name);
if (count == 0) { if (count == 0) {
return Optional.empty(); return Optional.empty();
} }
final TypedQuery<PageModel> query = getEntityManager().createNamedQuery( final TypedQuery<PageModel> query = getEntityManager().createNamedQuery(
"PageModel.findByApplicationAndName", PageModel.class); "PageModel.findDraftByApplicationAndName", PageModel.class);
query.setParameter("application", application); query.setParameter("application", application);
query.setParameter("name", name); query.setParameter("name", name);
@ -178,21 +215,145 @@ public class PageModelRepository extends AbstractEntityRepository<Long, PageMode
* @return The number of {@link PageModel}s matching the criteria. Should be * @return The number of {@link PageModel}s matching the criteria. Should be
* 0 or 1. * 0 or 1.
*/ */
public long countByApplicationAndName(final CcmApplication application, @Transactional(Transactional.TxType.REQUIRED)
final String name) { @AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public long countDraftByApplicationAndName(final CcmApplication application,
final String name) {
if (application == null) { Objects.requireNonNull(application,
throw new IllegalArgumentException( "Can't find page models for application null");
"Can't count page models for application null"); Objects.requireNonNull(name,
} "The name of a page model can't be null or empty.");
if (name == null || name.trim().isEmpty()) { if (name.isEmpty() || name.matches("\\s*")) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The name of a page model can't be null or empty."); "The name of a page model can't be null or empty.");
} }
final TypedQuery<Long> query = getEntityManager().createNamedQuery( final TypedQuery<Long> query = getEntityManager().createNamedQuery(
"PageModel.countByApplicationAndName", Long.class); "PageModel.countDraftByApplicationAndName", Long.class);
query.setParameter("application", application);
query.setParameter("name", name);
return query.getSingleResult();
}
/**
* Finds the live versions of all {@link PageModel}s for the provided
* application.
*
* @param application The application for which the {@link PageModel}s are
* retrieved.
*
* @return A list of the {@link PageModel}s defined for the provided
* {@code application}.
*/
@Transactional(Transactional.TxType.REQUIRED)
public List<PageModel> findLiveByApplication(
final CcmApplication application) {
Objects.requireNonNull(application,
"Can't find page models for application null");
final TypedQuery<PageModel> query = getEntityManager()
.createNamedQuery("PageModel.findLiveByApplication",
PageModel.class);
query.setParameter("application", application);
return query.getResultList();
}
/**
* Counts the {@link PageModel}s (live version) defined for a application.
*
* @param application The application for which the {@link PageModels}s are
* counted.
*
* @return The number of {@link PageModel}s defined for the provided
* {@code application}.
*/
@Transactional(Transactional.TxType.REQUIRED)
public long countLiveByApplication(final CcmApplication application) {
Objects.requireNonNull(application,
"Can't count page models for application null");
final TypedQuery<Long> query = getEntityManager().createNamedQuery(
"PageModel.countLiveByApplication", Long.class);
query.setParameter("application", application);
return query.getSingleResult();
}
/**
* Finds a {@link PageModel} (live version) by the application and its
* {@code name}.
*
* @param application The application for which the {@link PageModel} is
* defined.
* @param name The name of the {@link PageModel}.
*
* @return An {@link Optional} containing the {@link PageModel} for the
* provided {@code application} with the provided {@code name}. If
* there is no {@link PageModel} matching the criteria an empty
* {@link Optional} is returned.
*/
@Transactional(Transactional.TxType.REQUIRED)
public Optional<PageModel> findLiveByApplicationAndName(
final CcmApplication application,
final String name) {
Objects.requireNonNull(application,
"Can't find page models for application null");
Objects.requireNonNull(name,
"The name of a page model can't be null or empty.");
if (name.isEmpty() || name.matches("\\s*")) {
throw new IllegalArgumentException(
"The name of a page model can't be null or empty.");
}
final long count = countLiveByApplicationAndName(application, name);
if (count == 0) {
return Optional.empty();
}
final TypedQuery<PageModel> query = getEntityManager().createNamedQuery(
"PageModel.findLiveByApplicationAndName", PageModel.class);
query.setParameter("application", application);
query.setParameter("name", name);
return Optional.of(query.getSingleResult());
}
/**
* Counts the number of {@link PageModel} (live version) defined for the
* provided application with the provided name.
*
* @param application The application for which the {@link PageModel} is
* defined.
* @param name The name of the {@link PageModel}.
*
* @return The number of {@link PageModel}s matching the criteria. Should be
* 0 or 1.
*/
@Transactional(Transactional.TxType.REQUIRED)
public long countLiveByApplicationAndName(final CcmApplication application,
final String name) {
Objects.requireNonNull(application,
"Can't find page models for application null");
Objects.requireNonNull(name,
"The name of a page model can't be null or empty.");
if (name.isEmpty() || name.matches("\\s*")) {
throw new IllegalArgumentException(
"The name of a page model can't be null or empty.");
}
final TypedQuery<Long> query = getEntityManager().createNamedQuery(
"PageModel.countLiveByApplicationAndName", Long.class);
query.setParameter("application", application); query.setParameter("application", application);
query.setParameter("name", name); query.setParameter("name", name);

View File

@ -48,7 +48,7 @@ class PageTreeModel implements TreeModel {
PageModelRepository.class); PageModelRepository.class);
final CcmApplication application = ((ApplicationTreeNode) node) final CcmApplication application = ((ApplicationTreeNode) node)
.getApplication(); .getApplication();
final long count = pageModelRepo.countByApplication(application); final long count = pageModelRepo.countLiveByApplication(application);
return count > 0; return count > 0;
} else if (node instanceof PageModelTreeNode) { } else if (node instanceof PageModelTreeNode) {

View File

@ -54,7 +54,7 @@ import javax.persistence.Table;
name = "Site.findDefaultSite", name = "Site.findDefaultSite",
query = "SELECT s FROM Site s " query = "SELECT s FROM Site s "
+ "WHERE s.defaultSite = true " + "WHERE s.defaultSite = true "
+ "ORDER BY s.domain" + "ORDER BY s.domainOfSite"
) )
, ,
@NamedQuery( @NamedQuery(

View File

@ -671,7 +671,7 @@ ui.admin.pagemodels.table.columns.headers.name=Name
ui.admin.pagemodels.table.columns.headers.title=Title ui.admin.pagemodels.table.columns.headers.title=Title
ui.admin.pagemodels.table.columns.headers.desc=Description ui.admin.pagemodels.table.columns.headers.desc=Description
ui.admin.pagemodels.table.columns.headers.remove=Delete ui.admin.pagemodels.table.columns.headers.remove=Delete
\ \tui.admin.pagemodels.table.columns.remove.label=Delete \ ui.admin.pagemodels.table.columns.remove.label=Delete
ui.admin.pagemodels.details.model_name=Name ui.admin.pagemodels.details.model_name=Name
ui.admin.pagemodels.details.model_title=Titel ui.admin.pagemodels.details.model_title=Titel
ui.admin.pagemodels.details.model_application=Application ui.admin.pagemodels.details.model_application=Application
@ -680,3 +680,11 @@ ui.admin.pagemodels.details.edit_properties=Edit properties
ui.admin.pagemodels.components.key.label=ID ui.admin.pagemodels.components.key.label=ID
ui.admin.pagemodels.components.key.error.not_empty=The ID of a component can't be empty. ui.admin.pagemodels.components.key.error.not_empty=The ID of a component can't be empty.
ui.admin.pagemodels.table.columns.remove.label=Delete ui.admin.pagemodels.table.columns.remove.label=Delete
ui.admin.pagemodels.details.publish=(Re-)Publish
ui.admin.users.table.filter.groupname.placeholder=Name of Group
ui.admin.users.table.filter.groupname.description=Filter groups by name
ui.admin.roles.table.description=Roles
ui.admin.users.table.filter.rolename.placeholder=Name of role
ui.admin.users.table.filter.rolename.description=Filter roles by name
ui.admin.pagemodels.table.columns.headers.islive=Is live?
ui.admin.pagemodels.select_application=Please select an application

View File

@ -675,7 +675,7 @@ ui.admin.pagemodels.table.columns.headers.name=Name
ui.admin.pagemodels.table.columns.headers.title=Titel ui.admin.pagemodels.table.columns.headers.title=Titel
ui.admin.pagemodels.table.columns.headers.desc=Description ui.admin.pagemodels.table.columns.headers.desc=Description
ui.admin.pagemodels.table.columns.headers.remove=L\u00f6schen ui.admin.pagemodels.table.columns.headers.remove=L\u00f6schen
\ \tui.admin.pagemodels.table.columns.remove.label=L\u00f6schen \ ui.admin.pagemodels.table.columns.remove.label=L\u00f6schen
ui.admin.pagemodels.details.model_name=Name ui.admin.pagemodels.details.model_name=Name
ui.admin.pagemodels.details.model_title=Titel ui.admin.pagemodels.details.model_title=Titel
ui.admin.pagemodels.details.model_application=Applikation ui.admin.pagemodels.details.model_application=Applikation
@ -684,3 +684,11 @@ ui.admin.pagemodels.details.edit_properties=Bearbeiten
ui.admin.pagemodels.components.key.label=ID ui.admin.pagemodels.components.key.label=ID
ui.admin.pagemodels.components.key.error.not_empty=Die ID einer Komponente darf nicht leer sein. ui.admin.pagemodels.components.key.error.not_empty=Die ID einer Komponente darf nicht leer sein.
ui.admin.pagemodels.table.columns.remove.label=L\u00f6schen ui.admin.pagemodels.table.columns.remove.label=L\u00f6schen
ui.admin.pagemodels.details.publish=(Re-)Publizieren
ui.admin.users.table.filter.groupname.placeholder=Name der Gruppe
ui.admin.users.table.filter.groupname.description=Gruppen anhand des Namens filtern
ui.admin.roles.table.description=Rollen
ui.admin.users.table.filter.rolename.placeholder=Name der Rolle
ui.admin.users.table.filter.rolename.description=Rollen nach Name filtern
ui.admin.pagemodels.table.columns.headers.islive=Ist publiziert?
ui.admin.pagemodels.select_application=Bitte eine Applikation ausw\u00e4hlen

View File

@ -668,7 +668,7 @@ ui.admin.pagemodels.table.columns.headers.name=Name
ui.admin.pagemodels.table.columns.headers.title=Title ui.admin.pagemodels.table.columns.headers.title=Title
ui.admin.pagemodels.table.columns.headers.desc=Description ui.admin.pagemodels.table.columns.headers.desc=Description
ui.admin.pagemodels.table.columns.headers.remove=Delete ui.admin.pagemodels.table.columns.headers.remove=Delete
\ \tui.admin.pagemodels.table.columns.remove.label=Delete \ ui.admin.pagemodels.table.columns.remove.label=Delete
ui.admin.pagemodels.details.model_name=Name ui.admin.pagemodels.details.model_name=Name
ui.admin.pagemodels.details.model_title=Titel ui.admin.pagemodels.details.model_title=Titel
ui.admin.pagemodels.details.model_application=Application ui.admin.pagemodels.details.model_application=Application
@ -677,3 +677,11 @@ ui.admin.pagemodels.details.edit_properties=Edit properties
ui.admin.pagemodels.components.key.label=ID ui.admin.pagemodels.components.key.label=ID
ui.admin.pagemodels.components.key.error.not_empty=The ID of a component can't be empty. ui.admin.pagemodels.components.key.error.not_empty=The ID of a component can't be empty.
ui.admin.pagemodels.table.columns.remove.label=Delete ui.admin.pagemodels.table.columns.remove.label=Delete
ui.admin.pagemodels.details.publish=(Re-)Publish
ui.admin.users.table.filter.groupname.placeholder=Name of Group
ui.admin.users.table.filter.groupname.description=Filter groups by name
ui.admin.roles.table.description=Roles
ui.admin.users.table.filter.rolename.placeholder=Name of role
ui.admin.users.table.filter.rolename.description=Filter roles by name
ui.admin.pagemodels.table.columns.headers.islive=Is live?
ui.admin.pagemodels.select_application=Please select an application

View File

@ -659,7 +659,7 @@ ui.admin.pagemodels.table.columns.headers.name=Name
ui.admin.pagemodels.table.columns.headers.title=Title ui.admin.pagemodels.table.columns.headers.title=Title
ui.admin.pagemodels.table.columns.headers.desc=Description ui.admin.pagemodels.table.columns.headers.desc=Description
ui.admin.pagemodels.table.columns.headers.remove=Delete ui.admin.pagemodels.table.columns.headers.remove=Delete
\ \tui.admin.pagemodels.table.columns.remove.label=Delete \ ui.admin.pagemodels.table.columns.remove.label=Delete
ui.admin.pagemodels.details.model_name=Name ui.admin.pagemodels.details.model_name=Name
ui.admin.pagemodels.details.model_title=Titel ui.admin.pagemodels.details.model_title=Titel
ui.admin.pagemodels.details.model_application=Application ui.admin.pagemodels.details.model_application=Application
@ -668,3 +668,11 @@ ui.admin.pagemodels.details.edit_properties=Edit properties
ui.admin.pagemodels.components.key.label=ID ui.admin.pagemodels.components.key.label=ID
ui.admin.pagemodels.components.key.error.not_empty=The ID of a component can't be empty. ui.admin.pagemodels.components.key.error.not_empty=The ID of a component can't be empty.
ui.admin.pagemodels.table.columns.remove.label=Delete ui.admin.pagemodels.table.columns.remove.label=Delete
ui.admin.pagemodels.details.publish=(Re-)Publish
ui.admin.users.table.filter.groupname.placeholder=Name of Group
ui.admin.users.table.filter.groupname.description=Filter groups by name
ui.admin.roles.table.description=Roles
ui.admin.users.table.filter.rolename.placeholder=Name of role
ui.admin.users.table.filter.rolename.description=Filter roles by name
ui.admin.pagemodels.table.columns.headers.islive=Is live?
ui.admin.pagemodels.select_application=Please select an application