diff --git a/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationAddForm.java b/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationAddForm.java new file mode 100644 index 000000000..f40bfd545 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationAddForm.java @@ -0,0 +1,121 @@ +/* + * CategoryLocalizationAddForm.java + * + * Created on 18. April 2008, 12:03 + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.arsdigita.cms.ui.category; + + +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.categorization.CategorizationConfig; +import com.arsdigita.categorization.Category; +import com.arsdigita.dispatcher.AccessDeniedException; +import com.arsdigita.cms.util.GlobalizationUtil; +import java.util.Locale; +import java.util.StringTokenizer; + +import org.apache.log4j.Logger; + +/** + * Erzeugt ein Formular zum Anlegen einer neuen Lokalisierungen zu der aktuellen Kategorie. + * Diese Klasse ist Teil der Admin-Oberfläche von APLAWS+ und erweitert die Standardformulare + * um die Formulare für die Bearbeitung der neuen, mehrsprachigen Kategorien. + * + * @author quasi + */ +public class CategoryLocalizationAddForm extends CategoryLocalizationForm { + + public static final String versionId = + "$Id: CategoryLocalizationAddForm.java 287 2005-02-22 00:29:02Z sskracic $" + + "$Author: sskracic $" + + "$DateTime: 2004/08/17 23:15:09 $"; + + private static final Logger s_log = Logger.getLogger + (CategoryAddForm.class); + + /** Creates a new instance of CategoryLocalizationAddForm */ + public CategoryLocalizationAddForm(final CategoryRequestLocal category) { + + super("AddCategoryLocalization", gz("cms.ui.category.localization.add"), category); + + addInitListener(new InitListener()); + addProcessListener(new ProcessListener()); + + } + + // Deaktivate this widget, if category is root + public boolean isVisible(PageState state) { + return !m_category.getCategory(state).isRoot(); + } + + private class InitListener implements FormInitListener { + public final void init(final FormSectionEvent e) + throws FormProcessException { + + final PageState state = e.getPageState(); + final Category category = m_category.getCategory(state); + + // Select one entry + m_locale.addOption(new Option("", new Label((String) GlobalizationUtil.globalize("cms.ui.select_one").localize())), state); + + // Für alle Sprachen, die unterstützt werden (registry-Eintrag) + CategorizationConfig catConfig = new CategorizationConfig(); + StringTokenizer strTok = catConfig.getSupportedLanguages(); + + while(strTok.hasMoreTokens()) { + + String code = strTok.nextToken(); + + // Wenn die Sprache bereits existiert, dann entferne sie aus der Auswahlliste + if(!category.getCategoryLocalizationCollection().localizationExists(code)) { + m_locale.addOption(new Option(code, new Locale(code).getDisplayLanguage()), state); + } + } + } + } + + + private final class ProcessListener implements FormProcessListener { + public final void process(final FormSectionEvent e) + throws FormProcessException { + s_log.debug("Adding a categoryLocalization to category " + m_category); + + final PageState state = e.getPageState(); + + final Category category = m_category.getCategory(state); + final String locale = (String) m_locale.getValue(state); + final String name = (String) m_name.getValue(state); + final String description = (String) m_description.getValue(state); + final String url = (String) m_url.getValue(state); + final String isEnabled = (String) m_isEnabled.getValue(state); + + // Was soll das?? + //Assert.assertNotNull(parent, "Category parent"); + + if (s_log.isDebugEnabled()) { + s_log.debug("Adding localization for locale " + locale + " to category " + category); + } + + if (category.canEdit()) { + category.addLanguage(locale, name, description, url); + category.setEnabled("yes".equals(isEnabled), locale); + category.save(); + + } else { + // XXX user a better exception here. + // PermissionException doesn't work for this case. + throw new AccessDeniedException(); + } + } + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationEditForm.java b/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationEditForm.java new file mode 100644 index 000000000..016fc0e51 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationEditForm.java @@ -0,0 +1,105 @@ +/* + * CategoryLocalizationEditForm.java + * + * Created on 18. April 2008, 12:03 + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.arsdigita.cms.ui.category; + +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.categorization.Category; +import com.arsdigita.dispatcher.AccessDeniedException; +import java.util.Locale; + +import org.apache.log4j.Logger; + +/** + * Erzeugt ein Formular zum Bearbeiten einer vorhandenen Lokalisierungen zu der aktuellen Kategorie. + * Diese Klasse ist Teil der Admin-Oberfläche von APLAWS+ und erweitert die Standardformulare + * um die Formulare für die Bearbeitung der neuen, mehrsprachigen Kategorien. + * + * @author quasi + */ +public class CategoryLocalizationEditForm extends CategoryLocalizationForm { + + public static final String versionId = + "$Id: CategoryLocalizationEditForm.java 287 2005-02-22 00:29:02Z sskracic $" + + "$Author: sskracic $" + + "$DateTime: 2004/08/17 23:15:09 $"; + + private static final Logger s_log = Logger.getLogger + (CategoryLocalizationEditForm.class); + + private final String m_categoryLocalizationLocale; + + /** + * Creates a new instance of CategoryLocalizationEditForm + */ + public CategoryLocalizationEditForm(final CategoryRequestLocal category, + final String locale) { + + super("EditCategoryLocalization", gz("cms.ui.category.localization.edit"), category); + + // Speichere Locale ab + m_categoryLocalizationLocale = locale; + + addInitListener(new InitListener()); + addProcessListener(new ProcessListener()); + + } + + private class InitListener implements FormInitListener { + public final void init(final FormSectionEvent e) + throws FormProcessException { + + final PageState state = e.getPageState(); + final Category category = m_category.getCategory(state); + + // Verstecke Locale-Widget und sperre es (read-only) + m_locale.addOption(new Option(m_categoryLocalizationLocale, new Locale(m_categoryLocalizationLocale).getDisplayLanguage()), state); +// m_locale.setValue(state, m_categoryLocalizationLocale); +// m_locale.setVisible(state, false); + m_locale.lock(); + + m_name.setValue(state, category.getName((String) m_locale.getValue(state))); + m_description.setValue(state, category.getDescription((String) m_locale.getValue(state))); + m_url.setValue(state, category.getURL((String) m_locale.getValue(state))); + if (category.isEnabled((String) m_locale.getValue(state))) { + m_isEnabled.setValue(state, "yes"); + } else { + m_isEnabled.setValue(state, "no"); + } + } + } + + private class ProcessListener implements FormProcessListener { + public final void process(final FormSectionEvent e) + throws FormProcessException { + + final PageState state = e.getPageState(); + final Category category = m_category.getCategory(state); + + if (s_log.isDebugEnabled()) { + s_log.debug("Editing localization for locale " + m_locale + " for category " + category); + } + + if (category.canEdit()) { + category.setName((String) m_name.getValue(state), (String) m_locale.getValue(state)); + category.setDescription((String) m_description.getValue(state), (String) m_locale.getValue(state)); + category.setURL((String) m_url.getValue(state), (String) m_locale.getValue(state)); + category.setEnabled("yes".equals((String) m_isEnabled.getValue(state)), (String) m_locale.getValue(state)); + category.save(); + } else { + throw new AccessDeniedException(); + } + } + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationForm.java b/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationForm.java new file mode 100644 index 000000000..ba4d66c0a --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationForm.java @@ -0,0 +1,191 @@ +/* + * CategoryLocalizationForm.java + * + * Created on 18. April 2008, 12:04 + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.arsdigita.cms.ui.category; + +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.ParameterEvent; +import com.arsdigita.bebop.event.ParameterListener; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.RadioGroup; +import com.arsdigita.bebop.form.SingleSelect; +import com.arsdigita.bebop.form.TextArea; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.form.Widget; +import com.arsdigita.bebop.parameters.NotNullValidationListener; +import com.arsdigita.bebop.parameters.ParameterData; +import com.arsdigita.bebop.parameters.ParameterModel; +import com.arsdigita.bebop.parameters.StringInRangeValidationListener; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.bebop.parameters.TrimmedStringParameter; +import com.arsdigita.categorization.Category; +import com.arsdigita.categorization.CategoryCollection; +import com.arsdigita.cms.ui.BaseForm; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.xml.Element; + +/** + * Basisklasse für CategoryLocalizationAddForm und CategoryLocalizationEditForm. + * Diese Klasse ist Teil der Admin-Oberfläche von APLAWS+ und erweitert die Standardformulare + * um die Formulare für die Bearbeitung der neuen, mehrsprachigen Kategorien. + * + * @author quasi + */ +public class CategoryLocalizationForm extends BaseForm { + + final CategoryRequestLocal m_category; + final SingleSelect m_locale; + final TextField m_name; + final TextArea m_description; + final TextField m_url; + final RadioGroup m_isEnabled; + private Label m_script = new Label("", false); + + private final static String LOCALE = "locale"; + private final static String NAME = "name"; + private final static String DESCRIPTION = "description"; + private final static String URL = "url"; + private final static String IS_ENABLED = "isEnabled"; + + /** Creates a new instance of CategoryLocalizationForm */ + public CategoryLocalizationForm(final String key, + final GlobalizedMessage heading, + final CategoryRequestLocal category) { + + super(key, heading); + + m_category = category; + + // Parameter-Model für den SingleSelect + ParameterModel localeParam = new StringParameter(LOCALE); + localeParam.addParameterListener(new StringInRangeValidationListener(0, 2)); + + m_locale = new SingleSelect(localeParam); + m_locale.addValidationListener(new ParameterListener() { + + public void validate(ParameterEvent e) throws FormProcessException { + + // the --select one-- option is not allowed + ParameterData data = e.getParameterData(); + String code = (String) data.getValue() ; + if (code == null || code.length() == 0) { + data.addError( + (String)GlobalizationUtil.globalize( + "cms.ui.category.localization.error_locale").localize()); + } + } + }); + + addField(gz("cms.ui.category.localization.locale"), m_locale); + + m_name = new TextField(new TrimmedStringParameter(NAME)); + addField(gz("cms.ui.name"), m_name); + + m_name.setSize(30); + m_name.setMaxLength(200); + m_name.addValidationListener(new NotNullValidationListener()); + m_name.setOnFocus("if (this.form." + URL + ".value == '') { " + + " defaulting = true; this.form." + URL + + ".value = urlize(this.value); }"); + m_name.setOnKeyUp("if (defaulting) { this.form." + URL + + ".value = urlize(this.value) }"); + + // is enabled? + m_isEnabled = new RadioGroup(IS_ENABLED); + m_isEnabled.addOption(new Option("no", new Label(gz("cms.ui.no")))); + m_isEnabled.addOption(new Option("yes", new Label(gz("cms.ui.yes")))); + addField(gz("cms.ui.category.is_enabled"),m_isEnabled); + + m_description = new TextArea + (new TrimmedStringParameter(DESCRIPTION)); + addField(gz("cms.ui.description"), m_description); + + m_description.setWrap(TextArea.SOFT); + m_description.setRows(5); + m_description.setCols(40); + + // URL + // JavaScript auto-url generation is off by default. + // It is turned on under the following circumstances + // + // * If the url is null, upon starting edit of the title + // * If the url is null, upon finishing edit of name + // + // The rationale is that, auto-url generation is useful + // if the url is currently null, but once a name has been + // created you don't want to subsequently change it since + // it breaks URLs & potentially overwrites the user's + // customizations. + m_url = new TextField(new TrimmedStringParameter(URL)); + m_url.setSize(30); + m_url.setMaxLength(200); + m_url.addValidationListener(new NotNullValidationListener()); + m_url.setOnFocus("defaulting = false"); + m_url.setOnBlur("if (this.value == '') " + + "{ defaulting = true; this.value = urlize(this.form." + NAME + + ".value) }"); + addField(gz("cms.ui.category.url"),m_url); + + addAction(new Finish()); + addAction(new Cancel()); + + } + + public void generateXML(PageState ps, Element parent) { + m_script.generateXML(ps, parent); + super.generateXML(ps, parent); + } + + // Muß erweitert werden um folgende Funktion: Die Namen müssen eindeutig sein in der + // gewählten Sprache + class NameUniqueListener implements ParameterListener { + private final CategoryRequestLocal m_category; + private final Widget m_widget; + private final int m_type; + public final static int NAME_FIELD = 1; + public final static int URL_FIELD = 2; + + NameUniqueListener(final CategoryRequestLocal category) { + this(category,m_name,NAME_FIELD); + } + NameUniqueListener(final CategoryRequestLocal category, + Widget widget, int type) { + m_category = category; + m_widget = widget; + m_type = type; + } + + + // XXX Muß noch angepaßt werden + public final void validate(final ParameterEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + final String title = (String) m_widget.getValue(state); + + final Category category = m_category.getCategory(state); + + final CategoryCollection children = category.getChildren(); + + while (children.next()) { + final Category child = children.getCategory(); + String compField = + (m_type == URL_FIELD) ? child.getURL() : child.getName(); + if (compField.equalsIgnoreCase(title) + && (m_category == null + || !m_category.getCategory(state).equals(child))) { + throw new FormProcessException + (lz("cms.ui.category.name_not_unique")); + } + } + } + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationTable.java b/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationTable.java new file mode 100644 index 000000000..e0a6ac90a --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/ui/category/CategoryLocalizationTable.java @@ -0,0 +1,257 @@ +/* + * CategortyLocalizationTable.java + * + * Created on 18. April 2008, 12:03 + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.arsdigita.cms.ui.category; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.event.TableActionEvent; +import com.arsdigita.bebop.event.TableActionListener; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import com.arsdigita.categorization.Category; +import com.arsdigita.categorization.CategoryLocalization; +import com.arsdigita.categorization.CategoryLocalizationCollection; +import com.arsdigita.cms.SecurityManager; +import com.arsdigita.cms.dispatcher.Utilities; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.util.LockableImpl; +import java.math.BigDecimal; +import java.util.Locale; + +/** + * Listet alle vorhandenen Lokalisierungen zu der aktuellen Kategorie auf. Diese Klasse ist Teil + * der Admin-Oberfläche von APLAWS+ und erweitert die Standardformulare um die Formulare für die + * Bearbeitung der neuen, mehrsprachigen Kategorien. + * + * @author quasi + */ +public class CategoryLocalizationTable extends Table implements TableActionListener { + + private final CategoryRequestLocal m_category; + private final SingleSelectionModel m_model; + + private final String TABLE_COL_LANG = "table_col_lang"; + private final String TABLE_COL_DEL = "table_col_del"; + + /** + * Creates a new instance of CategoryLocalizationTable + */ + public CategoryLocalizationTable(final CategoryRequestLocal category, + final SingleSelectionModel model) { + + super(); + + m_category = category; + m_model = model; + + // Falls die Tabelle leer ist + setEmptyView(new Label(GlobalizationUtil.globalize("cms.ui.category.localization.none"))); + TableColumnModel tab_model = getColumnModel(); + + // Spalten definieren + // XXX Globalisieren + tab_model.add(new TableColumn(0, GlobalizationUtil.globalize("cms.ui.category.localization.locale").localize(), TABLE_COL_LANG)); + tab_model.add(new TableColumn(1, GlobalizationUtil.globalize("cms.ui.category.localization.name").localize())); + tab_model.add(new TableColumn(2, GlobalizationUtil.globalize("cms.ui.category.localization.description").localize())); + tab_model.add(new TableColumn(3, GlobalizationUtil.globalize("cms.ui.category.localization.url").localize())); + tab_model.add(new TableColumn(4, GlobalizationUtil.globalize("cms.ui.category.localization.action").localize(), TABLE_COL_DEL)); + + setModelBuilder(new CategoryLocalizationTableModelBuilder()); + + tab_model.get(0).setCellRenderer(new EditCellRenderer()); + tab_model.get(4).setCellRenderer(new DeleteCellRenderer()); + + addTableActionListener(this); + + } + + private class CategoryLocalizationTableModelBuilder extends LockableImpl implements TableModelBuilder { + + public TableModel makeModel(Table table, PageState state) { + final Category category = m_category.getCategory(state); + + if (category != null && category.hasLocalizations()) { + return new CategoryLocalizationTableModel(table, state, category); + } else { + return Table.EMPTY_MODEL; + } + } + } + + private class CategoryLocalizationTableModel implements TableModel { + + final private int MAX_DESC_LENGTH = 25; + + private Table m_table; + private CategoryLocalizationCollection m_categoryLocalizations; + private CategoryLocalization m_categoryLocalization; + + private CategoryLocalizationTableModel(Table t, PageState ps, Category category) { + m_table = t; + m_categoryLocalizations = new CategoryLocalizationCollection(category); + } + + public int getColumnCount() { + return m_table.getColumnModel().size(); + } + + /** + * check collection for the existence of another row.If it has fetch the + * value of current CategoryLocalization object into m_categoryLocalization class variable. + */ + public boolean nextRow() { + + if(m_categoryLocalizations != null && m_categoryLocalizations.next()){ + m_categoryLocalization = m_categoryLocalizations.getCategoryLocalization(); + return true; + + } else { + + return false; + + } + } + + /** + * Return the + * @see com.arsdigita.bebop.table.TableModel#getElementAt(int) + */ + public Object getElementAt(int columnIndex) { + switch (columnIndex){ + case 0: + Locale clLocale = new Locale(m_categoryLocalization.getLocale()); + return clLocale.getDisplayLanguage(/*Locale*/); + case 1: + return m_categoryLocalization.getName(); + case 2: + String desc = m_categoryLocalization.getDescription(); + if(desc != null && desc.length() > MAX_DESC_LENGTH) desc = desc.substring(MAX_DESC_LENGTH - 3).concat("..."); + return desc; + case 3: + return m_categoryLocalization.getURL(); + case 4: + return GlobalizationUtil.globalize("cms.ui.delete").localize(); +// return "Delete"; + default: + return null; + } + } + + /** + * + * @see com.arsdigita.bebop.table.TableModel#getKeyAt(int) + */ + public Object getKeyAt(int columnIndex) { + return m_categoryLocalization.getID(); + } + + } + + /** + * Check for the permissions to edit item and put either a Label or + * a ControlLink accordingly. + */ + private class EditCellRenderer extends LockableImpl implements TableCellRenderer { + + public Component getComponent(Table table, PageState state, Object value, + boolean isSelected, Object key, + int row, int column) { + + SecurityManager sm = Utilities.getSecurityManager(state); +// CategoryLocalization cl = (CategoryLocalization) m_clSel.getSelectedObject(state); + +// boolean canEdit = sm.canAccess(state.getRequest(), +// SecurityManager.DELETE_ITEM, +// cl); +// if (canEdit) { + if (true) { + ControlLink link = new ControlLink(value.toString()); + return link; + } else { + return new Label(value.toString()); + } + } + } + + /** + * Check for the permissions to delete item and put either a Label or + * a ControlLink accordingly. + */ + private class DeleteCellRenderer extends LockableImpl implements TableCellRenderer { + + public Component getComponent(Table table, PageState state, Object value, + boolean isSelected, Object key, + int row, int column) { + +// SecurityManager sm = Utilities.getSecurityManager(state); +// CategoryLocalization categoryLocalization = new CategoryLocalization(new BigDecimal(evt.getRowKey().toString())); + +// boolean canDelete = sm.canAccess(state.getRequest(), +// SecurityManager.DELETE_ITEM, +// categoryLocalization); +// if (canDelete) { + if (true) { + ControlLink link = new ControlLink(value.toString()); + link.setConfirmation((String) GlobalizationUtil.globalize("cms.ui.category.localization.confirm_delete").localize()); +// link.setConfirmation("Delete this localization?"); + return link; + } else { + return new Label(value.toString()); + } + } + } + + /** + * Provide implementation to TableActionListener method. + * Code that comes into picture when a link on the table is clicked. + * Handles edit and delete event. + */ + public void cellSelected(TableActionEvent evt) { + + PageState state = evt.getPageState(); + + // Get selected CategoryLocalization + CategoryLocalization categoryLocalization = new CategoryLocalization(new BigDecimal(evt.getRowKey().toString())); + + // Get Category + Category category = m_category.getCategory(state); + + // Get selected column + TableColumn col = getColumnModel().get(evt.getColumn().intValue()); + + // Edit + if(col.getHeaderKey().toString().equals(TABLE_COL_LANG)) { + + } + + // Delete + if(col.getHeaderKey().toString().equals(TABLE_COL_DEL)) { + category.delLanguage(categoryLocalization.getLocale()); + } + + } + + /** + * provide Implementation to TableActionListener method. + * Does nothing in our case. + */ + public void headSelected(TableActionEvent e) { + throw new UnsupportedOperationException("Not Implemented"); + } + + +}