MVC based UI for Content Section management
parent
7a630d0258
commit
dd8d8d1aac
|
|
@ -62,12 +62,14 @@ import static org.librecms.CmsConstants.*;
|
|||
@NamedQueries({
|
||||
@NamedQuery(
|
||||
name = "ContentSection.findById",
|
||||
query = "SELECT S FROM ContentSection s WHERE s.objectId = :objectId")
|
||||
,
|
||||
query = "SELECT s FROM ContentSection s WHERE s.objectId = :objectId"),
|
||||
@NamedQuery(
|
||||
name = "ContentSection.findByUuid",
|
||||
query = "SELECT s FROM ContentSection s WHERE s.uuid = :uuid"
|
||||
),
|
||||
@NamedQuery(
|
||||
name = "ContentSection.findByLabel",
|
||||
query = "SELECT s FROM ContentSection s WHERE s.label = :label")
|
||||
,
|
||||
query = "SELECT s FROM ContentSection s WHERE s.label = :label"),
|
||||
@NamedQuery(
|
||||
name = "ContentSection.findUsableContentTypes",
|
||||
query = "SELECT t FROM ContentType t "
|
||||
|
|
@ -77,8 +79,7 @@ import static org.librecms.CmsConstants.*;
|
|||
+ "WHERE p.grantedPrivilege = '"
|
||||
+ TypePrivileges.USE_TYPE + "' "
|
||||
+ "AND p.grantee in :roles) "
|
||||
+ "OR true = :isSysAdmin)")
|
||||
,
|
||||
+ "OR true = :isSysAdmin)"),
|
||||
@NamedQuery(
|
||||
name = "ContentSection.countUsableContentTypes",
|
||||
query = "SELECT COUNT(t) FROM ContentType t "
|
||||
|
|
@ -88,8 +89,7 @@ import static org.librecms.CmsConstants.*;
|
|||
+ "WHERE p.grantedPrivilege = '"
|
||||
+ TypePrivileges.USE_TYPE + "' "
|
||||
+ "AND p.grantee IN :roles) "
|
||||
+ "OR true = :isSysAdmin)")
|
||||
,
|
||||
+ "OR true = :isSysAdmin)"),
|
||||
@NamedQuery(
|
||||
name = "ContentSection.hasUsableContentTypes",
|
||||
query = "SELECT (CASE WHEN COUNT(t) > 0 THEN true ELSE false END)"
|
||||
|
|
@ -100,8 +100,7 @@ import static org.librecms.CmsConstants.*;
|
|||
+ "WHERE p.grantedPrivilege = '"
|
||||
+ TypePrivileges.USE_TYPE + "' "
|
||||
+ "AND p.grantee IN :roles) "
|
||||
+ "OR true = :isSysAdmin)")
|
||||
,
|
||||
+ "OR true = :isSysAdmin)"),
|
||||
@NamedQuery(
|
||||
name = "ContentSection.findPermissions",
|
||||
query = "SELECT p FROM Permission p "
|
||||
|
|
@ -124,12 +123,19 @@ public class ContentSection
|
|||
private static final long serialVersionUID = -671718122153931727L;
|
||||
|
||||
protected static final String ROOT = "root";
|
||||
|
||||
protected static final String ASSETS = "assets";
|
||||
|
||||
protected static final String ALERT_RECIPIENT = "alert_recipient";
|
||||
|
||||
protected static final String AUTHOR = "author";
|
||||
|
||||
protected static final String EDITOR = "editor";
|
||||
|
||||
protected static final String MANAGER = "manager";
|
||||
|
||||
protected static final String PUBLISHER = "publisher";
|
||||
|
||||
protected static final String CONTENT_READER = "content_reader";
|
||||
|
||||
@Column(name = "LABEL", length = 512)
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ import org.librecms.contentsection.privileges.TypePrivileges;
|
|||
import org.librecms.dispatcher.ItemResolver;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.enterprise.inject.Instance;
|
||||
|
||||
|
|
@ -77,6 +79,9 @@ public class ContentSectionManager {
|
|||
@Inject
|
||||
private CategoryRepository categoryRepo;
|
||||
|
||||
@Inject
|
||||
private FolderRepository folderRepository;
|
||||
|
||||
@Inject
|
||||
private RoleRepository roleRepo;
|
||||
|
||||
|
|
@ -462,7 +467,7 @@ public class ContentSectionManager {
|
|||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<ItemResolver> itemResolverClazz
|
||||
= (Class<ItemResolver>) Class.
|
||||
= (Class<ItemResolver>) Class.
|
||||
forName(section.getItemResolverClass());
|
||||
|
||||
final Instance<ItemResolver> instance = itemResolvers.select(
|
||||
|
|
@ -664,4 +669,41 @@ public class ContentSectionManager {
|
|||
typeRepo.delete(contentType.get());
|
||||
}
|
||||
|
||||
@AuthorizationRequired
|
||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public void deleteContentSection(final ContentSection section) {
|
||||
Objects.requireNonNull(section);
|
||||
|
||||
try {
|
||||
for (final ContentType type : section.getContentTypes()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<? extends ContentItem> clazz
|
||||
= (Class<? extends ContentItem>) Class.forName(
|
||||
type.getContentItemClass()
|
||||
);
|
||||
removeContentTypeFromSection(clazz, section);
|
||||
}
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
for (final LifecycleDefinition lifecycle : section
|
||||
.getLifecycleDefinitions()) {
|
||||
removeLifecycleDefinitionFromContentSection(
|
||||
lifecycle, section
|
||||
);
|
||||
}
|
||||
for (final Role role : section.getRoles()) {
|
||||
removeRoleFromContentSection(section, role);
|
||||
}
|
||||
for (final Workflow workflow : section.getWorkflowTemplates()) {
|
||||
removeWorkflowTemplateFromContentSection(workflow, section);
|
||||
}
|
||||
|
||||
folderRepository.delete(section.getRootAssetsFolder());
|
||||
folderRepository.delete(section.getRootDocumentsFolder());
|
||||
|
||||
sectionRepo.delete(section);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,22 @@ public class ContentSectionRepository
|
|||
|
||||
private static final long serialVersionUID = 4616599498399330865L;
|
||||
|
||||
public Optional<ContentSection> findByUuid(final String uuid) {
|
||||
try {
|
||||
return Optional.of(
|
||||
getEntityManager()
|
||||
.createNamedQuery(
|
||||
"ContentSection.findByUuid",
|
||||
ContentSection.class
|
||||
)
|
||||
.setParameter("uuid", uuid)
|
||||
.getSingleResult()
|
||||
);
|
||||
} catch (NoResultException ex) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<ContentSection> findByLabel(final String label) {
|
||||
if (label == null || label.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
|
|
|
|||
|
|
@ -5,20 +5,33 @@
|
|||
*/
|
||||
package org.librecms.ui;
|
||||
|
||||
import org.libreccm.api.Identifier;
|
||||
import org.libreccm.api.IdentifierParser;
|
||||
import org.libreccm.core.CoreConstants;
|
||||
import org.libreccm.security.AuthorizationRequired;
|
||||
import org.libreccm.security.PermissionChecker;
|
||||
import org.libreccm.security.RequiresPrivilege;
|
||||
import org.libreccm.security.Shiro;
|
||||
import org.librecms.contentsection.ContentSection;
|
||||
import org.librecms.contentsection.ContentSectionManager;
|
||||
import org.librecms.contentsection.ContentSectionRepository;
|
||||
import org.librecms.contentsection.Folder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.mvc.Controller;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.transaction.Transactional;
|
||||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
|
|
@ -34,11 +47,17 @@ public class ContentSectionsController {
|
|||
@Inject
|
||||
private ContentSectionRepository sectionRepo;
|
||||
|
||||
@Inject
|
||||
private ContentSectionManager sectionManager;
|
||||
|
||||
@Inject
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Inject
|
||||
private ServletContext servletContext;
|
||||
private IdentifierParser identifierParser;
|
||||
|
||||
@Inject
|
||||
private PermissionChecker permissionChecker;
|
||||
|
||||
@GET
|
||||
@Path("/")
|
||||
|
|
@ -98,10 +117,123 @@ public class ContentSectionsController {
|
|||
|
||||
@POST
|
||||
@Path("/new")
|
||||
public String createContentSection() {
|
||||
throw new WebApplicationException(
|
||||
Response.status(Response.Status.NOT_FOUND).build()
|
||||
@AuthorizationRequired
|
||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public String createContentSection(
|
||||
@FormParam("sectionName") final String sectionName
|
||||
) {
|
||||
sectionManager.createContentSection(sectionName);
|
||||
|
||||
return "redirect:/list";
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{sectionIdentifier}/rename")
|
||||
@AuthorizationRequired
|
||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public String renameContentSection(
|
||||
@PathParam("sectionIdentifier") final String identifierParam,
|
||||
@FormParam("sectionName") final String sectionName
|
||||
) {
|
||||
final ContentSection section = findContentSection(identifierParam);
|
||||
|
||||
sectionManager.renameContentSection(section, sectionName);
|
||||
|
||||
return "redirect:list";
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{sectionIdentifier}/delete")
|
||||
@AuthorizationRequired
|
||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public String deleteContentSection(
|
||||
@PathParam("sectionIdentifier") final String identifierParam,
|
||||
@FormParam("confirmed") final String confirmed
|
||||
) {
|
||||
if (Objects.equals(confirmed, "true")) {
|
||||
final ContentSection section = findContentSection(identifierParam);
|
||||
|
||||
if (!canDelete(section)) {
|
||||
throw new WebApplicationException(
|
||||
String.format(
|
||||
"ContentSection %s is not empty and can't be deleted.",
|
||||
section.getLabel()
|
||||
),
|
||||
Response.Status.BAD_REQUEST
|
||||
);
|
||||
}
|
||||
|
||||
sectionManager.deleteContentSection(section);
|
||||
}
|
||||
|
||||
return "redirect:/list";
|
||||
}
|
||||
|
||||
private ContentSection findContentSection(final String identifierParam) {
|
||||
final Identifier identifier = identifierParser.parseIdentifier(
|
||||
identifierParam
|
||||
);
|
||||
|
||||
final ContentSection section;
|
||||
switch (identifier.getType()) {
|
||||
case ID:
|
||||
section = sectionRepo.findById(
|
||||
Long.parseLong(identifier.getIdentifier())
|
||||
).orElseThrow(
|
||||
() -> new WebApplicationException(
|
||||
String.format(
|
||||
"No ContentSection identified by ID %s "
|
||||
+ "available.",
|
||||
identifierParam
|
||||
),
|
||||
Response.Status.NOT_FOUND
|
||||
)
|
||||
);
|
||||
break;
|
||||
case UUID:
|
||||
section = sectionRepo
|
||||
.findByUuid(identifier.getIdentifier())
|
||||
.orElseThrow(
|
||||
() -> new WebApplicationException(
|
||||
String.format(
|
||||
"No ContentSection identifed UUID %s "
|
||||
+ "available.",
|
||||
identifierParam
|
||||
),
|
||||
Response.Status.NOT_FOUND
|
||||
)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
section = sectionRepo
|
||||
.findByLabel(identifier.getIdentifier())
|
||||
.orElseThrow(
|
||||
() -> new WebApplicationException(
|
||||
String.format(
|
||||
"No ContentSection with name %s "
|
||||
+ "available.",
|
||||
identifierParam
|
||||
),
|
||||
Response.Status.NOT_FOUND
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
protected boolean canDelete(final ContentSection section) {
|
||||
final Folder rootAssetsFolder = section.getRootAssetsFolder();
|
||||
final Folder rootDocumentsFolder = section.getRootDocumentsFolder();
|
||||
|
||||
return rootAssetsFolder.getSubFolders().isEmpty()
|
||||
&& rootAssetsFolder.getObjects().isEmpty()
|
||||
&& rootDocumentsFolder.getSubFolders().isEmpty()
|
||||
&& rootDocumentsFolder.getObjects().isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,14 @@ import javax.transaction.Transactional;
|
|||
@Named("ContentSectionsTableModel")
|
||||
public class ContentSectionsTableModel {
|
||||
|
||||
@Inject
|
||||
private ContentSectionsController controller;
|
||||
|
||||
@Inject
|
||||
private ContentSectionRepository sectionRepo;
|
||||
|
||||
|
||||
|
||||
@AuthorizationRequired
|
||||
@Transactional
|
||||
public List<ContentSectionsTableRow> getContentSections() {
|
||||
|
|
@ -59,6 +64,7 @@ public class ContentSectionsTableModel {
|
|||
|
||||
row.setSectionId(section.getObjectId());
|
||||
row.setLabel(section.getLabel());
|
||||
row.setDeletable(controller.canDelete(section));
|
||||
|
||||
return row;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ public class ContentSectionsTableRow implements
|
|||
|
||||
private String label;
|
||||
|
||||
private boolean deletable;
|
||||
|
||||
public long getSectionId() {
|
||||
return sectionId;
|
||||
}
|
||||
|
|
@ -47,6 +49,14 @@ public class ContentSectionsTableRow implements
|
|||
this.label = label;
|
||||
}
|
||||
|
||||
public boolean isDeletable() {
|
||||
return deletable;
|
||||
}
|
||||
|
||||
public void setDeletable(boolean deletable) {
|
||||
this.deletable = deletable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final ContentSectionsTableRow other) {
|
||||
int result;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:bootstrap="http://xmlns.jcp.org/jsf/composite/components/bootstrap"
|
||||
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
|
||||
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-sections/content-sections.xhtml">
|
||||
|
||||
|
|
@ -19,11 +19,6 @@
|
|||
|
||||
<c:if test="#{UserInfo.admin}">
|
||||
<div class="text-right mb-2">
|
||||
<!-- <a class="btn btn-secondary"
|
||||
href="#{mvc.basePath}/new">
|
||||
<bootstrap:svgIcon icon="plus-circle" />
|
||||
<span>#{CmsAdminMessages['contentsections.list.add']}</span>
|
||||
</a>-->
|
||||
<button class="btn btn-secondary"
|
||||
data-toggle="modal"
|
||||
data-target="#new-content-section-dialog"
|
||||
|
|
@ -61,7 +56,7 @@
|
|||
<input aria-describedby="contentsection-name-help"
|
||||
class="form-control"
|
||||
id="content-section-name"
|
||||
name="contentSectionName"
|
||||
name="sectionName"
|
||||
pattern="^([a-z0-9-_]*)$"
|
||||
type="text"
|
||||
value="" />
|
||||
|
|
@ -86,13 +81,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</c:if>
|
||||
<table class="table table-hover">
|
||||
<table class="table table-hover contentsections-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th>
|
||||
#{CmsAdminMessages['contentsections.list.table.headers.label']}
|
||||
</th>
|
||||
<th class="text-center">#{CmsAdminMessages['contentsections.list.table.headers.actions']}</th>
|
||||
<th class="action-col text-center"
|
||||
colspan="2">#{CmsAdminMessages['contentsections.list.table.headers.actions']}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -100,16 +96,82 @@
|
|||
var="section">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#{mvc.basePath}/#{section.label}/contentitems">
|
||||
<a href="#{mvc.basePath}/#{section.label}/items">
|
||||
#{section.label}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a class="btn btn-info"
|
||||
href="#{mvc.basePath}/#{section.label}/details">
|
||||
<bootstrap:svgIcon icon="eye"/>
|
||||
#{CmsAdminMessages['contentsections.list.table.actions.show_details']}
|
||||
</a>
|
||||
<td class="action-col">
|
||||
<button class="btn btn-secondary"
|
||||
data-toggle="modal"
|
||||
data-target="#content-section-#{section.label}-edit-dialog"
|
||||
type="button">
|
||||
<bootstrap:svgIcon icon="plus-circle" />
|
||||
<span>#{CmsAdminMessages['contentsections.list.table.actions.edit']}</span>
|
||||
</button>
|
||||
<div aria-hidden="true"
|
||||
aria-labelledby="content-section-#{section.label}-edit-dialog-title"
|
||||
class="modal fade"
|
||||
id="content-section-#{section.label}-edit-dialog"
|
||||
tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<form action="#{mvc.basePath}/#{section.label}/rename"
|
||||
class="modal-content"
|
||||
method="post">
|
||||
<div class="modal-header">
|
||||
<h2 class="modal-title"
|
||||
id="content-section-#{section.label}-edit-dialog-title">
|
||||
#{CmsAdminMessages['contentsections.edit_dialog.title']}
|
||||
</h2>
|
||||
<button aria-label="#{CmsAdminMessages['contentsections.edit_dialog.close']}"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
type="button">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="contentsection-name">
|
||||
#{CmsAdminMessages['contentsections.edit_dialog.name.label']}
|
||||
</label>
|
||||
<input aria-describedby="contentsection-#{section.label}-name-help"
|
||||
class="form-control"
|
||||
id="content-section-#{section.label}-name"
|
||||
name="sectionName"
|
||||
pattern="^([a-z0-9-_]*)$"
|
||||
type="text"
|
||||
value="#{section.label}" />
|
||||
<small class="form-text text-muted"
|
||||
id="contentsection-name-help">
|
||||
#{CmsAdminMessages['contentsections.edit_dialog.name.help']}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-danger"
|
||||
data-dismiss="modal"
|
||||
type="button">
|
||||
#{CmsAdminMessages['contentsections.edit_dialog.close']}
|
||||
</button>
|
||||
<button class="btn btn-success"
|
||||
type="submit">
|
||||
#{CmsAdminMessages['contentsections.edit_dialog.save']}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="action-col">
|
||||
<c:if test="#{section.deletable}">
|
||||
<libreccm:deleteDialog actionTarget="#{mvc.basePath}/#{section.label}/delete"
|
||||
buttonText="#{CmsAdminMessages['contentsections.list.table.actions.delete']}"
|
||||
cancelLabel="#{CmsAdminMessages['contentsections.delete_dialog.close']}"
|
||||
confirmLabel="#{CmsAdminMessages['contentsections.delete_dialog.confirm']}"
|
||||
dialogId="delete-content-section-#{section.label}-dialog"
|
||||
dialogTitle="#{CmsAdminMessages.getMessage('contentsections.delete_dialog.title', [section.label])}"
|
||||
message="#{CmsAdminMessages.getMessage('contentsections.delete_dialog.message', [section.label])}" />
|
||||
</c:if>
|
||||
</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
|
|
|
|||
|
|
@ -13,3 +13,14 @@ contentsections.new_dialog.close=Cancel
|
|||
contentsections.new_dialog.save=Create new content section
|
||||
contentsections.new_dialog.name.label=Name
|
||||
contentsections.new_dialog.name.help=The name of the new content section. Can only contain the letters a to z, the numbers 0-9, the hyphen and the underscore.
|
||||
contentsections.list.table.actions.edit=Rename
|
||||
contentsections.list.table.actions.delete=Delete
|
||||
contentsections.delete_dialog.close=Cancel
|
||||
contentsections.delete_dialog.confirm=Delete
|
||||
contentsections.delete_dialog.title=Delete Content Section {0}
|
||||
contentsections.delete_dialog.message=Are you sure to delete content section {0}?
|
||||
contentsections.edit_dialog.title=Rename content section
|
||||
contentsections.edit_dialog.close=Cancel
|
||||
contentsections.edit_dialog.name.label=Name
|
||||
contentsections.edit_dialog.save=Rename content section
|
||||
contentsections.edit_dialog.name.help=The name of the content section. Can only contain the letters a to z, the numbers 0-9, the hyphen and the underscore.
|
||||
|
|
|
|||
|
|
@ -13,3 +13,14 @@ contentsections.new_dialog.close=Abbrechen
|
|||
contentsections.new_dialog.save=Neue Content Section anlegen
|
||||
contentsections.new_dialog.name.label=Name
|
||||
contentsections.new_dialog.name.help=Der Name der neuen Content Section. Darf nur die Zeichen a bis z, 0-9, the Bindestrich und den Unterstrich enthalten.
|
||||
contentsections.list.table.actions.edit=Umbenennen
|
||||
contentsections.list.table.actions.delete=L\u00f6schen
|
||||
contentsections.delete_dialog.close=Abbrechen
|
||||
contentsections.delete_dialog.confirm=L\u00f6schen
|
||||
contentsections.delete_dialog.title=Content Section {0} l\u00f6schen
|
||||
contentsections.delete_dialog.message=Wollen Sie die Content Section {0} wirklich l\u00f6schen?
|
||||
contentsections.edit_dialog.title=Content Section umbennen
|
||||
contentsections.edit_dialog.close=Abbrechen
|
||||
contentsections.edit_dialog.name.label=Name
|
||||
contentsections.edit_dialog.save=Content Section umbenennen
|
||||
contentsections.edit_dialog.name.help=Der Name der Content Section. Darf nur die Zeichen a bis z, 0-9, the Bindestrich und den Unterstrich enthalten.
|
||||
|
|
|
|||
|
|
@ -37,3 +37,11 @@ $pre-scrollable-max-height: 21.25rem;
|
|||
|
||||
// Navbar default colors have insufficient contrast
|
||||
$navbar-dark-color: #fff;
|
||||
|
||||
table.contentsections-table {
|
||||
tbody {
|
||||
td.action-col {
|
||||
width: 11em;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue