UI for Collected Volume asset.

pull/1/head
Jens Pelzetter 2022-05-28 17:51:49 +02:00
parent fdcda6b3fd
commit 5cad76c691
20 changed files with 6529 additions and 47 deletions

4336
sci-publications/package-lock.json generated 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
{
"name": "sci-publications",
"version": "7.0.0",
"description": "JavaScript parts of the UI of sci-publications",
"main": "index.js",
"scripts": {
"build": "npm-run-all build:*",
"build:js": "webpack"
},
"author": "Jens Pelzetter",
"license": "LGPL-3.0-or-later",
"devDependencies": {
"@types/sortablejs": "^1.10.7",
"npm-run-all": "^4.1.5",
"ts-loader": "^9.2.6",
"typescript": "^4.4.3",
"webpack": "^5.55.1",
"webpack-cli": "^4.8.0"
},
"dependencies": {
"sortablejs": "^1.14.0"
},
"targets": {
"main": false
}
}

View File

@ -127,6 +127,25 @@
<finalName>sci-publications</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>./target/generated-resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
<testResource>
<directory>${project.build.directory}/generated-resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -140,6 +159,43 @@
</configuration>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<configuration>
<installDirectory>../node</installDirectory>
</configuration>
<executions>
<execution>
<id>Install node.js and NPM</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v16.14.2</nodeVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments> --userconfig ../libreccm.npmrc install</arguments>
</configuration>
</execution>
<execution>
<id>build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
@ -196,12 +252,6 @@
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<reporting>
@ -254,7 +304,7 @@
<linkXref>true</linkXref>
<sourceEncoding>utf-8</sourceEncoding>
<targetJdk>1.8</targetJdk>
<!-- <rulesets>
<!-- <rulesets>
<ruleset>/rulesets/java/basic.xml</ruleset>
<ruleset>/rulesets/java/braces.xml</ruleset>
<ruleset>/rulesets/java/clone.xml</ruleset>

View File

@ -108,54 +108,64 @@ public class Publication implements Serializable {
@Column(name = "YEAR_OF_PUBLICATION")
private Integer yearOfPublication;
@OneToMany(cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
mappedBy = "author",
orphanRemoval = true)
@OneToMany(
cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
mappedBy = "author",
orphanRemoval = true
)
@OrderBy("authorOrder")
private List<Authorship> authorships;
@Embedded
@AssociationOverride(
name = "values",
joinTable = @JoinTable(name = "PUBLICATION_TITLES",
schema = DB_SCHEMA,
joinColumns = {
@JoinColumn(name = "PUBLICATION_ID")
})
joinTable = @JoinTable(
name = "PUBLICATION_TITLES",
schema = DB_SCHEMA,
joinColumns = {
@JoinColumn(name = "PUBLICATION_ID")
}
)
)
private LocalizedString title;
@Embedded
@AssociationOverride(
name = "values",
joinTable = @JoinTable(name = "PUBLICATION_SHORT_DESCS",
schema = DB_SCHEMA,
joinColumns = {
@JoinColumn(name = "PUBLICATION_ID")
})
joinTable = @JoinTable(
name = "PUBLICATION_SHORT_DESCS",
schema = DB_SCHEMA,
joinColumns = {
@JoinColumn(name = "PUBLICATION_ID")
}
)
)
private LocalizedString shortDescription;
@Embedded
@AssociationOverride(
name = "values",
joinTable = @JoinTable(name = "PUBLICATION_ABSTRACTS",
schema = DB_SCHEMA,
joinColumns = {
@JoinColumn(name = "PUBLICATION_ID")
})
joinTable = @JoinTable(
name = "PUBLICATION_ABSTRACTS",
schema = DB_SCHEMA,
joinColumns = {
@JoinColumn(name = "PUBLICATION_ID")
}
)
)
private LocalizedString publicationAbstract;
@Embedded
@AssociationOverride(
name = "values",
joinTable = @JoinTable(name = "PUBLICATION_MISC",
schema = DB_SCHEMA,
joinColumns = {
@JoinColumn(name = "PUBLICATION_ID")
})
joinTable = @JoinTable(
name = "PUBLICATION_MISC",
schema = DB_SCHEMA,
joinColumns = {
@JoinColumn(name = "PUBLICATION_ID")
}
)
)
private LocalizedString misc;
@ -333,7 +343,7 @@ public class Publication implements Serializable {
return false;
}
final Publication other
= (Publication) obj;
= (Publication) obj;
if (!other.canEqual(this)) {
return false;
}

View File

@ -0,0 +1,49 @@
package org.scientificcms.publications.ui.assets;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class AuthorsTableRow {
private long authorshipId;
private String authorshipUuid;
private String authorName;
private boolean editor;
public long getAuthorshipId() {
return authorshipId;
}
public void setAuthorshipId(final long authorshipId) {
this.authorshipId = authorshipId;
}
public String getAuthorshipUuid() {
return authorshipUuid;
}
public void setAuthorshipUuid(final String authorshipUuid) {
this.authorshipUuid = authorshipUuid;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public boolean isEditor() {
return editor;
}
public void setEditor(final boolean editor) {
this.editor = editor;
}
}

View File

@ -0,0 +1,111 @@
package org.scientificcms.publications.ui.assets;
import org.librecms.contentsection.Asset;
import org.librecms.contentsection.AssetRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.ui.contentsections.ContentSectionsUi;
import org.librecms.ui.contentsections.assets.MvcAssetEditSteps;
import org.scientificcms.publications.Authorship;
import org.scientificcms.publications.CollectedVolume;
import org.scientificcms.publications.PublicationRepository;
import org.scientificcms.publications.assets.CollectedVolumeAsset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
import javax.ws.rs.Consumes;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Path(MvcAssetEditSteps.PATH_PREFIX + "collectedvolume-edit-authors")
public class CollectedVolumeAssetAuthors {
@Inject
private AssetRepository assetRepo;
@Inject
private ContentSectionsUi sectionsUi;
@Inject
private PublicationRepository publicationRepo;
@POST
@Path("/save-order")
@Consumes(MediaType.APPLICATION_JSON)
@Transactional(Transactional.TxType.REQUIRED)
public Response saveOrder(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
final List<String> order
) {
final ContentSection section = sectionsUi
.findContentSection(sectionIdentifier)
.orElseThrow(
() -> new NotFoundException(
String.format(
"ContentSection %s not found.",
sectionIdentifier
)
)
);
final Asset asset = assetRepo
.findByPath(section, assetPath)
.orElseThrow(
() -> new NotFoundException(
String.format(
"Asset %s not found.",
assetPath
)
)
);
if (!(asset instanceof CollectedVolumeAsset)) {
throw new NotFoundException(
String.format(
"No CollectedVolumeAsset for path %s in section %s.",
assetPath,
section.getLabel()
)
);
}
final Map<Long, Long> orderMap = new HashMap<>();
for (int i = 0; i < order.size(); i++) {
orderMap.put(Long.parseLong(order.get(i)), (long) i);
}
final CollectedVolumeAsset collectedVolumeAsset
= (CollectedVolumeAsset) asset;
final CollectedVolume collectedVolume = collectedVolumeAsset
.getCollectedVolume();
for(final Authorship authorship : collectedVolume.getAuthorships()) {
authorship.setAuthorOrder(
orderMap.get(
authorship.getAuthorshipId()
)
);
}
publicationRepo.save(collectedVolume);
return Response.ok().build();
}
}

View File

@ -0,0 +1,132 @@
package org.scientificcms.publications.ui.assets;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.ui.contentsections.assets.AbstractMvcAssetCreateStep;
import org.scientificcms.publications.CollectedVolume;
import org.scientificcms.publications.PublicationRepository;
import org.scientificcms.publications.assets.CollectedVolumeAsset;
import org.scientificcms.publications.ui.SciPublicationsUiConstants;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("SciCmsCollectedVolumeAssetCreateStep")
public class CollectedVolumeAssetCreateStep
extends AbstractMvcAssetCreateStep<CollectedVolumeAsset> {
private static final String FORM_PARAMS_YEAR_OF_PUBLICATION
= "yearOfPublication";
private static final String FORM_PARAMS_SHORT_DESCRIPTION
= "shortDescription";
private int yearOfPublication;
private String shortDescription;
@Inject
private GlobalizationHelper globalizationHelper;
@Inject
private PublicationRepository publicationRepo;
@Override
public String showCreateStep() {
return "org/scientificcms/assets/collectedvolume/ui/create-collected-volume.xhtml";
}
@Override
public String getLabel() {
return globalizationHelper
.getLocalizedTextsUtil(getBundle())
.getText("collectedvolume.label");
}
@Override
public String getDescription() {
return globalizationHelper
.getLocalizedTextsUtil(getBundle())
.getText("collectedvolume.description");
}
@Override
public String getBundle() {
return SciPublicationsUiConstants.BUNDLE;
}
@Override
protected Class<CollectedVolumeAsset> getAssetClass() {
return CollectedVolumeAsset.class;
}
public int getYearOfPublication() {
return yearOfPublication;
}
public String getShortDescription() {
return shortDescription;
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
protected String setAssetProperties(
final CollectedVolumeAsset collectedVolumeAsset,
final Map<String, String[]> formParams
) {
final CollectedVolume collectedVolume = new CollectedVolume();
final Locale locale = new Locale(getInitialLocale());
collectedVolume.getTitle().putValue(
locale,
collectedVolumeAsset.getTitle().getValue(locale)
);
shortDescription = Optional
.ofNullable(formParams.get(FORM_PARAMS_SHORT_DESCRIPTION))
.filter(value -> value.length > 0)
.map(value -> value[0])
.filter(value -> !value.isBlank())
.orElse(null);
if (shortDescription != null) {
collectedVolume.getShortDescription().putValue(
locale,
shortDescription
);
}
final String yearOfPublicationParam = Optional
.ofNullable(formParams.get(FORM_PARAMS_YEAR_OF_PUBLICATION))
.filter(value -> value.length > 0)
.map(value -> value[0])
.filter(value -> value.matches("\\d*"))
.orElse(null);
if (yearOfPublicationParam != null) {
collectedVolume.setYearOfPublication(
Integer.parseInt(yearOfPublicationParam)
);
}
publicationRepo.save(collectedVolume);
collectedVolumeAsset.setCollectedVolume(collectedVolume);
return String.format(
"redirect:/%s/assets/%s/%s/@collectedvolume-edit",
getContentSectionLabel(),
getFolderPath(),
getName()
);
}
}

View File

@ -0,0 +1,829 @@
package org.scientificcms.publications.ui.assets;
import org.libreccm.api.Identifier;
import org.libreccm.api.IdentifierParser;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.ui.BaseUrl;
import org.librecms.assets.Person;
import org.librecms.assets.PersonRepository;
import org.librecms.contentsection.AssetRepository;
import org.librecms.ui.contentsections.AssetPermissionsChecker;
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.librecms.ui.contentsections.assets.AbstractMvcAssetEditStep;
import org.librecms.ui.contentsections.assets.AssetNotFoundException;
import org.librecms.ui.contentsections.assets.AssetStepsDefaultMessagesBundle;
import org.librecms.ui.contentsections.assets.AssetUi;
import org.librecms.ui.contentsections.assets.MvcAssetEditStep;
import org.librecms.ui.contentsections.assets.MvcAssetEditStepDef;
import org.librecms.ui.contentsections.assets.MvcAssetEditSteps;
import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow;
import org.scientificcms.publications.Authorship;
import org.scientificcms.publications.CollectedVolume;
import org.scientificcms.publications.PublicationManager;
import org.scientificcms.publications.PublicationRepository;
import org.scientificcms.publications.Publisher;
import org.scientificcms.publications.PublisherManager;
import org.scientificcms.publications.PublisherRepository;
import org.scientificcms.publications.assets.CollectedVolumeAsset;
import org.scientificcms.publications.assets.SeriesAsset;
import org.scientificcms.publications.ui.SciPublicationsUiConstants;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
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.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Path(MvcAssetEditSteps.PATH_PREFIX + "collectedvolume-edit")
@Controller
@MvcAssetEditStepDef(
bundle = SciPublicationsUiConstants.BUNDLE,
descriptionKey = "collectedvolume.editstep.description",
labelKey = "collectedvolume.editstep.label",
supportedAssetType = SeriesAsset.class
)
public class CollectedVolumeAssetEditStep extends AbstractMvcAssetEditStep {
@Inject
private AssetPermissionsChecker assetPermissionsChecker;
@Inject
private AssetStepsDefaultMessagesBundle messageBundle;
@Inject
private AssetRepository assetRepo;
@Inject
private AssetUi assetUi;
@Inject
private BaseUrl baseUrl;
@Inject
private GlobalizationHelper globalizationHelper;
@Inject
private HttpServletRequest request;
@Inject
private IdentifierParser identifierParser;
@Inject
private Models models;
@Inject
private PersonRepository personRepo;
@Inject
private PublicationManager publicationManager;
@Inject
private PublicationRepository publicationRepo;
@Inject
private PublisherManager publisherManager;
@Inject
private PublisherRepository publisherRepo;
@Inject
private CollectedVolumeAssetEditStepModel editStepModel;
@Override
public Class<? extends MvcAssetEditStep> getStepClass() {
return CollectedVolumeAssetEditStep.class;
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
protected void init() throws ContentSectionNotFoundException,
AssetNotFoundException {
super.init();
if (getAsset() instanceof CollectedVolumeAsset) {
final CollectedVolume collectedVolume = getCollectedVolume();
editStepModel.setBaseUrl(baseUrl.getBaseUrl(request));
editStepModel.setNumberOfVolumes(
collectedVolume.getNumberOfVolumes()
);
if (collectedVolume.getPublisher() != null) {
editStepModel.setPublisherName(
collectedVolume.getPublisher().getName()
);
editStepModel.setPublisherPlace(
collectedVolume.getPublisher().getPlace()
);
editStepModel.setPublisherUuid(
collectedVolume.getPublisher().getUuid()
);
}
editStepModel.setAuthors(
collectedVolume
.getAuthorships()
.stream()
.map(this::buildAuthorsTableRow)
.collect(Collectors.toList())
);
editStepModel.setShortDescriptionValues(
collectedVolume
.getShortDescription()
.getValues()
.entrySet()
.stream()
.collect(
Collectors.toMap(
entry -> entry.getKey().toString(),
entry -> entry.getValue()
)
)
);
final Set<Locale> shortDescriptionLocales = collectedVolume
.getShortDescription()
.getAvailableLocales();
editStepModel.setUnusedShortDescriptionLocales(
globalizationHelper
.getAvailableLocales()
.stream()
.filter(locale -> !shortDescriptionLocales.contains(locale))
.map(Locale::toString)
.collect(Collectors.toList())
);
editStepModel.setShortDescriptionVariants(
collectedVolume
.getShortDescription()
.getValues()
.entrySet()
.stream()
.map(this::buildVariantRow)
.collect(Collectors.toList())
);
editStepModel.setVolume(collectedVolume.getVolume());
editStepModel.setYearOfPublication(
collectedVolume.getYearOfPublication()
);
} else {
throw new AssetNotFoundException(
assetUi.showAssetNotFound(
getContentSection(), getAssetPath()
),
String.format(
"No CollectedVolumeAsset for path %s found in section %s.",
getAssetPath(),
getContentSection().getLabel()
)
);
}
}
protected CollectedVolumeAsset getCollectedVolumeAsset() {
return (CollectedVolumeAsset) getAsset();
}
protected CollectedVolume getCollectedVolume() {
return getCollectedVolumeAsset().getCollectedVolume();
}
private CmsEditorLocaleVariantRow buildVariantRow(
final Map.Entry<Locale, String> entry
) {
final CmsEditorLocaleVariantRow variant
= new CmsEditorLocaleVariantRow();
variant.setLocale(entry.getKey().toString());
variant.setWordCount(
new StringTokenizer(entry.getValue()).countTokens()
);
return variant;
}
@GET
@Path("/")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String showStep(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
return "org/scientificcms/assets/collectedvolume/ui/edit-collectedvolume.xhtml";
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
@POST
@Path("/properties")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String updateProperties(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@FormParam("yearOfPublication")
final String yearOfPublicationParam,
@FormParam("volume")
final String volumeParam,
@FormParam("numberOfVolumes")
final String numberOfVolumesParam
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
final CollectedVolume collectedVolume = getCollectedVolume();
if (yearOfPublicationParam != null) {
if (yearOfPublicationParam.isBlank()) {
collectedVolume.setYearOfPublication(null);
} else {
collectedVolume.setYearOfPublication(
Integer.parseInt(yearOfPublicationParam)
);
}
}
if (volumeParam != null) {
if (volumeParam.isBlank()) {
collectedVolume.setVolume(null);
} else {
collectedVolume.setVolume(Integer.parseInt(volumeParam));
}
}
if (numberOfVolumesParam != null) {
if (numberOfVolumesParam.isBlank()) {
collectedVolume.setVolume(null);
} else {
collectedVolume.setVolume(
Integer.parseInt(numberOfVolumesParam)
);
}
}
publicationRepo.save(collectedVolume);
return buildRedirectPathForStep();
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
@POST
@Path("/title/@add")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String addTitle(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@FormParam("locale") final String localeParam,
@FormParam("value") final String value
) {
final String redirect = super.addTitle(
sectionIdentifier,
assetPath,
localeParam,
value
);
final CollectedVolume collectedVolume = getCollectedVolume();
collectedVolume.getTitle().putValue(new Locale(localeParam), value);
publicationRepo.save(collectedVolume);
return redirect;
}
@POST
@Path("/title/@edit/{locale}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String editTitle(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@PathParam("locale") final String localeParam,
@FormParam("value") final String value
) {
final String redirect = super.editTitle(
sectionIdentifier,
assetPath,
localeParam,
value
);
final CollectedVolume collectedVolume = getCollectedVolume();
collectedVolume.getTitle().putValue(new Locale(localeParam), value);
publicationRepo.save(collectedVolume);
return redirect;
}
@POST
@Path("/title/@remove/{locale}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String removeTitle(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@PathParam("locale") final String localeParam
) {
final String redirect = super.removeTitle(
sectionIdentifier,
assetPath,
localeParam
);
final CollectedVolume collectedVolume = getCollectedVolume();
collectedVolume.getTitle().removeValue(new Locale(localeParam));
publicationRepo.save(collectedVolume);
return redirect;
}
@POST
@Path("/shortdescription/@add")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String addShortDescription(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@FormParam("locale") final String localeParam,
@FormParam("value") final String value
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
getCollectedVolume().getShortDescription().putValue(
new Locale(localeParam),
value
);
publicationRepo.save(getCollectedVolume());
return buildRedirectPathForStep();
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
@POST
@Path("/shortdescription/edit/{locale}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String editShortDescription(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@PathParam("locale") final String localeParam,
@FormParam("value") final String value
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
getCollectedVolume().getShortDescription().putValue(
new Locale(localeParam),
value
);
publicationRepo.save(getCollectedVolume());
return buildRedirectPathForStep();
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
@POST
@Path("/shortdescription/remove/{locale}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String removeShortDescription(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@PathParam("locale") final String localeParam
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
getCollectedVolume().getShortDescription().removeValue(
new Locale(localeParam)
);
publicationRepo.save(getCollectedVolume());
return buildRedirectPathForStep();
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
@POST
@Path("/authors")
@AuthorizationRequired
@Transactional
public String addAuthor(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@FormParam("authorIdentifier")
final String authorIdentifier,
@FormParam("editor")
final String editorParam
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
final Identifier identifier = identifierParser.parseIdentifier(
authorIdentifier
);
final Optional<Person> authorResult;
switch (identifier.getType()) {
case ID:
authorResult = personRepo.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
case UUID:
authorResult = assetRepo.findByUuidAndType(
identifier.getIdentifier(),
Person.class
);
break;
default: {
final List<Person> result = personRepo.findBySurname(
identifier.getIdentifier()
);
if (result.isEmpty()) {
authorResult = Optional.empty();
} else {
authorResult = Optional.of(result.get(0));
}
}
}
if (!authorResult.isPresent()) {
return showAuthorNotFound(
sectionIdentifier,
assetPath,
authorIdentifier
);
}
final Person author = authorResult.get();
final boolean editor = "true".equals(editorParam);
publicationManager.addAuthor(author, getCollectedVolume(), editor);
return buildRedirectPathForStep();
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
@POST
@Path("/authors/{authorshipUuid}")
@AuthorizationRequired
@Transactional
public String editAuthorship(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@PathParam("authorshipUuid")
final String authorshipUuid,
@FormParam("editor")
final String editorParam
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
final CollectedVolume collectedVolume = getCollectedVolume();
final Optional<Authorship> authorshipResult = collectedVolume
.getAuthorships()
.stream()
.filter(current -> current.getUuid().equals(authorshipUuid))
.findAny();
if (!authorshipResult.isPresent()) {
return showAuthorshipNotFound(
sectionIdentifier,
assetPath,
authorshipUuid
);
}
final Authorship authorship = authorshipResult.get();
authorship.setEditor("true".equals(editorParam));
publicationRepo.save(collectedVolume);
return buildRedirectPathForStep();
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
@POST
@Path("/authors/{authorshipUuid}/remove")
@AuthorizationRequired
@Transactional
public String removeAuthorship(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@PathParam("authorshipUuid")
final String authorshipUuid
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
final CollectedVolume collectedVolume = getCollectedVolume();
final Optional<Authorship> authorshipResult = collectedVolume
.getAuthorships()
.stream()
.filter(current -> current.getUuid().equals(authorshipUuid))
.findAny();
if (!authorshipResult.isPresent()) {
return showAuthorshipNotFound(
sectionIdentifier,
assetPath,
authorshipUuid
);
}
final Authorship authorship = authorshipResult.get();
publicationManager.removeAuthor(
authorship.getAuthor(),
collectedVolume
);
return buildRedirectPathForStep();
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
@POST
@Path("/publisher")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String setPublisher(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
final String assetPath,
@FormParam("publisherIdentifier")
final String publisherIdentifier
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
final Identifier identifier = identifierParser.parseIdentifier(
publisherIdentifier
);
final Optional<Publisher> publisherResult;
switch (identifier.getType()) {
case ID:
publisherResult = publisherRepo.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
case UUID:
publisherResult = publisherRepo.findByUuid(
identifier.getIdentifier()
);
break;
default: {
final List<Publisher> result = publisherRepo.findByName(
identifier.getIdentifier()
);
if (result == null || result.isEmpty()) {
publisherResult = Optional.empty();
} else {
publisherResult = Optional.of(result.get(0));
}
break;
}
}
if (!publisherResult.isPresent()) {
return showPublisherNotFound(
sectionIdentifier,
assetPath,
publisherIdentifier
);
}
final Publisher publisher = publisherResult.get();
publisherManager.addPublicationToPublisher(
getCollectedVolume(),
publisher
);
return buildRedirectPathForStep();
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
@POST
@Path("/publisher/@remove")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String removePublisher() {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (AssetNotFoundException ex) {
return ex.showErrorMessage();
}
if (assetPermissionsChecker.canEditAsset(getAsset())) {
final CollectedVolume collectedVolume = getCollectedVolume();
final Publisher publisher = collectedVolume.getPublisher();
if (publisher != null) {
publisherManager.removePublicationFromPublisher(
collectedVolume,
publisher
);
}
return buildRedirectPathForStep();
} else {
return assetUi.showAccessDenied(
getContentSection(),
getAsset(),
messageBundle.get("asset.edit.denied"));
}
}
private String showAuthorNotFound(
final String sectionIdentifier,
final String assetPath,
final String authorIdentifier
) {
models.put("authorNotFound", authorIdentifier);
return showStep(sectionIdentifier, assetPath);
}
private String showAuthorshipNotFound(
final String sectionIdentifier,
final String assetPath,
final String authorshipIdentifier
) {
models.put("authorshipNotFound", authorshipIdentifier);
return showStep(sectionIdentifier, assetPath);
}
private String showPublisherNotFound(
final String sectionIdentifier,
final String assetPath,
final String publisherIdentifier
) {
models.put("publisherNotFound", publisherIdentifier);
return showStep(sectionIdentifier, assetPath);
}
private AuthorsTableRow buildAuthorsTableRow(final Authorship authorship) {
final AuthorsTableRow row = new AuthorsTableRow();
row.setAuthorName(
String.join(
", ",
authorship.getAuthor().getPersonName().getSurname(),
authorship.getAuthor().getPersonName().getGivenName()
)
);
row.setAuthorshipId(authorship.getAuthorshipId());
row.setAuthorshipUuid(authorship.getUuid());
row.setEditor(authorship.isEditor());
return row;
}
}

View File

@ -0,0 +1,152 @@
package org.scientificcms.publications.ui.assets;
import org.librecms.assets.Person;
import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow;
import org.scientificcms.publications.Publisher;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("SciCmsCollectedVolumeAssetEditStepModel")
public class CollectedVolumeAssetEditStepModel {
private String baseUrl;
private List<AuthorsTableRow> authors;
private int yearOfPublication;
private String publisherUuid;
private String publisherName;
private String publisherPlace;
private Map<String, String> shortDescriptionValues;
private List<CmsEditorLocaleVariantRow> shortDescriptionVariants;
private List<String> unusedShortDescriptionLocales;
private Integer volume;
private Integer numberOfVolumes;
public String getBaseUrl() {
return baseUrl;
}
protected void setBaseUrl(final String baseUrl) {
this.baseUrl = baseUrl;
}
public List<AuthorsTableRow> getAuthors() {
return Collections.unmodifiableList(authors);
}
public void setAuthors(final List<AuthorsTableRow> authors) {
this.authors = authors;
}
public int getYearOfPublication() {
return yearOfPublication;
}
public void setYearOfPublication(final int yearOfPublication) {
this.yearOfPublication = yearOfPublication;
}
public String getPublisherUuid() {
return publisherUuid;
}
public void setPublisherUuid(final String publisherUuid) {
this.publisherUuid = publisherUuid;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(final String publisherName) {
this.publisherName = publisherName;
}
public String getPublisherPlace() {
return publisherPlace;
}
public void setPublisherPlace(final String publisherPlace) {
this.publisherPlace = publisherPlace;
}
public Map<String, String> getShortDescriptionValues() {
return Collections.unmodifiableMap(shortDescriptionValues);
}
public void setShortDescriptionValues(
final Map<String, String> shortDescriptionValues
) {
this.shortDescriptionValues = new HashMap<>(shortDescriptionValues);
}
public List<CmsEditorLocaleVariantRow> getShortDescriptionVariants() {
return Collections.unmodifiableList(shortDescriptionVariants);
}
public void setShortDescriptionVariants(
final List<CmsEditorLocaleVariantRow> shortDescriptionVariants
) {
this.shortDescriptionVariants = new ArrayList<>(
shortDescriptionVariants
);
}
public List<String> getUnusedShortDescriptionLocales() {
return Collections.unmodifiableList(unusedShortDescriptionLocales);
}
public void setUnusedShortDescriptionLocales(
final List<String> unusedShortDescriptionLocales
) {
this.unusedShortDescriptionLocales = new ArrayList<>(
unusedShortDescriptionLocales
);
}
public Integer getVolume() {
return volume;
}
public void setVolume(final Integer volume) {
this.volume = volume;
}
public Integer getNumberOfVolumes() {
return numberOfVolumes;
}
public void setNumberOfVolumes(final Integer numberOfVolumes) {
this.numberOfVolumes = numberOfVolumes;
}
public String getAuthorType() {
return Person.class.getName();
}
public String getPublisherType() {
return Publisher.class.getName();
}
}

View File

@ -190,9 +190,8 @@ public class SeriesAssetEditStep extends AbstractMvcAssetEditStep {
value
);
final Locale locale = new Locale(localeParam);
final Series series = getSeries();
series.getTitle().putValue(locale, value);
series.getTitle().putValue(new Locale(localeParam), value);
seriesRepo.save(series);
return redirect;
@ -218,9 +217,8 @@ public class SeriesAssetEditStep extends AbstractMvcAssetEditStep {
value
);
final Locale locale = new Locale(localeParam);
final Series series = getSeries();
series.getTitle().putValue(locale, value);
series.getTitle().putValue(new Locale(localeParam), value);
seriesRepo.save(series);
return redirect;
@ -230,6 +228,7 @@ public class SeriesAssetEditStep extends AbstractMvcAssetEditStep {
@Path("/title/@remove/{locale}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String removeTitle(
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@ -243,10 +242,10 @@ public class SeriesAssetEditStep extends AbstractMvcAssetEditStep {
localeParam
);
final Locale locale = new Locale(localeParam);
final Series series = getSeries();
series.getTitle().removeValue(locale);
series.getTitle().removeValue(new Locale(localeParam));
seriesRepo.save(series);
return redirect;
}

View File

@ -0,0 +1,80 @@
<!DOCTYPE html [<!ENTITY times '&#215;'>]>
<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: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/contentsection/contentsection.xhtml">
<ui:define name="main">
<div class="container">
<h1>#{SciPublicationsUiMessageBundle['collectedvolume.createform.title']}</h1>
<c:forEach items="#{SciCmsCollectedVolumeAssetCreateStep.messages.entrySet()}"
var="messages">
<div class="alert alert-#{message.key}" role="alert">
#{message.value}
</div>
</c:forEach>
<form action="#{mvc.basePath}/#{SciCmsCollectedVolumeAssetCreateStep.contentSectionLabel}/assets/#{SciCmsCollectedVolumeAssetCreateStep.folderPath}@create/#{SciCmsCollectedVolumeAssetCreateStep.assetType}"
method="post">
<bootstrap:formGroupText
help="#{CmsAssetsStepsDefaultMessagesBundle['createform.name.help']}"
inputId="name"
label="#{CmsAssetsStepsDefaultMessagesBundle['createform.name.label']}"
name="name"
pattern="^([a-zA-Z0-9_-]*)$"
required="true"
value="#{SciCmsJournalAssetCreateStep.name}"
/>
<bootstrap:formGroupSelect
help="#{CmsAssetsStepsDefaultMessagesBundle['createform.initial_locale.help']}"
inputId="locale"
label="#{CmsAssetsStepsDefaultMessagesBundle['createform.initial_locale.label']}"
name="locale"
options="#{SciCmsCollectedVolumeAssetCreateStep.availableLocales}"
required="true"
selectedOptions="#{[SciCmsCollectedVolumeAssetCreateStep.initialLocale]}"
/>
<bootstrap:formGroupText
help="#{SciPublicationsUiMessageBundle['collectedvolume.createform.title.help']}"
inputId="journalTitle"
label="#{SciPublicationsUiMessageBundle['collectedvolume.createform.title.label']}"
name="journalTitle"
required="true"
value="#{SciCmsJournalAssetCreateStep.title}"
/>
<bootstrap:formGroupNumber
help="#{SciPublicationsUiMessageBundle['collectedvolume.createform.yearofpublication.help']}"
inputId="yearOfPublication"
label="#{SciPublicationsUiMessageBundle['collectedvolume.createform.yearofpublication.label']}"
name="yearOfPublication"
/>
<bootstrap:formGroupTextarea
cols="80"
help="#{SciPublicationsUiMessageBundle['collectedvolume.createform.shortdescription.help']}"
inputId="shortDescription"
label="#{SciPublicationsUiMessageBundle['collectedvolume.createform.shortdescription.label']}"
name="shortDescription"
rows="20"
/>
<a class="btn btn-warning"
href="#{mvc.basePath}/#{SciCmsCollectedVolumeAssetCreateStep.contentSectionLabel}/assetsfolders/#{SciCmsCollectedVolumeAssetCreateStep.folderPath}">
#{CmsAssetsStepsDefaultMessagesBundle['createform.cancel']}
</a>
<button class="btn btn-success"
type="submit">
#{CmsAssetsStepsDefaultMessagesBundle['createform.submit']}
</button>
</form>
</div>
</ui:define>
</ui:composition>
</html>

View File

@ -0,0 +1,363 @@
<!DOCTYPE html [<!ENTITY times '&#215;'>]>
<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:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
xmlns:librecms="http://xmlns.jcp.org/jsf/composite/components/librecms"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/librecms/ui/contentsection/assets/editstep.xhtml">
<ui:param name="stepControllerUrl"
value="@collectedvolume-edit"
/>
<ui:param name="title"
value="#{SciPublicationsUiMessageBundle.getMessage('collectedvolume.editstep.header', [MvcAssetEditStepModel.name])}"
/>
<ui:define name="editStep">
<c:if test="#{authorNotFound != null}">
<div class="alert alert-warning" role="alert">
#{SciPublicationsUiMessageBundle.getMessage('collectedvolume.editstep.errors.author_not_found', [authorNotFound])}
</div>
</c:if>
<c:if test="#{authorshipNotFound != null}">
<div class="alert alert-warning" role="alert">
#{SciPublicationsUiMessageBundle.getMessage('collectedvolume.editstep.errors.authorship_not_found', [authorshipNotFound])}
</div>
</c:if>
<c:if test="#{publisherNotFound != null}">
<div class="alert alert-warning" role="alert">
#{SciPublicationsUiMessageBundle.getMessage('collectedvolume.editstep.errors.publisher_not_found', [publisherNotFound])}
</div>
</c:if>
<template id="authors-sort-error-general">
<div class="alert alert-warning mt-3" role="alert">
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.errors.authors.sort.general']}
</div>
</template>
<template id="authors-sort-error-save">
<div class="alert alert-warning mt-3" role="alert">
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.errors.authors.sort.save']}
</div>
</template>
<c:if test="#{MvcAssetEditStepModel.canEdit}">
<h3>#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors']}</h3>
<div class="mb-2">
<div class="text-right">
<librecms:assetPickerButton
assetPickerId="authors-picker"
buttonIcon="plus-circle"
buttonText="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.add.label']}"
/>
</div>
</div>
<librecms:assetPicker
actionUrl="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit/authors"
assetType="#{SciCmsCollectedVolumeAssetEditStepModel.authorType}"
assetPickerId="authors-picker"
baseUrl="#{SciCmsCollectedVolumeAssetEditStepModel.baseUrl}"
contentSection="#{ContentSectionModel.sectionName}"
dialogTitle="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.add.dialog.title']}"
formParamName="authorIdentifier"
>
<bootstrap:formCheck
inputId="authors-picker-editor"
label="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.editor.label']}"
name="editor"
/>
</librecms:assetPicker>
<button class="btn btn-secondary authors-save-order-button"
disabled="disabled"
type="button">
<span class="save-icon">
<bootstrap:svgIcon icon="save" />
</span>
<span class="save-spinner d-none">
<span aria-hidden="true"
class="spinner-border spinner-border-sm"
role="status"></span>
<span class="sr-only">#{SciPublicationsUiMessageBundle['authors.order.save.inprogress']}</span>
</span>
<span>#{SciPublicationsUiMessageBundle['authors.order.save']}</span>
</button>
<table id="authors-table"
data-saveUrl="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit-authors/save-order">
<thead>
<tr>
<th>#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.table.name']}</th>
<th>
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.table.editor']}
</th>
<th colspan="2">
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.table.actions']}
</th>
</tr>
</thead>
<tbody>
<c:forEach items="#{SciCmsCollectedVolumeAssetEditStepModel.authors}"
var="author">
<tr class="collectedvolume-author"
id="#{author.id}"
data-id="#{author.authorshipId}">
<td>
<button class="btn btn-secondary cms-sort-handle mr-2"
type="button">
#{author.authorName}
</button>
</td>
<td>
<c:choose>
<c:when test="#{author.editor}">
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.table.editor.yes']}
</c:when>
<c:otherwise>
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.table.editor.no']}
</c:otherwise>
</c:choose>
</td>
<td>
<button class="btn btn-secondary"
data-toggle="modal"
data-target="authorship-edit-#{author.authorshipUuid}"
type="button">
<bootstrap:svgIcon icon="pen" />
<span class="sr-only">
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.edit.label']}
</span>
</button>
<div aria-hidden="true"
aria-labelledby="authorship-edit-#{author.authorshipUuid}-title"
class="modal fade"
id="authorship-edit-#{author.authorshipUuid}"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit/authors/#{author.authorshipUuid}"
class="modal-content"
method="post">
<div class="modal-header">
<h4 class="modal-title"
id="authorship-edit-#{author.authorshipUuid}-title">
#{SciPublicationsUiMessageBundle.getMessage('collectedvolume.editstep.authors.editdialog.title', [author.authorName])}
</h4>
<button aria-label="{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.editdialog.cancel']}"
class="close"
data-dismiss="modal"
type="button">
<bootstrap:svgIcon icon="x" />
</button>
</div>
<div class="modal-body">
<bootstrap:formCheck
checked="#{author.editor ? 'checked' : ''}"
inputId="#{author.authorshipUuid}-editor"
label="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.editdialog.editor.label']}"
name="editor"
value="true"
/>
</div>
<div class="modal-footer">
<button class="btn btn-warning"
data-dismiss="modal"
type="button">
{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.editdialog.cancel']}
</button>
<button class="btn btn-success"
type="submit">
{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.editdialog.submit']}
</button>
</div>
</form>
</div>
</div>
</td>
<td>
<libreccm:deleteDialog
actionTarget="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit/authors/#{author.authorshipUuid}/remove"
buttonText="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.remove.label']}"
cancelLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.remove.cancel']}"
confirmLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.authors.remove.confirm']}"
dialogId="remove-author-#{author.authorshipUuid}"
dialogTitle="#{SciPublicationsUiMessageBundle.getMessage('collectedvolume.editstep.authors.remove.title', [author.authorName])}"
message="#{SciPublicationsUiMessageBundle.getMessage('collectedvolume.editstep.authors.remove.text', [author.authorName])}"
/>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<h3>#{SciPublicationsUiMessageBundle['collectedvolume.editstep.publisher']}</h3>
<div class="mb-2">
<div class="text-right">
<librecms:assetPickerButton
assetPickerId="publisher-picker"
buttonIcon="plus-circle"
buttonText="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.publisher.set.label']}"
/>
</div>
</div>
<librecms:assetPicker
actionUrl="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit/publisher"
assetType="#{SciCmsCollectedVolumeAssetEditStepModel.publisherType}"
assetPickerId="publisher-picker"
baseUrl="#{SciCmsCollectedVolumeAssetEditStepModel.baseUrl}"
contentSection="#{ContentSectionModel.sectionName}"
dialogTitle="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.publisher.select.dialog.title']}"
formParamName="publisherIdentifier"
/>
<p>
<c:choose>
<c:when test="#{SciCmsCollectedVolumeAssetEditStepModel.publisherPlace != null}">
#{SciCmsCollectedVolumeAssetEditStepModel.publisherName}, #{SciCmsCollectedVolumeAssetEditStepModel.publisherPlace}
</c:when>
<c:otherwise>
#{SciCmsCollectedVolumeAssetEditStepModel.publisherName}
</c:otherwise>
</c:choose>
<libreccm:deleteDialog
actionTarget="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit/publisher/@remove"
buttonText="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.publisher.remove.label']}"
cancelLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.publisher.cancel']}"
confirmLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.publisher.confirm']}"
dialogId="publisher.remove"
dialogTitle="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.publisher.title']}"
message="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.publisher.message']}"
/>
</p>
<h3>#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties']}</h3>
<div class="text-right">
<button class="btn btn-primary"
data-toggle="modal"
data-target="#properties-edit-dialog"
type="button">
<bootstrap:svgIcon icon="pen" />
<span class="sr-only">#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.edit']}</span>
</div>
<div aria-hidden="true"
aria-labelledby="properties-edit-dialog-title"
class="modal fade"
id="properties-edit-dialog"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit/properties"
class="modal-content"
method="post">
<div class="modal-header">
<h4 class="modal-title"
id="properties-edit-dialog-title">
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.edit.title']}
</h4>
<button
aria-label="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.edit.close']}"
class="close"
data-dismiss="modal"
type="button">
<bootstrap:svgIcon icon="x" />
</button>
</div>
<div class="modal-body">
<bootstrap:formGroupNumber
help="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.yearofpublication.help']}"
inputId="yearOfPublication"
label="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.yearofpublication.label']}"
name="yearOfPublication"
value="#{SciCmsCollectedVolumeAssetEditStepModel.yearOfPublication}"
/>
<bootstrap:formGroupNumber
help="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.volume.help']}"
inputId="volume"
label="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.volume.label']}"
name="volume"
value="#{SciCmsCollectedVolumeAssetEditStepModel.volume}"
/>
<bootstrap:formGroupNumber
help="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.numberofvolume.help']}"
inputId="numberOfVolume"
label="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.numberofvolume.label']}"
name="numberOfVolume"
value="#{SciCmsCollectedVolumeAssetEditStepModel.numberOfVolumes}"
/>
</div>
<div class="modal-footer">
<button class="btn btn-warning"
data-dismiss="modal"
type="button">
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.edit.close']}
</button>
<button class="btn btn-success"
type="submit">
#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.edit.submit']}
</button>
</div>
</form>
</div>
</div>
<dl>
<div>
<dt>#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.yearofpublication.label']}</dt>
<dd>#{SciCmsCollectedVolumeAssetEditStepModel.yearOfPublication}</dd>
</div>
<div>
<dt>#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.volume.label']}</dt>
<dd>#{SciCmsCollectedVolumeAssetEditStepModel.volume}</dd>
</div>
<div>
<dt>#{SciPublicationsUiMessageBundle['collectedvolume.editstep.properties.numberofvolume.label']}</dt>
<dd>#{SciCmsCollectedVolumeAssetEditStepModel.numberOfVolumes}</dd>
</div>
</dl>
<libreccm:localizedStringEditor
addButtonLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.add.label']}"
addDialogCancelLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.add.cancel']}"
addDialogLocaleSelectHelp="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.add.locale.help']}"
addDialogLocaleSelectLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.add.locale.label']}"
addDialogSubmitLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.add.submit']}"
addDialogTitle="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.add.title']}"
addDialogValueHelp="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.add.value.help']}"
addDialogValueLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.add.value.label']}"
addMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit/shortdescription/add"
editButtonLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.edit.label']}"
editDialogCancelLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.edit.cancel']}"
editDialogSubmitLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.edit.submit']}"
editDialogTitle="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.edit.title']}"
editDialogValueHelp="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.edit.value.help']}"
editDialogValueLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.edit.value.label']}"
editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit/shortdescription/edit"
editorId="shortdescription-editor"
hasUnusedLocales="#{!SciCmsCollectedVolumeAssetEditStepModel.unusedShortDescriptionLocales.isEmpty()}"
headingLevel="4"
objectIdentifier="#{CmsSelectedAssetModel.assetPath}"
readOnly="#{!MvcAssetEditStepModel.canEdit}"
removeButtonLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.remove.label']}"
removeDialogCancelLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.remove.cancel']}"
removeDialogSubmitLabel="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.remove.submit']}"
removeDialogText="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.remove.text']}"
removeDialogTitle="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.remove.title']}"
removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@collectedvolume-edit/shortdescription/remove"
title="#{SciPublicationsUiMessageBundle['collectedvolume.editstep.shortdescription.title']}"
unusedLocales="#{SciCmsCollectedVolumeAssetEditStepModel.unusedShortDescriptionLocales}"
useTextarea="true"
values="#{SciCmsCollectedVolumeAssetEditStepModel.shortDescriptionValues}"
/>
</c:if>
</ui:define>
<ui:define name="scripts">
<script src="#{request.contextPath}/assets/@scipublications/collectedvolume-asset-authors.js" />
</ui:define>
</ui:composition>
</html>

View File

@ -87,3 +87,76 @@ series.editstep.description.remove.title=Confirm removal of localized descriptio
series.editstep.description.title=Description
series.label=Series
series.description=Create a new series (of publications)
collectedvolume.createform.title=Create new Collected Volume as Asset
collectedvolume.createform.title.help=The title of the collected volume.
collectedvolume.createform.title.label=Title
collectedvolume.label=Collected Volume
collectedvolume.description=A collected volume as asset.
collectedvolume.createform.yearofpublication.help=Year of publication
collectedvolume.createform.shortdescription.help=A short description of the collected volume.
collectedvolume.createform.shortdescription.label=Description
collectedvolume.editstep.header=Edit Collected Volume {0}
collectedvolume.editstep.errors.author_not_found=Author {0} not found.
collectedvolume.editstep.errors.authorship_not_found=Authorship {0} not found
collectedvolume.editstep.errors.publisher_not_found=Publisher {0} not found
collectedvolume.editstep.errors.authors.sort.general=Error sorting authors of collected volume.
collectedvolume.editstep.errors.authors.sort.save=Error saving sorting of authors of collected volume.
collectedvolume.editstep.authors=Authors
collectedvolume.editstep.authors.add.label=Add author
collectedvolume.editstep.authors.add.dialog.title=Add author
collectedvolume.editstep.authors.editor.label=Editor?
authors.order.save.inprogress=Saving sorting of authors...
collectedvolume.editstep.authors.table.name=Name
collectedvolume.editstep.authors.table.editor=Editor?
collectedvolume.editstep.authors.table.actions=Actions
collectedvolume.editstep.authors.table.editor.yes=Yes
collectedvolume.editstep.authors.table.editor.no=No
collectedvolume.editstep.authors.edit.label=Edit
collectedvolume.editstep.authors.editdialog.title=Edit authorship of {0}
collectedvolume.editstep.authors.editdialog.cancel=Cancel
collectedvolume.editstep.authors.editdialog.editor.label=Editor?
collectedvolume.editstep.authors.editdialog.submit=Save
collectedvolume.editstep.authors.remove.label=Remove authorship
collectedvolume.editstep.authors.remove.cancel=Cancel
collectedvolume.editstep.authors.remove.confirm=Remove
collectedvolume.editstep.authors.remove.title=Confirm removal of authorship of {0}
collectedvolume.editstep.authors.remove.text=Are you sure to remove the authorship of {0}?
collectedvolume.editstep.publisher=Publisher
collectedvolume.editstep.publisher.set.label=Set publisher
collectedvolume.editstep.publisher.select.dialog.title=Select publisher
collectedvolume.editstep.publisher.remove.label=Remove publisher
collectedvolume.editstep.publisher.cancel=Cancel
collectedvolume.editstep.publisher.confirm=Remove
collectedvolume.editstep.publisher.title=Confirm removal of publisher
collectedvolume.editstep.publisher.message=Are you sure to remove the publisher from this collected volume?
collectedvolume.editstep.properties=Properties
collectedvolume.editstep.properties.edit=Edit properties
collectedvolume.editstep.properties.edit.title=Edit properties
collectedvolume.editstep.properties.edit.close=Cancel
collectedvolume.editstep.properties.yearofpublication.help=The year of publication of the collected volume.
collectedvolume.editstep.properties.yearofpublication.label=Year of publication
collectedvolume.editstep.properties.volume.help=The volume of the publication.
collectedvolume.editstep.properties.volume.label=Volume
collectedvolume.editstep.properties.numberofvolume.help=The number of volumes of the publication.
collectedvolume.editstep.properties.numberofvolume.label=Number of volumes
collectedvolume.editstep.properties.edit.submit=Save
collectedvolume.editstep.shortdescription.add.label=Add localized description
collectedvolume.editstep.shortdescription.add.cancel=Cancel
collectedvolume.editstep.shortdescription.add.locale.help=The locale of the localized description.
collectedvolume.editstep.shortdescription.add.locale.label=Locale
collectedvolume.editstep.shortdescription.add.submit=Add
collectedvolume.editstep.shortdescription.add.title=Add localized description
collectedvolume.editstep.shortdescription.add.value.help=The localized description of the collected volume.
collectedvolume.editstep.shortdescription.add.value.label=Description
collectedvolume.editstep.shortdescription.edit.label=Edit
collectedvolume.editstep.shortdescription.edit.cancel=Cancel
collectedvolume.editstep.shortdescription.edit.submit=Save
collectedvolume.editstep.shortdescription.edit.title=Edit localized description
collectedvolume.editstep.shortdescription.edit.value.help=The localized description of the collected volume.
collectedvolume.editstep.shortdescription.edit.value.label=Description
collectedvolume.editstep.shortdescription.remove.label=Remove
collectedvolume.editstep.shortdescription.remove.cancel=Cancel
collectedvolume.editstep.shortdescription.remove.submit=Remove
collectedvolume.editstep.shortdescription.remove.text=Are you sure to remove the following localized description of the collected volume:
collectedvolume.editstep.shortdescription.remove.title=Confirm removal of localized description
collectedvolume.editstep.shortdescription.title=Description

View File

@ -87,3 +87,76 @@ series.editstep.description.remove.title=Entfernen einer lokaliserten Beschreibu
series.editstep.description.title=Beschreibung
series.label=Reihe
series.description=Eine neue (Publikations-) Reihe anlegen
collectedvolume.createform.title=Neues Sammelband als Asset anlegen
collectedvolume.createform.title.help=Der Titel des Sammelbandes.
collectedvolume.createform.title.label=Titel
collectedvolume.label=Sammelband
collectedvolume.description=Ein Sammelband, repr\u00e4sentiert als Asset.
collectedvolume.createform.yearofpublication.help=Erscheinungsjahr
collectedvolume.createform.shortdescription.help=Eine kurze Beschreibung des Sammelbandes.
collectedvolume.createform.shortdescription.label=Beschreibung
collectedvolume.editstep.header=Sammelband {0} bearbeiten
collectedvolume.editstep.errors.author_not_found=Autor {0} wurde nicht gefunden.
collectedvolume.editstep.errors.authorship_not_found=Autorenschaft {0} wurde nicht gefunden
collectedvolume.editstep.errors.publisher_not_found=Verlag {0} wurde nicht gefunden
collectedvolume.editstep.errors.authors.sort.general=Fehler beim Sortieren der Autoren des Sammelbandes.
collectedvolume.editstep.errors.authors.sort.save=Fehler beim Speichern der Sortierung der Autoren des Sammelbandes.
collectedvolume.editstep.authors=Autoren
collectedvolume.editstep.authors.add.label=Autor hinzuf\u00fcgen
collectedvolume.editstep.authors.add.dialog.title=Autor hinzuf\u00fcgen
collectedvolume.editstep.authors.editor.label=Herausgeber?
authors.order.save.inprogress=Speichere Sortierung der Autoren...
collectedvolume.editstep.authors.table.name=Name
collectedvolume.editstep.authors.table.editor=Herausgeber?
collectedvolume.editstep.authors.table.actions=Aktionen
collectedvolume.editstep.authors.table.editor.yes=Ja
collectedvolume.editstep.authors.table.editor.no=Nein
collectedvolume.editstep.authors.edit.label=Bearbeiten
collectedvolume.editstep.authors.editdialog.title=Autorenschaft von {0} bearbeiten
collectedvolume.editstep.authors.editdialog.cancel=Abbrechen
collectedvolume.editstep.authors.editdialog.editor.label=Herausgaber?
collectedvolume.editstep.authors.editdialog.submit=Speichern
collectedvolume.editstep.authors.remove.label=Autorenschaft entfernen
collectedvolume.editstep.authors.remove.cancel=Abbrechen
collectedvolume.editstep.authors.remove.confirm=Entfernen
collectedvolume.editstep.authors.remove.title=Entfernen der Autorenschaft von {0} best\u00e4tigen
collectedvolume.editstep.authors.remove.text=Sind Sie sicher, dass die Autorschaft von {0} entfernen wollen?
collectedvolume.editstep.publisher=Verlag
collectedvolume.editstep.publisher.set.label=Verlag hinzuf\u00fcgen
collectedvolume.editstep.publisher.select.dialog.title=Verlag ausw\u00e4hlen
collectedvolume.editstep.publisher.remove.label=Verlag entfernen
collectedvolume.editstep.publisher.cancel=Abbrechen
collectedvolume.editstep.publisher.confirm=Entfernen
collectedvolume.editstep.publisher.title=Entfernen des Verlages best\u00e4tigen
collectedvolume.editstep.publisher.message=Sind Sie sicher, dass Sie den Verlag von diesem Sammelband entfernen wollen?
collectedvolume.editstep.properties=Eigenschaften
collectedvolume.editstep.properties.edit=Eigenschaften bearbeiten
collectedvolume.editstep.properties.edit.title=Eigenschaften bearbeiten
collectedvolume.editstep.properties.edit.close=Abbrechen
collectedvolume.editstep.properties.yearofpublication.help=Das Erscheinungsjahr des Sammelbandes
collectedvolume.editstep.properties.yearofpublication.label=Erscheinungsjahr
collectedvolume.editstep.properties.volume.help=Der Band der Publikation.
collectedvolume.editstep.properties.volume.label=Band
collectedvolume.editstep.properties.numberofvolume.help=Die Anzahl der B\u00e4nde der Publikation.
collectedvolume.editstep.properties.numberofvolume.label=Anzahl der B\u00e4nde
collectedvolume.editstep.properties.edit.submit=Speichern
collectedvolume.editstep.shortdescription.add.label=Lokaliserte Beschreibung hinzuf\u00fcgen
collectedvolume.editstep.shortdescription.add.cancel=Abbrechen
collectedvolume.editstep.shortdescription.add.locale.help=Die Sprache der lokalisierten Beschreibung.
collectedvolume.editstep.shortdescription.add.locale.label=Sprache
collectedvolume.editstep.shortdescription.add.submit=Hinzuf\u00fcgen
collectedvolume.editstep.shortdescription.add.title=Lokalisierte Beschreibung hinzuf\u00fcgen
collectedvolume.editstep.shortdescription.add.value.help=Die lokalisierte Beschreibung des Sammelbandes.
collectedvolume.editstep.shortdescription.add.value.label=Beschreibung
collectedvolume.editstep.shortdescription.edit.label=Bearbeiten
collectedvolume.editstep.shortdescription.edit.cancel=Abbrechen
collectedvolume.editstep.shortdescription.edit.submit=Speichern
collectedvolume.editstep.shortdescription.edit.title=Lokalisierte Beschreibung bearbeiten
collectedvolume.editstep.shortdescription.edit.value.help=Die lokalisierte Beschreibung des Sammelbandes.
collectedvolume.editstep.shortdescription.edit.value.label=Beschreibung
collectedvolume.editstep.shortdescription.remove.label=Entfernen
collectedvolume.editstep.shortdescription.remove.cancel=Abbrechen
collectedvolume.editstep.shortdescription.remove.submit=Entfernen
collectedvolume.editstep.shortdescription.remove.text=Sind Sie sicher, dass Sie die folgende lokaliserte Beschreibung des Sammelbandes entfernen wollen:
collectedvolume.editstep.shortdescription.remove.title=Entfernen einer lokaliserten Beschreibung best\u00e4tigen
collectedvolume.editstep.shortdescription.title=Beschreibung

View File

@ -0,0 +1,148 @@
import Sortable, { SortableEvent } from "sortablejs";
let authorsSortable: Sortable;
document.addEventListener("DOMContentLoaded", function (event) {
const authorsTable = document.querySelector("#authors-table tbody");
if (authorsTable) {
authorsSortable = initAuthorsTable(authorsTable as HTMLElement);
}
const saveOrderButton = document.querySelectorAll(
".authors-save-order-button"
);
for (let i = 0; i < saveOrderButton.length; i++) {
saveOrderButton[i].addEventListener("click", saveOrder);
}
});
function initAuthorsTable(authorsTable: HTMLElement): Sortable {
return new Sortable(authorsTable, {
animation: 150,
group: "collectedvolume-author",
handle: ".cms-sort-handle",
onEnd: enableSaveButton,
});
}
function enableSaveButton(event: SortableEvent) {
const saveOrderButtons = document.querySelectorAll(
".authors-save-order-button"
);
for (let i = 0; i < saveOrderButtons.length; i++) {
const saveOrderButton: HTMLButtonElement = saveOrderButtons[
i
] as HTMLButtonElement;
saveOrderButton.disabled = false;
}
}
function saveOrder() {
const authorsTable = document.querySelector("#authors-table");
if (!authorsTable) {
showGeneralError();
throw Error("authors-table not found");
}
const saveUrl = authorsTable.getAttribute("data-saveUrl");
if (!saveUrl) {
showGeneralError();
throw Error("data-saveUrl on authors-table is missing or empty.");
}
const saveOrderButtons = document.querySelectorAll(
".authors-save-order-button"
);
for (let i = 0; i < saveOrderButtons.length; i++) {
const saveOrderButton: HTMLButtonElement = saveOrderButtons[
i
] as HTMLButtonElement;
saveOrderButton.disabled = true;
const saveIcon = saveOrderButton.querySelector(".save-icon");
const spinner = saveOrderButton.querySelector(".save-spinner");
saveIcon?.classList.toggle("d-none");
spinner?.classList.toggle("d-none");
}
const headers = new Headers();
headers.append("Cotent-Type", "application/json");
fetch(saveUrl, {
credentials: "include",
body: JSON.stringify(authorsSortable.toArray()),
headers,
method: "POST",
})
.then((response) => {
if (response.ok) {
for (let i = 0; i < saveOrderButtons.length; i++) {
const saveOrderButton: HTMLButtonElement = saveOrderButtons[
i
] as HTMLButtonElement;
saveOrderButton.disabled = true;
const saveIcon =
saveOrderButton.querySelector(".save-icon");
const spinner =
saveOrderButton.querySelector(".save-spinner");
saveIcon?.classList.toggle("d-none");
spinner?.classList.toggle("d-none");
}
} else {
showSaveError();
for (let i = 0; i < saveOrderButtons.length; i++) {
const saveOrderButton: HTMLButtonElement = saveOrderButtons[
i
] as HTMLButtonElement;
saveOrderButton.disabled = true;
const saveIcon =
saveOrderButton.querySelector(".save-icon");
const spinner =
saveOrderButton.querySelector(".save-spinner");
saveIcon?.classList.toggle("d-none");
spinner?.classList.toggle("d-none");
}
throw Error(
`Failed to save authors order. Response status: ${response.status}, statusText: ${response.statusText}`
);
}
})
.catch((error) => {
showSaveError();
for (let i = 0; i < saveOrderButtons.length; i++) {
const saveOrderButton: HTMLButtonElement = saveOrderButtons[
i
] as HTMLButtonElement;
saveOrderButton.disabled = true;
const saveIcon = saveOrderButton.querySelector(".save-icon");
const spinner = saveOrderButton.querySelector(".save-spinner");
saveIcon?.classList.toggle("d-none");
spinner?.classList.toggle("d-none");
}
throw new Error(`Failed to save authors order: ${error}`);
});
}
function showGeneralError(): void {
const alertTemplate = document.querySelector(
"authors-sort-error-general"
) as HTMLTemplateElement;
const alert = alertTemplate.content.cloneNode(true) as Element;
const container = document.querySelector("#messages");
if (container) {
container.appendChild(alert);
}
}
function showSaveError(): void {
const alertTemplate = document.querySelector(
"authors-sort-error-save"
) as HTMLTemplateElement;
const alert = alertTemplate.content.cloneNode(true) as Element;
const container = document.querySelector("#messages");
if (container) {
container.appendChild(alert);
}
}

View File

@ -0,0 +1,20 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": true,
"lib": [
"DOM",
"ES2016"
],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "target/generated-resources/assets/@scipublications",
"sourceMap": true,
"strict": true,
"target": "ES6"
},
"include": [
"src/main/typescript/**/*"
]
}

View File

@ -0,0 +1,23 @@
module.exports = {
mode: "development",
devtool: "source-map",
optimization: {
chunkIds: false
},
entry: {
"collectedvolume-asset-authors": "./src/main/typescript/collectedvolume-asset-authors.ts"
},
output: {
filename: "[name].js",
path: __dirname + "/target/generated-resources/assets/@scipublications"
},
resolve: {
extensions: [".tsx", ".ts", ".js", ".json"]
},
module: {
rules: [
// all files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'
{ test: /\.tsx?$/, use: ["ts-loader"], exclude: /node_modules/ }
]
}
}

View File

@ -14,19 +14,19 @@
<h2>#{SciProjectMessageBundle['description_step.header']}</h2>
<c:if test="#{contactableNotFound != null}">
<div class="alert alert-warning">
<div class="alert alert-warning" role="alert">
#{SciProjectMessageBundle.getMessage('description_step.errors.contactable_not_found', [contactableNotFound])}
</div>
</c:if>
<c:if test="#{personNotFound != null}">
<div class="alert alert-warning">
<div class="alert alert-warning" role="alert">
#{SciProjectMessageBundle.getMessage('description_step.errors.person_not_found', [personNotFound])}
</div>
</c:if>
<c:if test="#{illegalStatusValue != null}">
<div class="alert alert-warning">
<div class="alert alert-warning" role="alert">
#{SciProjectMessageBundle.getMessage('description_step.errors.illegal_member_status_value', [illegalStatusValue])}
</div>
</c:if>

View File

@ -8,7 +8,7 @@
],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "target/generated-resources/assets/@content-sections",
"outDir": "target/generated-resources/assets/@sciproject",
"sourceMap": true,
"strict": true,
"target": "ES6"

View File

@ -246,6 +246,14 @@
<include>WEB-INF/</include>
</includes>
</overlay>
<overlay>
<groupId>org.scientificcms</groupId>
<artifactId>sci-publications</artifactId>
<type>jar</type>
<includes>
<include>assets/</include>
</includes>
</overlay>
<overlay>
<groupId>org.scientificcms</groupId>
<artifactId>sci-publications</artifactId>