From e00a9e42b35cf4d8c90969fc7b4bed4f47207503 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Tue, 1 Dec 2020 20:42:52 +0100 Subject: [PATCH] Theme Management via Admin UI Former-commit-id: 228691d5407c763e8f0f39e395bb108a09e7bc4b --- .../theming/FileSystemThemeProvider.java | 5 + .../libreccm/theming/StaticThemeProvider.java | 5 + .../org/libreccm/theming/ThemeProvider.java | 6 + .../java/org/libreccm/theming/Themes.java | 127 +++++++++++++ .../theming/db/DatabaseThemeProvider.java | 8 +- .../applications/ApplicationsController.java | 1 - .../admin/applications/ApplicationsPage.java | 10 +- .../SystemInformationPage.java | 3 +- .../ui/admin/themes/ThemesController.java | 117 ++++++++++++ .../libreccm/ui/admin/themes/ThemesModel.java | 126 +++++++++++++ .../libreccm/ui/admin/themes/ThemesPage.java | 82 +++++++++ .../ui/admin/themes/ThemesTableRow.java | 148 +++++++++++++++ .../org/libreccm/ui/admin/themes/themes.xhtml | 168 ++++++++++++++++++ .../org/libreccm/ui/AdminBundle.properties | 33 ++++ .../org/libreccm/ui/AdminBundle_de.properties | 33 ++++ 15 files changed, 861 insertions(+), 11 deletions(-) create mode 100644 ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesController.java create mode 100644 ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesModel.java create mode 100644 ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesPage.java create mode 100644 ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesTableRow.java create mode 100644 ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/themes/themes.xhtml diff --git a/ccm-core/src/main/java/org/libreccm/theming/FileSystemThemeProvider.java b/ccm-core/src/main/java/org/libreccm/theming/FileSystemThemeProvider.java index 7a3c1b3ce..00dde8161 100644 --- a/ccm-core/src/main/java/org/libreccm/theming/FileSystemThemeProvider.java +++ b/ccm-core/src/main/java/org/libreccm/theming/FileSystemThemeProvider.java @@ -77,6 +77,11 @@ public class FileSystemThemeProvider implements ThemeProvider { @Inject private ThemeFileInfoUtil themeFileInfoUtil; + @Override + public String getName() { + return "FileSystemThemeProvider"; + } + @Override public List getThemes() { diff --git a/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java b/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java index 3a8836b7e..ed89e5afd 100644 --- a/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java +++ b/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java @@ -80,6 +80,11 @@ public class StaticThemeProvider implements ThemeProvider { @Inject private ThemeFileInfoUtil themeFileInfoUtil; + @Override + public String getName() { + return "StaticThemeProvider"; + } + @Override public List getThemes() { diff --git a/ccm-core/src/main/java/org/libreccm/theming/ThemeProvider.java b/ccm-core/src/main/java/org/libreccm/theming/ThemeProvider.java index 451e4b683..885424340 100644 --- a/ccm-core/src/main/java/org/libreccm/theming/ThemeProvider.java +++ b/ccm-core/src/main/java/org/libreccm/theming/ThemeProvider.java @@ -36,6 +36,12 @@ import javax.enterprise.context.RequestScoped; */ public interface ThemeProvider extends Serializable { + /** + * A human readable name for the {@code ThemeProvider} implementation. + * @return + */ + String getName(); + /** * Provides a list of all themes provided by this theme provider. The list * should be ordered by the name of the theme. diff --git a/ccm-core/src/main/java/org/libreccm/theming/Themes.java b/ccm-core/src/main/java/org/libreccm/theming/Themes.java index fcf2a4eae..8601065d7 100644 --- a/ccm-core/src/main/java/org/libreccm/theming/Themes.java +++ b/ccm-core/src/main/java/org/libreccm/theming/Themes.java @@ -28,7 +28,9 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.Any; @@ -53,6 +55,7 @@ public class Themes implements Serializable { @Any private Instance providers; // + @Inject private ThemeProcessors themeProcessors; @@ -108,6 +111,100 @@ public class Themes implements Serializable { return Optional.empty(); } + public List getThemeProviders() { + return providers + .stream() + .collect(Collectors.toList()); + } + + public Optional findThemeProviderInstance( + final Class ofClazz + ) { + final Instance instance = providers + .select(ofClazz); + if (instance.isResolvable()) { + return Optional.of(instance.get()); + } else { + return Optional.empty(); + } + } + + public ThemeInfo createTheme( + final String themeName, final String providerName + ) { + final Class providerClass = getThemeProviderClass( + providerName + ); + + return createTheme( + themeName, + findThemeProviderInstance(providerClass).orElseThrow( + () -> new IllegalArgumentException( + String.format( + "No instance of ThemeProvider implementation %s available.", + providerName + ) + ) + ) + ); + } + + public ThemeInfo createTheme( + final String themeName, final ThemeProvider themeProvider + ) { + return themeProvider.createTheme(themeName); + } + + public void deleteTheme(final String themeName) { + final Optional provider = findProviderOfTheme( + Objects.requireNonNull( + themeName, + "Can't delete theme null." + ) + ); + + if (provider.isPresent()) { + provider.get().deleteTheme(themeName); + } else { + throw new IllegalArgumentException( + String.format( + "No provider providing a theme named %s found.", + themeName + ) + ); + } + } + + public void publishTheme(final String themeName) { + final Optional provider = findProviderOfTheme(themeName); + + if (provider.isPresent()) { + provider.get().publishTheme(themeName); + } else { + throw new IllegalArgumentException( + String.format( + "No provider providing a theme named %s found.", + themeName + ) + ); + } + } + + public void unpublishTheme(final String themeName) { + final Optional provider = findProviderOfTheme(themeName); + + if (provider.isPresent()) { + provider.get().unpublishTheme(themeName); + } else { + throw new IllegalArgumentException( + String.format( + "No provider providing a theme named %s found.", + themeName + ) + ); + } + } + /** * Creates HTML from the result of rendering a {@link PageModel}. * @@ -240,7 +337,37 @@ public class Themes implements Serializable { final ThemeProvider provider = forTheme.get(); provider.deleteThemeFile(theme.getName(), path); + } + @SuppressWarnings("unchecked") + private Class getThemeProviderClass( + final String providerName + ) { + try { + return (Class) Class.forName(providerName); + } catch (ClassNotFoundException ex) { + throw new IllegalArgumentException( + String.format( + "No ThemeProvider implementation %s available.", + providerName + ) + ); + } + } + + private Optional findProviderOfTheme( + final String themeName + ) { + final List providersList = new ArrayList<>(); + providers.forEach(provider -> providersList.add(provider)); + + return providersList + .stream() + .filter( + current -> current.providesTheme( + themeName, ThemeVersion.DRAFT + ) + ).findAny(); } } diff --git a/ccm-core/src/main/java/org/libreccm/theming/db/DatabaseThemeProvider.java b/ccm-core/src/main/java/org/libreccm/theming/db/DatabaseThemeProvider.java index 7f6bf54c0..bceb2da3c 100644 --- a/ccm-core/src/main/java/org/libreccm/theming/db/DatabaseThemeProvider.java +++ b/ccm-core/src/main/java/org/libreccm/theming/db/DatabaseThemeProvider.java @@ -71,6 +71,11 @@ public class DatabaseThemeProvider implements ThemeProvider { @Inject private ThemeRepository themeRepository; + @Override + public String getName() { + return "DatabaseThemeProvider"; + } + @Override @Transactional(Transactional.TxType.REQUIRED) public List getThemes() { @@ -193,7 +198,7 @@ public class DatabaseThemeProvider implements ThemeProvider { final Optional themeFile = fileRepository .findByPath(theme, path, version); - + if (themeFile.isPresent()) { return Optional.of(createThemeFileInfo(themeFile.get())); } else { @@ -419,6 +424,7 @@ public class DatabaseThemeProvider implements ThemeProvider { private class DataFileOutputStream extends OutputStream { private final DataFile dataFile; + private final ByteArrayOutputStream outputStream; private DataFileOutputStream(final DataFile dataFile) { diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/applications/ApplicationsController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/applications/ApplicationsController.java index b94ec271c..8a5f4200f 100644 --- a/ccm-core/src/main/java/org/libreccm/ui/admin/applications/ApplicationsController.java +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/applications/ApplicationsController.java @@ -35,7 +35,6 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.mvc.Controller; import javax.mvc.Models; -import javax.mvc.MvcContext; import javax.transaction.Transactional; import javax.ws.rs.GET; import javax.ws.rs.Path; diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/applications/ApplicationsPage.java b/ccm-core/src/main/java/org/libreccm/ui/admin/applications/ApplicationsPage.java index d55460afb..499a14483 100644 --- a/ccm-core/src/main/java/org/libreccm/ui/admin/applications/ApplicationsPage.java +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/applications/ApplicationsPage.java @@ -37,10 +37,6 @@ import javax.inject.Inject; */ @ApplicationScoped public class ApplicationsPage implements AdminPage { - - private static final Logger LOGGER = LogManager.getLogger( - ApplicationsPage.class - ); @Inject private ApplicationManager applicationManager; @@ -49,7 +45,7 @@ public class ApplicationsPage implements AdminPage { public Set> getControllerClasses() { final Set> classes = new HashSet<>(); classes.add(ApplicationsController.class); - + classes.addAll( applicationManager .getApplicationTypes() @@ -65,8 +61,8 @@ public class ApplicationsPage implements AdminPage { @Override public String getUriIdentifier() { return String.format( - "%s#getApplicationTypes", ApplicationsController.class - .getSimpleName() + "%s#getApplicationTypes", + ApplicationsController.class.getSimpleName() ); } diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/systeminformation/SystemInformationPage.java b/ccm-core/src/main/java/org/libreccm/ui/admin/systeminformation/SystemInformationPage.java index bacaa0888..b2fcb5a73 100644 --- a/ccm-core/src/main/java/org/libreccm/ui/admin/systeminformation/SystemInformationPage.java +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/systeminformation/SystemInformationPage.java @@ -23,7 +23,6 @@ import java.util.Set; import org.libreccm.ui.admin.AdminConstants; import org.libreccm.ui.admin.AdminPage; -import org.libreccm.ui.admin.imexport.ImExportController; import javax.enterprise.context.ApplicationScoped; @@ -76,7 +75,7 @@ public class SystemInformationPage implements AdminPage { @Override public int getPosition() { - return 70; + return 80; } } diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesController.java new file mode 100644 index 000000000..f3ed452cb --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesController.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2020 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.libreccm.ui.admin.themes; + +import org.libreccm.core.CoreConstants; +import org.libreccm.security.AuthorizationRequired; +import org.libreccm.security.RequiresPrivilege; +import org.libreccm.theming.ThemeInfo; +import org.libreccm.theming.Themes; +import org.libreccm.theming.manager.ThemeManager; +; + +import java.util.List; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.mvc.Controller; +import javax.mvc.Models; +import javax.transaction.Transactional; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +/** + * + * @author Jens Pelzetter + */ + + +@RequestScoped +@Controller +@Path("/themes") +public class ThemesController { + + @Inject + private Themes themes; + + + @Inject + private Models models; + + @GET + @Path("/") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public String getThemes() { + return "org/libreccm/ui/admin/themes/themes.xhtml"; + } + + @POST + @Path("/new") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public String createTheme( + @FormParam("themeName") final String themeName, + @FormParam("providerName") final String providerName + ) { + themes.createTheme(themeName, providerName); + + return "redirect:themes/"; + } + + @POST + @Path("/{themeName}/publish") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public String publishTheme(final String themeName) { + themes.publishTheme(themeName); + + return "redirect:themes/"; + } + + @POST + @Path("/{themeName}/unpublish") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public String unpublishTheme(final String themeName) { + themes.unpublishTheme(themeName); + + return "redirect:themes/"; + } + + @POST + @Path("/{themeName}/delete") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public String deleteTheme(@PathParam("themeName") final String themeName) { + themes.deleteTheme(themeName); + + return "redirect:themes/"; + } + + +} diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesModel.java b/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesModel.java new file mode 100644 index 000000000..fc6c32ee5 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesModel.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2020 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.libreccm.ui.admin.themes; + +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.l10n.LocalizedTextsUtil; +import org.libreccm.theming.ThemeInfo; +import org.libreccm.theming.ThemeProvider; +import org.libreccm.theming.ThemeVersion; +import org.libreccm.theming.Themes; +import org.libreccm.ui.admin.AdminConstants; + +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Any; +import javax.enterprise.inject.Instance; +import javax.inject.Inject; +import javax.inject.Named; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Named("Themes") +public class ThemesModel { + + @Inject + private GlobalizationHelper globalizationHelper; + + @Inject + private Themes themes; + + public List getThemes() { + return themes + .getAvailableThemes() + .stream() + .map(this::mapThemeInfo) + .collect(Collectors.toList()); + } + + public Map getProviderOptions() { + return themes + .getThemeProviders() + .stream() + .filter(ThemeProvider::supportsChanges) + .filter(ThemeProvider::supportsDraftThemes) + .collect( + Collectors.toMap( + provider -> provider.getClass().getName(), + provider -> provider.getName() + ) + ); + } + + private ThemesTableRow mapThemeInfo(final ThemeInfo themeInfo) { + + final LocalizedTextsUtil textsUtil = globalizationHelper + .getLocalizedTextsUtil(AdminConstants.ADMIN_BUNDLE); + + final ThemesTableRow row = new ThemesTableRow(); + row.setDescription( + Optional + .ofNullable(themeInfo.getManifest().getDescription()) + .map(ls -> globalizationHelper.getValueFromLocalizedString(ls)) + .orElse("") + ); + row.setName(themeInfo.getName()); + row.setProvider(themeInfo.getProvider().getName()); + row.setTitle( + Optional + .ofNullable(themeInfo.getManifest().getTitle()) + .map(ls -> globalizationHelper.getValueFromLocalizedString(ls)) + .orElse("") + ); + row.setType(themeInfo.getType()); + row.setVersion( + textsUtil.getText( + String.format( + "themes.versions.%s", + Objects.toString( + themeInfo.getVersion()).toLowerCase(Locale.ROOT) + ) + ) + ); + + row.setPublished(themeInfo.getVersion() == ThemeVersion.LIVE); + + final Optional themeProviderResult = themes + .findThemeProviderInstance(themeInfo.getProvider()); + if (themeProviderResult.isPresent()) { + final ThemeProvider themeProvider = themeProviderResult.get(); + + row.setEditable(themeProvider.supportsChanges()); + row.setPublishable(themeProvider.supportsDraftThemes()); + } else { + row.setEditable(false); + row.setPublishable(false); + } + + return row; + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesPage.java b/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesPage.java new file mode 100644 index 000000000..eacd43de9 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesPage.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020 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.libreccm.ui.admin.themes; + +import org.libreccm.ui.admin.AdminConstants; +import org.libreccm.ui.admin.AdminPage; + +import java.util.HashSet; +import java.util.Set; + +import javax.enterprise.context.ApplicationScoped; + +/** + * + * @author Jens Pelzetter + */ +@ApplicationScoped +public class ThemesPage implements AdminPage { + + @Override + public Set> getControllerClasses() { + final Set> classes = new HashSet<>(); + classes.add(ThemesController.class); + return classes; + } + + @Override + public String getUriIdentifier() { + return String.format( + "%s#getThemes", ThemesController.class.getSimpleName() + ); + } + + @Override + public String getLabelBundle() { + return AdminConstants.ADMIN_BUNDLE; + } + + @Override + public String getLabelKey() { + return "themes.label"; + } + + @Override + public String getDescriptionBundle() { + return AdminConstants.ADMIN_BUNDLE; + } + + @Override + public String getDescriptionKey() { + return "themes.description"; + } + + @Override + public String getIcon() { + return "brush-fill"; + } + + @Override + public int getPosition() { + return 70; + } + + + +} diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesTableRow.java b/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesTableRow.java new file mode 100644 index 000000000..b0b523a58 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/themes/ThemesTableRow.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2020 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.libreccm.ui.admin.themes; + +import org.libreccm.theming.ThemeVersion; + +import java.io.Serializable; +import java.util.Comparator; + +/** + * + * @author Jens Pelzetter + */ +public class ThemesTableRow implements Comparable, Serializable { + + private static final long serialVersionUID = 1L; + + private String name; + + private String type; + + private ThemeVersion themeVersion; + + private String version; + + private String provider; + + private String title; + + private String description; + + private boolean editable; + + private boolean publishable; + + private boolean published; + + public String getName() { + return name; + } + + protected void setName(final String name) { + this.name = name; + } + + public ThemeVersion getThemeVersion() { + return themeVersion; + } + + protected void setThemeVersion(final ThemeVersion themeVersion) { + this.themeVersion = themeVersion; + } + + public String getType() { + return type; + } + + protected void setType(final String type) { + this.type = type; + } + + public String getVersion() { + return version; + } + + protected void setVersion(final String version) { + this.version = version; + } + + public String getProvider() { + return provider; + } + + protected void setProvider(final String provider) { + this.provider = provider; + } + + public String getTitle() { + return title; + } + + protected void setTitle(final String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + protected void setDescription(final String description) { + this.description = description; + } + + public boolean isEditable() { + return editable; + } + + protected void setEditable(final boolean editable) { + this.editable = editable; + } + + public boolean isPublishable() { + return publishable; + } + + protected void setPublishable(final boolean publishable) { + this.publishable = publishable; + } + + public boolean isPublished() { + return published; + } + + protected void setPublished(final boolean published) { + this.published = published; + } + + @Override + public int compareTo(final ThemesTableRow other) { + return Comparator.nullsFirst(Comparator + .comparing(ThemesTableRow::getTitle) + .thenComparing(ThemesTableRow::getName) + .thenComparing(ThemesTableRow::getVersion) + .thenComparing(ThemesTableRow::getType) + .thenComparing(ThemesTableRow::getProvider) + .thenComparing(ThemesTableRow::isPublishable) + .thenComparing(ThemesTableRow::isPublished) + .thenComparing(ThemesTableRow::isEditable) + ).compare(this, other); + } + +} diff --git a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/themes/themes.xhtml b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/themes/themes.xhtml new file mode 100644 index 000000000..c14dd1ee0 --- /dev/null +++ b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/themes/themes.xhtml @@ -0,0 +1,168 @@ +]> + + + + + + + + + + + +
+

#{AdminMessages['themes.label']}

+ + + +

#{AdminMessages['themes.dialog.new_theme.title']}

+
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
#{AdminMessages['themes.table.headers.name']}#{AdminMessages['themes.table.headers.title']}#{AdminMessages['themes.table.headers.version']}#{AdminMessages['themes.table.headers.type']}#{AdminMessages['themes.table.headers.provider']}#{AdminMessages['themes.table.headers.actions']}
#{theme.name}#{theme.title}#{theme.version}#{theme.type}#{theme.provider} + + + + + + + +
+ +
+
+ +
+ +
+
+
+
+ + + + + + + +
+
+
+ +
+ \ No newline at end of file diff --git a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties index 7bf9becf9..ca1a32d5b 100644 --- a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties +++ b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties @@ -493,3 +493,36 @@ sites.form.buttons.save=Save applications.types.singleton=Singleton applications.number_of_instances={0} instances applications.number_of_instances_one={0} instance +themes.label=Themes +themes.description=Manage themes +themes.table.headers.name=Name +themes.table.headers.title=Title +themes.table.headers.version=Version +themes.table.headers.type=Type +themes.table.headers.provider=Provided by +themes.table.actions.republish=Republish +themes.table.actions.publish=Publish +themes.table.actions.unpublish=Unpublish +themes.table.actions.delete=Delete +themes.versions.live=Live +themes.versions.draft=Draft +themes.table.headers.actions=Actions +themes.dialog.description.title=Description of theme {0} +themes.dialog.description.close=Close +themes.table.description.show=Show description of theme {0} +themes.create_new_theme=Create new theme +themes.dialog.new_theme.title=Create new theme +themes.dialog.new_theme.close=Cancel +themes.dialog.new_theme.create=Create new theme +themes.dialog.new_theme.name.help=Unique name of the new theme +themes.dialog.new_theme.name.label=Name +themes.dialog.new_theme.provider.help=The provider which manages the theme. +themes.dialog.new_theme.provider.label=Provider +themes.table.actions.unpublish.cancel=Cancel +themes.table.actions.unpublish.confirm=Unpublish theme +themes.table.actions.unpublish.title=Confirm to unpublish theme +themes.table.actions.unpublish.message=Are your sure to unpublish theme {0}? +themes.table.actions.delete.cancel=Cancel +themes.table.actions.delete.confirm=Delete theme +themes.table.actions.delete.title=Confirm theme deletion +themes.table.actions.delete.message=Are you sure to delete the theme {0}? diff --git a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties index 3829640f5..e82e6aa5c 100644 --- a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties +++ b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties @@ -493,3 +493,36 @@ sites.form.buttons.save=Speichern applications.types.singleton=Singleton applications.number_of_instances={0} Instanzen applications.number_of_instances_one={0} instance +themes.label=Themes +themes.description=Themes verwalten +themes.table.headers.name=Name +themes.table.headers.title=Titel +themes.table.headers.version=Version +themes.table.headers.type=Typ +themes.table.headers.provider=Bereitgestellt durch +themes.table.actions.republish=Republizieren +themes.table.actions.publish=Publizieren +themes.table.actions.unpublish=Depublizieren +themes.table.actions.delete=L\u00f6schen +themes.versions.live=Live +themes.versions.draft=Draft +themes.table.headers.actions=Aktionen +themes.dialog.description.title=Beschreibung Theme {0} +themes.dialog.description.close=Schlie\u00dfen +themes.table.description.show=Beschreibung des Themes {0} anzeigen +themes.create_new_theme=Neues Theme anlegen +themes.dialog.new_theme.title=Neues Theme anlegen +themes.dialog.new_theme.close=Abbrechen +themes.dialog.new_theme.create=Neues Theme anlegen +themes.dialog.new_theme.name.help=Eindeutiger Name des neuen Themes +themes.dialog.new_theme.name.label=Name +themes.dialog.new_theme.provider.help=Der Provider, \u00fcber den das Theme verwaltet wird. +themes.dialog.new_theme.provider.label=Provider +themes.table.actions.unpublish.cancel=Abbrechen +themes.table.actions.unpublish.confirm=Theme depublizieren +themes.table.actions.unpublish.title=Depublizieren des Themes best\u00e4tigen +themes.table.actions.unpublish.message=Sind Sie sicher, dass Sie das Theme {0} depublizieren wollen? +themes.table.actions.delete.cancel=Abbrechen +themes.table.actions.delete.confirm=Theme l\u00f6schen +themes.table.actions.delete.title=L\u00f6schen des Themes best\u00e4tigen +themes.table.actions.delete.message=Sind Sie sicher, dass Sie das Theme {0} l\u00f6schen wollen?