Infrastructure for assets UI
parent
59dac810ac
commit
cf79f39a7a
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.libreccm.l10n.GlobalizationHelper;
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
import org.librecms.contentsection.Folder;
|
||||||
|
import org.librecms.contentsection.FolderManager;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public abstract class AbstractMvcAssetCreateStep<T extends Asset>
|
||||||
|
implements MvcAssetCreateStep<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides operations for folders.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private FolderManager folderManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides functions for working with {@link LocalizedString}s.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private GlobalizationHelper globalizationHelper;
|
||||||
|
|
||||||
|
private boolean canCreate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current folder.
|
||||||
|
*/
|
||||||
|
private Folder folder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current content section.
|
||||||
|
*/
|
||||||
|
private ContentSection section;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Messages to be shown to the user.
|
||||||
|
*/
|
||||||
|
private SortedMap<String, String> messages;
|
||||||
|
|
||||||
|
public AbstractMvcAssetCreateStep() {
|
||||||
|
messages = new TreeMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getAvailableLocales() {
|
||||||
|
return globalizationHelper
|
||||||
|
.getAvailableLocales()
|
||||||
|
.stream()
|
||||||
|
.collect(
|
||||||
|
Collectors.toMap(
|
||||||
|
locale -> locale.toString(),
|
||||||
|
locale -> locale.toString(),
|
||||||
|
(value1, value2) -> value1,
|
||||||
|
() -> new LinkedHashMap<String, String>()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
@Override
|
||||||
|
public ContentSection getContentSection() {
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
@Override
|
||||||
|
public void setContentSection(final ContentSection section) {
|
||||||
|
this.section = section;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
@Override
|
||||||
|
public String getContentSectionLabel() {
|
||||||
|
return section.getLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
@Override
|
||||||
|
public String getContentSectionTitle() {
|
||||||
|
return globalizationHelper.getValueFromLocalizedString(
|
||||||
|
section.getTitle()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCanCreate() {
|
||||||
|
return canCreate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Folder getFolder() {
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFolder(final Folder folder) {
|
||||||
|
this.folder = folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFolderPath() {
|
||||||
|
if (folder.getParentFolder() == null) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return folderManager.getFolderPath(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getMessages() {
|
||||||
|
return Collections.unmodifiableSortedMap(messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMessage(final String context, final String message) {
|
||||||
|
messages.put(context, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessages(final SortedMap<String, String> messages) {
|
||||||
|
this.messages = new TreeMap<>(messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.enterprise.context.Dependent;
|
||||||
|
import javax.mvc.Controller;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@Dependent
|
||||||
|
public class AssetEditStepsValidator {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(
|
||||||
|
AssetEditStepsValidator.class
|
||||||
|
);
|
||||||
|
|
||||||
|
public boolean validateEditStep(final Class<?> stepClass) {
|
||||||
|
if (stepClass.getAnnotation(Controller.class) == null) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Class {} is part of a set of asset edit steps, but is not"
|
||||||
|
+ " annotated with {}. The class will be ignored.",
|
||||||
|
stepClass.getName(),
|
||||||
|
Controller.class.getName()
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Path pathAnnotation = stepClass.getAnnotation(Path.class);
|
||||||
|
if (pathAnnotation == null) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Class {} is part of a set of asset edit steps, but is not "
|
||||||
|
+ "annotated with {}. the class will be ignored.",
|
||||||
|
stepClass.getName(),
|
||||||
|
Path.class.getName()
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String path = pathAnnotation.value();
|
||||||
|
if (path == null
|
||||||
|
|| !path.startsWith(MvcAssetEditSteps.PATH_PREFIX)) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Class {} is part of a set of asset edit steps, but the value"
|
||||||
|
+ "of the {} annotation of the class does not start "
|
||||||
|
+ "with {}. The class will be ignored.",
|
||||||
|
stepClass.getName(),
|
||||||
|
Path.class.getName(),
|
||||||
|
MvcAssetEditSteps.PATH_PREFIX
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stepClass.getAnnotation(MvcAssetEditStep.class) == null) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Class {} is part of a set of asset edit steps, but is not "
|
||||||
|
+ "annotated with {}. The class will be ignored.",
|
||||||
|
stepClass.getName(),
|
||||||
|
MvcAssetEditStep.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsAsset(final Class<?> stepClass, final Asset asset) {
|
||||||
|
return Optional
|
||||||
|
.ofNullable(stepClass.getAnnotation(MvcAssetEditStep.class))
|
||||||
|
.map(
|
||||||
|
stepAnnotation -> asset.getClass().isAssignableFrom(
|
||||||
|
stepAnnotation.supportedAssetType()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.orElse(false);
|
||||||
|
|
||||||
|
// final MvcAssetEditStep stepAnnotation = stepClass.getAnnotation(
|
||||||
|
// MvcAssetEditStep.class
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// if (stepAnnotation == null) {
|
||||||
|
// return false;
|
||||||
|
// } else {
|
||||||
|
// return asset.getClass().isAssignableFrom(
|
||||||
|
// stepAnnotation.supportedAssetType());
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.libreccm.ui.AbstractMessagesBean;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
@Named("CmsAssetsStepsDefaultMessagesBundle")
|
||||||
|
public class AssetStepsDefaultMessagesBundle extends AbstractMessagesBean {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessageBundle() {
|
||||||
|
return MvcAssetStepsConstants.BUNDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
import org.librecms.contentsection.AssetManager;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.mvc.Models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
public class AssetUi {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssetManager assetManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to provide data for the views without a named bean.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private Models models;
|
||||||
|
|
||||||
|
public String showAccessDenied(
|
||||||
|
final ContentSection section,
|
||||||
|
final Asset asset,
|
||||||
|
final String step
|
||||||
|
) {
|
||||||
|
return showAccessDenied(
|
||||||
|
section, assetManager.getAssetPath(asset), step
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String showAccessDenied(
|
||||||
|
final ContentSection section, final String assetPath, final String step
|
||||||
|
) {
|
||||||
|
models.put("section", section.getLabel());
|
||||||
|
models.put("assetPath", assetPath);
|
||||||
|
models.put(step, step);
|
||||||
|
return "org/librecms/ui/contentsections/assets/access-denied.xhtml";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String showAssetNotFound(
|
||||||
|
final ContentSection section, final String assetPath
|
||||||
|
) {
|
||||||
|
models.put("section", section.getLabel());
|
||||||
|
models.put("assetPath", assetPath);
|
||||||
|
return "/org/librecms/ui/contentsections/assets/asset-not-found.xhtml";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,503 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.libreccm.l10n.GlobalizationHelper;
|
||||||
|
import org.libreccm.security.AuthorizationRequired;
|
||||||
|
import org.libreccm.security.PermissionChecker;
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
import org.librecms.contentsection.AssetManager;
|
||||||
|
import org.librecms.contentsection.AssetRepository;
|
||||||
|
import org.librecms.contentsection.ContentItemRepository;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
import org.librecms.contentsection.Folder;
|
||||||
|
import org.librecms.contentsection.FolderRepository;
|
||||||
|
import org.librecms.contentsection.FolderType;
|
||||||
|
import org.librecms.contentsection.privileges.AssetPrivileges;
|
||||||
|
import org.librecms.ui.contentsections.AssetPermissionsChecker;
|
||||||
|
import org.librecms.ui.contentsections.ContentSectionModel;
|
||||||
|
import org.librecms.ui.contentsections.ContentSectionsUi;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.enterprise.inject.Any;
|
||||||
|
import javax.enterprise.inject.Instance;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.mvc.Controller;
|
||||||
|
import javax.mvc.Models;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
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.core.Context;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
@Path("/{sectionIdentifier}/assets")
|
||||||
|
@Controller
|
||||||
|
public class AssetsController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssetEditStepsValidator stepsValidator;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssetManager assetManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ContentSectionModel sectionModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ContentSectionsUi} instance providing for helper functions for
|
||||||
|
* dealing with {@link ContentSection}s.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ContentSectionsUi sectionsUi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link AssetUi} instance providing some common functions for managing
|
||||||
|
* assets.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private AssetUi assetUi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link FolderRepository} instance for retrieving folders.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private FolderRepository folderRepo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ContentItemRepository} instance for retrieving content items.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private AssetRepository assetRepo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Any
|
||||||
|
private Instance<MvcAssetCreateStep<?>> assetCreateSteps;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssetStepsDefaultMessagesBundle defaultStepsMessageBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link GlobalizationHelper} for working with localized texts etc.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private GlobalizationHelper globalizationHelper;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssetPermissionsChecker assetPermissionsChecker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to make avaiable in the views without a named bean.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private Models models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to check permissions on content items.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private PermissionChecker permissionChecker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Named bean providing access to the properties of the selected asset from
|
||||||
|
* the view.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private SelectedAssetModel selectedAssetModel;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Redirect requests to the root path of this controller to the path for
|
||||||
|
* displaying the content of the root asset folder. The root path of this
|
||||||
|
* controller has no function. We assume that somebody who access the root
|
||||||
|
* folders wants to browse all asset in the content section. Therefore we
|
||||||
|
* redirect these requests to the root folder.
|
||||||
|
*
|
||||||
|
* @param sectionIdentifier The identififer of the current content section.
|
||||||
|
*
|
||||||
|
* @return A redirect to the root assets folder.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String redirectToAssetFolders(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifier
|
||||||
|
) {
|
||||||
|
return String.format(
|
||||||
|
"redirect:/%s/assetfolders/",
|
||||||
|
sectionIdentifier
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegates requests for the path {@code @create} to the create step
|
||||||
|
* (subresource) of the asset type. The new asset will be created in the
|
||||||
|
* root folder of the current content section.
|
||||||
|
*
|
||||||
|
* @param sectionIdentifier The identifier of the current content section.
|
||||||
|
* @param assetType The type of the asset to create.
|
||||||
|
*
|
||||||
|
* @return The template of the create step.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/@create/{assetType}")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String showCreateStep(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
|
@PathParam("assetType") final String assetType
|
||||||
|
) {
|
||||||
|
return showCreateStep(sectionIdentifier, "", assetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/@create")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String showCreateStepPost(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
|
@FormParam("documentType") final String assetType
|
||||||
|
) {
|
||||||
|
return String.format(
|
||||||
|
"redirect:/%s/assets/@create/%s",
|
||||||
|
sectionIdentifier,
|
||||||
|
assetType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{folderPath:(.+)?}/@create/{assetType}")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String showCreateStep(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
|
@PathParam("folderPath") final String folderPath,
|
||||||
|
@FormParam("assetType") final String assetType
|
||||||
|
) {
|
||||||
|
final CreateStepResult result = findCreateStep(
|
||||||
|
sectionIdentifier,
|
||||||
|
folderPath,
|
||||||
|
assetType
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.isCreateStepAvailable()) {
|
||||||
|
return result.getCreateStep().showCreateStep();
|
||||||
|
} else {
|
||||||
|
return result.getErrorTemplate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{folderPath:(.+)?}/@create")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String showCreateStepPost(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
|
@PathParam("folderPath") final String folderPath,
|
||||||
|
@FormParam("assetType") final String assetType
|
||||||
|
) {
|
||||||
|
return String.format(
|
||||||
|
"redirect:/%s/documents/%s/@create/%s",
|
||||||
|
sectionIdentifier,
|
||||||
|
folderPath,
|
||||||
|
assetType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/@create/{assetType}")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String createAsset(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
|
@PathParam("assetType") final String assetType,
|
||||||
|
@Context final HttpServletRequest request
|
||||||
|
) {
|
||||||
|
return createAsset(
|
||||||
|
sectionIdentifier,
|
||||||
|
"",
|
||||||
|
assetType,
|
||||||
|
request
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{folderPath:(.+)?}/@create/{assetType}")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String createAsset(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
|
@PathParam("folderPath") final String folderPath,
|
||||||
|
@PathParam("assetType") final String assetType,
|
||||||
|
@Context final HttpServletRequest request
|
||||||
|
) {
|
||||||
|
final CreateStepResult result = findCreateStep(
|
||||||
|
sectionIdentifier,
|
||||||
|
folderPath,
|
||||||
|
assetType
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.isCreateStepAvailable()) {
|
||||||
|
return result.getCreateStep().createAsset(
|
||||||
|
request.getParameterMap()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return result.getErrorTemplate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{assetPath:(.+)?")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String editAsset(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
|
@PathParam("assetPath") final String assetPath
|
||||||
|
) {
|
||||||
|
final Optional<ContentSection> sectionResult = sectionsUi
|
||||||
|
.findContentSection(sectionIdentifier);
|
||||||
|
if (!sectionResult.isPresent()) {
|
||||||
|
return sectionsUi.showContentSectionNotFound(sectionIdentifier);
|
||||||
|
}
|
||||||
|
final ContentSection section = sectionResult.get();
|
||||||
|
|
||||||
|
final Optional<Asset> assetResult = assetRepo
|
||||||
|
.findByPath(section, assetPath);
|
||||||
|
if (!assetResult.isPresent()) {
|
||||||
|
return assetUi.showAssetNotFound(section, assetPath);
|
||||||
|
}
|
||||||
|
final Asset asset = assetResult.get();
|
||||||
|
if (!permissionChecker.isPermitted(AssetPrivileges.EDIT, asset)) {
|
||||||
|
return assetUi.showAccessDenied(section, asset, assetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format("redirect:%s", findEditStep(asset, section));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for finding the path fragment for the edit step of an
|
||||||
|
* asset.
|
||||||
|
*
|
||||||
|
* @param asset The asset.
|
||||||
|
*
|
||||||
|
* @return The path of the edit step of the asset.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private String findEditStep(
|
||||||
|
final Asset asset, final ContentSection section
|
||||||
|
) {
|
||||||
|
final MvcAssetEditKit editKit = asset
|
||||||
|
.getClass()
|
||||||
|
.getAnnotation(MvcAssetEditKit.class);
|
||||||
|
|
||||||
|
final Class<?> step = editKit.editStep();
|
||||||
|
final Path pathAnnotation = step.getAnnotation(Path.class);
|
||||||
|
return pathAnnotation
|
||||||
|
.value()
|
||||||
|
.replace(
|
||||||
|
String.format(
|
||||||
|
"{%s}",
|
||||||
|
MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM
|
||||||
|
),
|
||||||
|
section.getLabel()
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
String.format(
|
||||||
|
"/{%s}",
|
||||||
|
MvcAssetEditSteps.ASSET_PATH_PATH_PARAM
|
||||||
|
),
|
||||||
|
assetManager.getAssetPath(asset)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for showing the "asset folder not found" page if there
|
||||||
|
* is no folder for the provided path.
|
||||||
|
*
|
||||||
|
* @param section The content section.
|
||||||
|
* @param folderPath The folder path.
|
||||||
|
*
|
||||||
|
* @return The template of the "document folder not found" page.
|
||||||
|
*/
|
||||||
|
private String showAssetFolderNotFound(
|
||||||
|
final ContentSection section, final String folderPath
|
||||||
|
) {
|
||||||
|
models.put("contentSection", section.getLabel());
|
||||||
|
models.put("folderPath", folderPath);
|
||||||
|
|
||||||
|
return "org/librecms/ui/contentsection/assetfolder/assetfolder-not-found.xhtml";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Helper method for showing the "asset type not available" page if the
|
||||||
|
* requested asset type is not available.
|
||||||
|
*
|
||||||
|
* @param section The content section.
|
||||||
|
* @param assetType The asset type.
|
||||||
|
*
|
||||||
|
* @return The template of the "asset type not found" page.
|
||||||
|
*/
|
||||||
|
public String showAssetTypeNotFound(
|
||||||
|
final ContentSection section, final String assetType
|
||||||
|
) {
|
||||||
|
models.put("contentSection", section.getLabel());
|
||||||
|
models.put("assetType", assetType);
|
||||||
|
|
||||||
|
return "org/librecms/ui/contentsection/assetfolder/asset-type-not-found.xhtml";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String showCreateStepNotAvailable(
|
||||||
|
final ContentSection section,
|
||||||
|
final String folderPath,
|
||||||
|
final String assetType
|
||||||
|
) {
|
||||||
|
models.put("contentSection", section.getLabel());
|
||||||
|
models.put("folderPath", folderPath);
|
||||||
|
models.put("assetType", assetType);
|
||||||
|
|
||||||
|
return "org/librecms/ui/contentsection/assetfolder/create-step-not-available.xhtml";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private CreateStepResult findCreateStep(
|
||||||
|
final String sectionIdentifier,
|
||||||
|
final String folderPath,
|
||||||
|
final String assetType
|
||||||
|
) {
|
||||||
|
final Optional<ContentSection> sectionResult = sectionsUi
|
||||||
|
.findContentSection(sectionIdentifier);
|
||||||
|
if (!sectionResult.isPresent()) {
|
||||||
|
return new CreateStepResult(
|
||||||
|
sectionsUi.showContentSectionNotFound(sectionIdentifier)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final ContentSection section = sectionResult.get();
|
||||||
|
sectionModel.setSection(section);
|
||||||
|
|
||||||
|
final Folder folder;
|
||||||
|
if (folderPath.isEmpty()) {
|
||||||
|
folder = section.getRootAssetsFolder();
|
||||||
|
} else {
|
||||||
|
final Optional<Folder> folderResult = folderRepo
|
||||||
|
.findByPath(section, folderPath, FolderType.ASSETS_FOLDER
|
||||||
|
);
|
||||||
|
if (!folderResult.isPresent()) {
|
||||||
|
return new CreateStepResult(
|
||||||
|
showAssetFolderNotFound(section, folderPath)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
folder = folderResult.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assetPermissionsChecker.canCreateAssets(folder)) {
|
||||||
|
return new CreateStepResult(
|
||||||
|
sectionsUi.showAccessDenied(
|
||||||
|
"sectionidentifier", sectionIdentifier,
|
||||||
|
"folderPath", folderPath,
|
||||||
|
"step", defaultStepsMessageBundle.getMessage("create_step")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Class<?> clazz;
|
||||||
|
try {
|
||||||
|
clazz = Class.forName(assetType);
|
||||||
|
} catch(ClassNotFoundException ex) {
|
||||||
|
return new CreateStepResult(
|
||||||
|
showAssetTypeNotFound(section, assetType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Class<? extends Asset> assetClass = (Class<? extends Asset>) clazz;
|
||||||
|
|
||||||
|
final Optional<MvcAssetEditKit> editKitResult = Optional.ofNullable(
|
||||||
|
assetClass.getDeclaredAnnotation(MvcAssetEditKit.class)
|
||||||
|
);
|
||||||
|
if (!editKitResult.isPresent()) {
|
||||||
|
return new CreateStepResult(
|
||||||
|
showCreateStepNotAvailable(section, folderPath, assetType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final MvcAssetEditKit editKit = editKitResult.get();
|
||||||
|
final Class<? extends MvcAssetCreateStep<?>> createStepClass
|
||||||
|
= editKit.createStep();
|
||||||
|
|
||||||
|
final Instance<? extends MvcAssetCreateStep<?>> instance
|
||||||
|
= assetCreateSteps.select(createStepClass);
|
||||||
|
if (instance.isUnsatisfied() || instance.isAmbiguous()) {
|
||||||
|
return new CreateStepResult(
|
||||||
|
showCreateStepNotAvailable(section, folderPath, assetType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final MvcAssetCreateStep<? extends Asset> createStep = instance.get();
|
||||||
|
|
||||||
|
createStep.setContentSection(section);
|
||||||
|
createStep.setFolder(folder);
|
||||||
|
|
||||||
|
return new CreateStepResult(createStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CreateStepResult {
|
||||||
|
|
||||||
|
private final MvcAssetCreateStep<? extends Asset> createStep;
|
||||||
|
|
||||||
|
private final boolean createStepAvailable;
|
||||||
|
|
||||||
|
private final String errorTemplate;
|
||||||
|
|
||||||
|
public CreateStepResult(
|
||||||
|
final MvcAssetCreateStep<? extends Asset> createStep
|
||||||
|
) {
|
||||||
|
this.createStep = createStep;
|
||||||
|
createStepAvailable = true;
|
||||||
|
errorTemplate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateStepResult(final String errorTemplate) {
|
||||||
|
this.createStep = null;
|
||||||
|
createStepAvailable = false;
|
||||||
|
this.errorTemplate = errorTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MvcAssetCreateStep<? extends Asset> getCreateStep() {
|
||||||
|
return createStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCreateStepAvailable() {
|
||||||
|
return createStepAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorTemplate() {
|
||||||
|
return errorTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
import org.librecms.contentsection.Folder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A create step for an asset. Implmenting classes MUST be CDI beans (request
|
||||||
|
* scope is recommended). They are are retrieved by the {@link AssetController}
|
||||||
|
* using CDI. The {@link AssetController} will first call
|
||||||
|
* {@link #setContentSection(org.librecms.contentsection.ContentSection)} and {@link #setFolder(org.librecms.contentsection.Folder)
|
||||||
|
* } to provided the current current content section and folder. After that,
|
||||||
|
* dpending on the request method, either {@link #showCreateStep} or {@link #createAsset(java.util.Map)
|
||||||
|
* } will be called.
|
||||||
|
*
|
||||||
|
* In most cases, {@link AbstractMvcAssetCreateStep} should be used as base for
|
||||||
|
* implementations. {@link AbstractMvcAssetCreateStep} implements several common
|
||||||
|
* operations.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
* @param <T> The asset type created by the create step.
|
||||||
|
*/
|
||||||
|
public interface MvcAssetCreateStep<T extends Asset> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the template for the create step.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String showCreateStep();
|
||||||
|
|
||||||
|
String createAsset(Map<String, String[]> formParams);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should be set by the implementing class to indicate if the current user
|
||||||
|
* can create document in the current folder.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean getCanCreate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The asset type generated by the create step described by an instance of
|
||||||
|
* this class.
|
||||||
|
*
|
||||||
|
* @return Asset type generated.
|
||||||
|
*/
|
||||||
|
String getAssetType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Localized description of the create step. The current locale as returned
|
||||||
|
* by {@link GlobalizationHelper#getNegotiatedLocale()} should be used to
|
||||||
|
* select the language variant to return.
|
||||||
|
*
|
||||||
|
* @return The localized description of the create step.
|
||||||
|
*/
|
||||||
|
String getDescription();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link ResourceBundle} providing the localized description of the
|
||||||
|
* create step.
|
||||||
|
*
|
||||||
|
* @return The {@link ResourceBundle} providing the localized description of
|
||||||
|
* the create step.
|
||||||
|
*/
|
||||||
|
String getBundle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The locales that can be used for documents.
|
||||||
|
*
|
||||||
|
* @return The locales that can be used for documents.
|
||||||
|
*/
|
||||||
|
Map<String, String> getAvailableLocales();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current content section.
|
||||||
|
*
|
||||||
|
* @return The current content section.
|
||||||
|
*/
|
||||||
|
ContentSection getContentSection();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convinient method for getting the label of the current content section.
|
||||||
|
*
|
||||||
|
* @return The label of the current content section.
|
||||||
|
*/
|
||||||
|
String getContentSectionLabel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convinient method for getting the title of the current content section.
|
||||||
|
*
|
||||||
|
* @return The title of the current content section for the current locale.
|
||||||
|
*/
|
||||||
|
String getContentSectionTitle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current content section is provided by the
|
||||||
|
* {@link DocumentController}.
|
||||||
|
*
|
||||||
|
* @param section The current content section.
|
||||||
|
*/
|
||||||
|
void setContentSection(final ContentSection section);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent folder of the new asset.
|
||||||
|
*
|
||||||
|
* @return The parent folder of the new asset.
|
||||||
|
*/
|
||||||
|
Folder getFolder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the path the the parent folder of the new asset.
|
||||||
|
*
|
||||||
|
* @return The path of the parent folder of the new asset.
|
||||||
|
*/
|
||||||
|
String getFolderPath();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent folder of the new asset is provided by the
|
||||||
|
* {@link DocumentController}.
|
||||||
|
*
|
||||||
|
* @param folder The parent folder of the new doucment.
|
||||||
|
*/
|
||||||
|
void setFolder(final Folder folder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets messages from the create step.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Map<String, String> getMessages();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the steps for creating, viewing, and editing an asset.
|
||||||
|
*
|
||||||
|
* This annotation can only be used on classes extending the {@link Asset}
|
||||||
|
* class.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface MvcAssetEditKit {
|
||||||
|
|
||||||
|
Class<? extends MvcAssetCreateStep<?>> createStep();
|
||||||
|
|
||||||
|
Class<?> editStep();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata of an edit step for assets.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface MvcAssetEditStep {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the resource bundle providing the localized values for
|
||||||
|
* {@link #labelKey} and {@link descriptionKey}.
|
||||||
|
*
|
||||||
|
* @return The resource bundle providing the localized labelKey and
|
||||||
|
* descriptionKey.
|
||||||
|
*/
|
||||||
|
String bundle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key for the localized description of the step.
|
||||||
|
*
|
||||||
|
* @return The key for the localized description of the step.
|
||||||
|
*/
|
||||||
|
String descriptionKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key for the localized label of the authoring step..
|
||||||
|
*
|
||||||
|
* @return The key for the localized label of the authoring step...
|
||||||
|
*/
|
||||||
|
String labelKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit steps only support a specific type, and all subtypes.
|
||||||
|
*
|
||||||
|
* @return The asset type supported by the edit step.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Class<? extends Asset> supportedAssetType();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public interface MvcAssetEditSteps {
|
||||||
|
|
||||||
|
public static final String PATH_PREFIX
|
||||||
|
= "/{sectionIdentifier}/assets/{assetPath:(.+)?}/@";
|
||||||
|
|
||||||
|
public static final String SECTION_IDENTIFIER_PATH_PARAM
|
||||||
|
= "sectionIdentifier";
|
||||||
|
|
||||||
|
public static final String ASSET_PATH_PATH_PARAM_NAME = "assetPath";
|
||||||
|
|
||||||
|
public static final String ASSET_PATH_PATH_PARAM
|
||||||
|
= ASSET_PATH_PATH_PARAM_NAME + ":(.+)?";
|
||||||
|
|
||||||
|
Set<Class<?>> getClasses();
|
||||||
|
|
||||||
|
default Set<Class<?>> getResourceClasses() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some constants shared by most asset create and edit steps.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class MvcAssetStepsConstants {
|
||||||
|
|
||||||
|
private MvcAssetStepsConstants() {
|
||||||
|
// Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fully qualified name of the bundle provdiding texts shared by most asset
|
||||||
|
* create and edit steps.
|
||||||
|
*/
|
||||||
|
public static final String BUNDLE = "org.librecms.ui.MvcAssetStepsBundle";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.libreccm.l10n.GlobalizationHelper;
|
||||||
|
import org.libreccm.security.PermissionChecker;
|
||||||
|
import org.libreccm.security.Shiro;
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
import org.librecms.contentsection.AssetManager;
|
||||||
|
import org.librecms.contentsection.Folder;
|
||||||
|
import org.librecms.contentsection.FolderManager;
|
||||||
|
import org.librecms.ui.contentsections.FolderBreadcrumbsModel;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model/named bean providing data about the currently selected asset for
|
||||||
|
* several views.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
@Named("CmsSelectedAssetModel")
|
||||||
|
public class SelectedAssetModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if edit step classes have all required annotations.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private AssetEditStepsValidator stepsValidator;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssetManager assetManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private FolderManager folderManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to retrieve some localized data.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private GlobalizationHelper globalizationHelper;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private HttpServletRequest request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to check permissions
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private PermissionChecker permissionChecker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to get the current user.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private Shiro shiro;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current asset.
|
||||||
|
*/
|
||||||
|
private Asset asset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the current asset.
|
||||||
|
*/
|
||||||
|
private String assetName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The title of the current asset. This value is determined from
|
||||||
|
* {@link Asset#title} using {@link GlobalizationHelper#getValueFromLocalizedString(org.libreccm.l10n.LocalizedString)
|
||||||
|
* }.
|
||||||
|
*/
|
||||||
|
private String assetTitle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the current asset.
|
||||||
|
*/
|
||||||
|
private String assetPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The breadcrumb trail of the folder of the current item.
|
||||||
|
*/
|
||||||
|
private List<FolderBreadcrumbsModel> parentFolderBreadcrumbs;
|
||||||
|
|
||||||
|
public String getAssetName() {
|
||||||
|
return assetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAssetTitle() {
|
||||||
|
return assetTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAssetPath() {
|
||||||
|
return assetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FolderBreadcrumbsModel> getParentFolderBreadcrumbs() {
|
||||||
|
return Collections.unmodifiableList(parentFolderBreadcrumbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current asset and sets the properties of this model based on the
|
||||||
|
* asset.
|
||||||
|
*
|
||||||
|
* @param asset
|
||||||
|
*/
|
||||||
|
void setAsset(final Asset asset) {
|
||||||
|
this.asset = Objects.requireNonNull(asset);
|
||||||
|
assetName = asset.getDisplayName();
|
||||||
|
assetTitle = globalizationHelper.getValueFromLocalizedString(
|
||||||
|
asset.getTitle()
|
||||||
|
);
|
||||||
|
assetPath = assetManager.getAssetPath(asset).substring(1); // Without leasding slash.
|
||||||
|
parentFolderBreadcrumbs = assetManager
|
||||||
|
.getAssetFolders(asset)
|
||||||
|
.stream()
|
||||||
|
.map(this::buildFolderBreadcrumbsModel)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for building the breadcrumb trail for the folder of the
|
||||||
|
* current item.
|
||||||
|
*
|
||||||
|
* @param folder The folder of the current item.
|
||||||
|
*
|
||||||
|
* @return The breadcrumb trail of the folder.
|
||||||
|
*/
|
||||||
|
private FolderBreadcrumbsModel buildFolderBreadcrumbsModel(
|
||||||
|
final Folder folder
|
||||||
|
) {
|
||||||
|
final FolderBreadcrumbsModel model = new FolderBreadcrumbsModel();
|
||||||
|
model.setCurrentFolder(false);
|
||||||
|
model.setPath(folderManager.getFolderPath(folder));
|
||||||
|
model.setPathToken(folder.getName());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue