CCM NG: Asset editing current status

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@6150 8810af33-2d31-482b-a856-94f89814c4df
jensp 2019-07-24 11:05:04 +00:00
parent 6fda965f86
commit 944ebafc04
10 changed files with 227 additions and 49 deletions

View File

@ -99,4 +99,19 @@ public class AbstractAssetFormController {
return new ArrayList<>(l10nManager.creatableLocales(result)); return new ArrayList<>(l10nManager.creatableLocales(result));
} }
@Transactional(Transactional.TxType.REQUIRED)
public void updateAsset(final Asset asset,
final String displayName,
final String title,
final Locale selectedLocale) {
Objects.requireNonNull(asset, "Can't update null");
final Asset selected = assetRepository
.findById(asset.getObjectId())
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No Asset with ID %d found.", asset.getObjectId())));
}
} }

View File

@ -18,17 +18,65 @@
*/ */
package com.arsdigita.cms.ui.assets; package com.arsdigita.cms.ui.assets;
import javax.enterprise.context.RequestScoped; import org.librecms.contentsection.Asset;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/** /**
* *
* Controller for the asset forms * Interface for the CDI backend for the forms to manage assets.To avoid
* problems with transactions etc.
*
* the Bebop based forms should access any other CDI beans beside the
* approbriate implementation of this interface. To minimize the efford to
* create an implementation the {@link AbstractAssetFormController} class should
* be used. This class provides basic implementations for most methods.
*
* Implementations of the methods defined by this interface should annotated with
* {@code @Transactional(Transactional.TxType.REQUIRED)}.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*
* @param <T> The type asset managed by this controller.
*/ */
@RequestScoped public interface AssetFormController<T extends Asset> {
class AssetFormController {
/**
* Gets the data for the forms from the asset.
*
* @param asset The asset.
* @param selectedLocale The selected locale
*
* @return The values of the properties of the asset for the the selected
* locale.
*/
Map<String, Object> getData(T asset, Locale selectedLocale);
/**
* Updates the asset with the provided data and saves the changes.
*
* @param asset
* @param selectedLocale
* @param data
*/
void setData(T asset, Locale selectedLocale, Map<String, Object> data);
/**
* Determines in which locales the provided asset is available.
*
* @param asset The asset.
* @return A list of the locales for which the asset has data.
*/
List<Locale> availableLocales(T asset);
/**
* Determines for which the provided asset has no data.
*
* @param asset The asset.
* @return A list of the locales for which the asset has data yet.
*/
List<Locale> creatableLocales(T asset);
} }

View File

@ -19,6 +19,7 @@
package com.arsdigita.cms.ui.assets.forms; package com.arsdigita.cms.ui.assets.forms;
import com.arsdigita.bebop.ActionLink; import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Component; import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink; import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.FormProcessException; import com.arsdigita.bebop.FormProcessException;
@ -37,6 +38,7 @@ import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.event.TableActionListener; import com.arsdigita.bebop.event.TableActionListener;
import com.arsdigita.bebop.form.Option; import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.SingleSelect; import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.form.TextField; import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.bebop.table.TableCellRenderer; import com.arsdigita.bebop.table.TableCellRenderer;
@ -58,6 +60,7 @@ import org.librecms.assets.ContactEntryKeyByLabelComparator;
import org.librecms.assets.ContactEntryKey; import org.librecms.assets.ContactEntryKey;
import org.librecms.assets.ContactEntryKeyRepository; import org.librecms.assets.ContactEntryKeyRepository;
import org.librecms.assets.ContactableEntity; import org.librecms.assets.ContactableEntity;
import org.librecms.assets.ContactableEntityManager;
import org.librecms.assets.PostalAddress; import org.librecms.assets.PostalAddress;
import java.util.Iterator; import java.util.Iterator;
@ -92,7 +95,7 @@ public abstract class AbstractContactableEntityForm<T extends ContactableEntity>
private TextField contactEntryValueField; private TextField contactEntryValueField;
private ActionLink addContactEntryLink; private Submit addContactEntryLink;
private AssetSearchWidget postalAddressSearchWidget; private AssetSearchWidget postalAddressSearchWidget;
@ -108,7 +111,7 @@ public abstract class AbstractContactableEntityForm<T extends ContactableEntity>
addPropertyWidgets(); addPropertyWidgets();
contactEntriesContainer = new SimpleContainer() { contactEntriesContainer = new BoxPanel(BoxPanel.VERTICAL) {
@Override @Override
public boolean isVisible(final PageState state) { public boolean isVisible(final PageState state) {
@ -144,13 +147,11 @@ public abstract class AbstractContactableEntityForm<T extends ContactableEntity>
); );
contactEntriesContainer.add(contactEntryValueField); contactEntriesContainer.add(contactEntryValueField);
addContactEntryLink = new ActionLink( addContactEntryLink = new Submit(
new GlobalizedMessage( new GlobalizedMessage(
"cms.ui.authoring.assets.contactable.contactentries.add", "cms.ui.authoring.assets.contactable.contactentries.add",
CMS_BUNDLE) CMS_BUNDLE)
); );
addContactEntryLink
.addActionListener(new AddContactEntryActionListener());
contactEntriesContainer.add(addContactEntryLink); contactEntriesContainer.add(addContactEntryLink);
contactEntriesContainer.add(new Label( contactEntriesContainer.add(new Label(
@ -179,6 +180,50 @@ public abstract class AbstractContactableEntityForm<T extends ContactableEntity>
} }
} }
@Override
public void process(final FormSectionEvent event)
throws FormProcessException {
if (addContactEntryLink.equals(event.getSource())) {
final PageState state = event.getPageState();
final ContactableEntity selected = getSelectedAsset(state)
.orElseThrow(() -> new FormProcessException(
new GlobalizedMessage(
"cms.ui.assets.none_selected", CMS_BUNDLE)));
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContactableEntityManager contactableEntityManager = cdiUtil
.findBean(ContactableEntityManager.class);
final ContactEntryKeyRepository keyRepository = cdiUtil
.findBean(ContactEntryKeyRepository.class);
final String key = (String) contactEntryKeySelect
.getValue(state);
final String value = (String) contactEntryValueField.getValue(state);
final ContactEntryKey entryKey = keyRepository
.findByEntryKey(key)
.orElseThrow(() -> new FormProcessException(
new GlobalizedMessage(
"cms.ui.assets.contactable.illegal_entry_key", CMS_BUNDLE)));
final ContactEntry entry = new ContactEntry();
entry.setKey(entryKey);
entry.setValue(value);
entry.setOrder(selected.getContactEntries().size());
contactableEntityManager
.addContactEntryToContactableEntity(entry, selected);
contactEntryKeySelect.setValue(state, null);
contactEntryValueField.setValue(state, "");
} else {
super.process(event);
}
}
@Override @Override
public void register(final Page page) { public void register(final Page page) {
@ -378,21 +423,17 @@ public abstract class AbstractContactableEntityForm<T extends ContactableEntity>
target.addOption( target.addOption(
new Option("", new Option("",
new Label(new GlobalizedMessage("cms.ui.select_one"), new Label(new GlobalizedMessage("cms.ui.select_one",
CMS_BUNDLE)) CMS_BUNDLE)))
); );
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContactEntryKeyRepository keyRepo = cdiUtil final AbstractContactableEntityFormController controller = cdiUtil
.findBean(ContactEntryKeyRepository.class); .findBean(AbstractContactableEntityFormController.class);
final GlobalizationHelper globalizationHelper = cdiUtil final GlobalizationHelper globalizationHelper = cdiUtil
.findBean(GlobalizationHelper.class); .findBean(GlobalizationHelper.class);
final List<ContactEntryKey> keys = keyRepo final List<ContactEntryKey> keys = controller
.findAll() .findAvailableContactEntryKeys();
.stream()
.sorted(new ContactEntryKeyByLabelComparator(globalizationHelper
.getNegotiatedLocale()))
.collect(Collectors.toList());
for (final ContactEntryKey key : keys) { for (final ContactEntryKey key : keys) {
@ -406,13 +447,4 @@ public abstract class AbstractContactableEntityForm<T extends ContactableEntity>
} }
private class AddContactEntryActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
} }

View File

@ -18,14 +18,20 @@
*/ */
package com.arsdigita.cms.ui.assets.forms; package com.arsdigita.cms.ui.assets.forms;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.assets.ContactEntry; import org.librecms.assets.ContactEntry;
import org.librecms.assets.ContactEntryKey;
import org.librecms.assets.ContactEntryKeyByLabelComparator;
import org.librecms.assets.ContactEntryKeyRepository;
import org.librecms.assets.ContactableEntity; import org.librecms.assets.ContactableEntity;
import org.librecms.assets.ContactableEntityManager; import org.librecms.assets.ContactableEntityManager;
import org.librecms.assets.ContactableEntityRepository; import org.librecms.assets.ContactableEntityRepository;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
@ -44,6 +50,12 @@ public class AbstractContactableEntityFormController {
@Inject @Inject
private ContactableEntityManager contactableEntityManager; private ContactableEntityManager contactableEntityManager;
@Inject
private ContactEntryKeyRepository keyRepository;
@Inject
private GlobalizationHelper globalizationHelper;
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public List<ContactEntry> getContactEntries( public List<ContactEntry> getContactEntries(
final ContactableEntity contactable) { final ContactableEntity contactable) {
@ -58,7 +70,7 @@ public class AbstractContactableEntityFormController {
contactable.getObjectId()))); contactable.getObjectId())));
final List<ContactEntry> entries = new ArrayList<>(); final List<ContactEntry> entries = new ArrayList<>();
for(final ContactEntry entry : entity.getContactEntries()) { for (final ContactEntry entry : entity.getContactEntries()) {
entries.add(entry); entries.add(entry);
} }
@ -88,7 +100,18 @@ public class AbstractContactableEntityFormController {
contactableEntityManager.removeContactEntryFromContactableEntity( contactableEntityManager.removeContactEntryFromContactableEntity(
contactEntry, contactableEntity); contactEntry, contactableEntity);
} }
}
@Transactional(Transactional.TxType.REQUIRED)
public List<ContactEntryKey> findAvailableContactEntryKeys() {
final Locale locale = globalizationHelper.getNegotiatedLocale();
return keyRepository
.findAll()
.stream()
.sorted(new ContactEntryKeyByLabelComparator(locale))
.collect(Collectors.toList());
} }
} }

View File

@ -31,6 +31,8 @@ import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.JoinTable; import javax.persistence.JoinTable;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table; import javax.persistence.Table;
import static org.librecms.CmsConstants.*; import static org.librecms.CmsConstants.*;
@ -42,6 +44,12 @@ import static org.librecms.CmsConstants.*;
@Entity @Entity
@Audited @Audited
@Table(name = "CONTACT_ENTRY_KEYS", schema = DB_SCHEMA) @Table(name = "CONTACT_ENTRY_KEYS", schema = DB_SCHEMA)
@NamedQueries({
@NamedQuery(
name = "ContactEntryKey.findByEntryKey",
query = "SELECT k FROM ContactEntryKey k WHERE k.entryKey = :entryKey"
)
})
public class ContactEntryKey public class ContactEntryKey
implements Comparable<ContactEntryKey>, Serializable { implements Comparable<ContactEntryKey>, Serializable {

View File

@ -51,8 +51,12 @@ public class ContactEntryKeyByLabelComparator
final String localized1 = getLocalizedValue(label1); final String localized1 = getLocalizedValue(label1);
final String localized2 = getLocalizedValue(label2); final String localized2 = getLocalizedValue(label2);
if (localized1 == null) {
return -1;
} else {
return localized1.compareTo(localized2); return localized1.compareTo(localized2);
} }
}
private String getLocalizedValue(final LocalizedString source) { private String getLocalizedValue(final LocalizedString source) {

View File

@ -20,7 +20,12 @@ package org.librecms.assets;
import org.libreccm.core.AbstractEntityRepository; import org.libreccm.core.AbstractEntityRepository;
import java.util.Objects;
import java.util.Optional;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.persistence.NoResultException;
import javax.transaction.Transactional;
/** /**
* *
@ -28,7 +33,7 @@ import javax.enterprise.context.RequestScoped;
*/ */
@RequestScoped @RequestScoped
public class ContactEntryKeyRepository public class ContactEntryKeyRepository
extends AbstractEntityRepository<Long, ContactEntryKey>{ extends AbstractEntityRepository<Long, ContactEntryKey> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -56,4 +61,23 @@ public class ContactEntryKeyRepository
return entity.getKeyId() == 0; return entity.getKeyId() == 0;
} }
@Transactional(Transactional.TxType.REQUIRED)
public Optional<ContactEntryKey> findByEntryKey(final String entryKey) {
try {
return Optional.of(
getEntityManager()
.createNamedQuery("ContactEntryKey.findByEntryKey",
ContactEntryKey.class)
.setParameter("entryKey",
Objects.requireNonNull(
entryKey,
"Can't find a ContactEntry for key null."
))
.getSingleResult());
} catch (NoResultException ex) {
return Optional.empty();
}
}
} }

View File

@ -541,3 +541,11 @@ cms.ui.pages.item_page_model=Page Model for item page
cms.ui.pages.tab.pages=Pages cms.ui.pages.tab.pages=Pages
cms.ui.pages.tab.page_models=Page Models cms.ui.pages.tab.page_models=Page Models
cms.ui.assets.organization.name=Name of the organization cms.ui.assets.organization.name=Name of the organization
cms.ui.authoring.assets.contactable.contactentries.nonecms.ui.authoring.assets.contactable.contactentries.key=Type
cms.ui.authoring.assets.contactable.contactentries.value=Value
cms.ui.authoring.assets.contactable.postaladdress\ =Postal address
cms.ui.assets.none_selected=No assets selected
cms.ui.assets.contactable.illegal_entry_key=Illegal value for contact entry key.
cms.ui.authoring.assets.contactable.contactentries.none=No contact entries
cms.ui.authoring.assets.contactable.contactentries.key=Type
cms.ui.authoring.assets.contactable.contactentries.add=Add

View File

@ -538,3 +538,11 @@ cms.ui.pages.item_page_model=Page Model f\u00fcr Item Seite
cms.ui.pages.tab.pages=Seiten cms.ui.pages.tab.pages=Seiten
cms.ui.pages.tab.page_models=Page Models cms.ui.pages.tab.page_models=Page Models
cms.ui.assets.organization.name=Name der Organization cms.ui.assets.organization.name=Name der Organization
cms.ui.authoring.assets.contactable.contactentries.nonecms.ui.authoring.assets.contactable.contactentries.key=Typ
cms.ui.authoring.assets.contactable.contactentries.value=Wert
cms.ui.authoring.assets.contactable.postaladdress\ =Post Adresse
cms.ui.assets.none_selected=Kein aktives Asset
cms.ui.assets.contactable.illegal_entry_key=Unzul\u00e4ssiger Eintragsschl\u00fcssel
cms.ui.authoring.assets.contactable.contactentries.none=Keine Eintr\u00e4ge
cms.ui.authoring.assets.contactable.contactentries.key=Typ
cms.ui.authoring.assets.contactable.contactentries.add=Hinzuf\u00fcgen

View File

@ -500,3 +500,11 @@ cms.ui.pages.item_page_model=Page Model for item page
cms.ui.pages.tab.pages=Pages cms.ui.pages.tab.pages=Pages
cms.ui.pages.tab.page_models=Page Models cms.ui.pages.tab.page_models=Page Models
cms.ui.assets.organization.name=Name of the organization cms.ui.assets.organization.name=Name of the organization
cms.ui.authoring.assets.contactable.contactentries.nonecms.ui.authoring.assets.contactable.contactentries.key=Type
cms.ui.authoring.assets.contactable.contactentries.value=Value
cms.ui.authoring.assets.contactable.postaladdress\ =Postal address
cms.ui.assets.none_selected=No assets selected
cms.ui.assets.contactable.illegal_entry_key=Illegal value for contact entry key.
cms.ui.authoring.assets.contactable.contactentries.none=No contact entries
cms.ui.authoring.assets.contactable.contactentries.key=Type
cms.ui.authoring.assets.contactable.contactentries.add=Add