From 6236220f1b1dabc62ecf5fee55fe26224f41fe6b Mon Sep 17 00:00:00 2001 From: jensp Date: Thu, 6 Jul 2017 09:24:27 +0000 Subject: [PATCH] CCM NG/ccm-cms: Editing step for editing the text of an article works now. git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4846 8810af33-2d31-482b-a856-94f89814c4df --- ...cArticleBody.java => ArticleTextBody.java} | 130 ++- .../cms/ui/authoring/PageFileForm.java | 269 +++++++ .../cms/ui/authoring/PageTextForm.java | 177 +++++ .../cms/ui/authoring/TextAssetBody.java | 750 ------------------ .../arsdigita/cms/ui/authoring/TextBody.java | 291 +++++++ ...ySheet.java => TextBodyPropertySheet.java} | 16 +- .../org/librecms/contenttypes/Article.java | 11 +- .../org/librecms/CmsResources.properties | 4 + .../org/librecms/CmsResources_de.properties | 4 + .../org/librecms/CmsResources_fr.properties | 4 + 10 files changed, 818 insertions(+), 838 deletions(-) rename ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/{GenericArticleBody.java => ArticleTextBody.java} (53%) create mode 100644 ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageFileForm.java create mode 100644 ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageTextForm.java delete mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBody.java create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBody.java rename ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/{TextAssetBodyPropertySheet.java => TextBodyPropertySheet.java} (93%) diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/GenericArticleBody.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/ArticleTextBody.java similarity index 53% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/GenericArticleBody.java rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/ArticleTextBody.java index 06d075a91..8202dcfdf 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/GenericArticleBody.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/ArticleTextBody.java @@ -30,11 +30,14 @@ import com.arsdigita.cms.ItemSelectionModel; import org.librecms.contenttypes.Article; import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess; +import com.arsdigita.kernel.KernelConfig; import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.l10n.LocalizedString; import org.librecms.contentsection.ContentItemRepository; +import java.util.Locale; + /** * Displays the current text body of the article and allows the user to edit it, * by uploading a file or entering text in a text box. @@ -45,29 +48,32 @@ import org.librecms.contentsection.ContentItemRepository; * @author Stanislav Freidin (sfreidin@arsdigita.com) * @author Jens Pelzetter */ -public class GenericArticleBody extends TextAssetBody { +public class ArticleTextBody extends TextBody { - protected AuthoringKitWizard authoringKitWizard; - protected ItemSelectionModel itemSelectionModel; + private final AuthoringKitWizard authoringKitWizard; + private final ItemSelectionModel itemSelectionModel; + private final StringParameter selectedLanguageParam; /** * Construct a new GenericArticleBody component * - * @param itemSelectionModel The {@link ItemSelectionModel} which will be - * responsible for loading the current item + * @param itemSelectionModel The {@link ItemSelectionModel} which will be + * responsible for loading the current item * - * @param authoringKitWizard The parent wizard which contains the form. The - * form may use the wizard's methods, such as - * stepForward and stepBack, in its process - * listener. + * @param authoringKitWizard The parent wizard which contains the form. + * The form may use the wizard's methods, such + * as stepForward and stepBack, in its process + * listener. + * @param selectedLanguageParam */ - public GenericArticleBody(final ItemSelectionModel itemSelectionModel, - final AuthoringKitWizard authoringKitWizard, - final StringParameter selectedLanguageParam) { + public ArticleTextBody(final ItemSelectionModel itemSelectionModel, + final AuthoringKitWizard authoringKitWizard, + final StringParameter selectedLanguageParam) { - super(new ItemAssetModel(null), selectedLanguageParam); + super(itemSelectionModel, selectedLanguageParam); this.itemSelectionModel = itemSelectionModel; this.authoringKitWizard = authoringKitWizard; + this.selectedLanguageParam = selectedLanguageParam; // Rest the component when it is hidden authoringKitWizard @@ -91,6 +97,7 @@ public class GenericArticleBody extends TextAssetBody { * Adds the options for the mime type select widget of * GenericArticleForm and sets the default mime type. * + * @param mimeSelect */ @Override protected void setMimeTypeOptions(final SingleSelect mimeSelect) { @@ -99,39 +106,26 @@ public class GenericArticleBody extends TextAssetBody { } /** - * Create a new text asset and associate it with the current item + * Updates the text for the currently selected locale. * * @param state the current page state - * - * @return a valid TextAsset + * @param text the new text for the currently selected locale */ @Override - protected LocalizedString createTextAsset(final PageState state) { + protected void updateText(final PageState state, + final String text) { - final Article article = getGenericArticle(state); - final LocalizedString text = article.getText(); + final Article article = getSelectedArticle(state); + final String selectedLanguage = (String) state.getValue( + selectedLanguageParam); + final Locale selectedLocale; + if (selectedLanguage == null) { + selectedLocale = KernelConfig.getConfig().getDefaultLocale(); + } else { + selectedLocale = new Locale(selectedLanguage); + } - // no need - cg. Text doesn't need a security context, - // and ownership of text is recorded in text_pages - // t.setParent(item); - return text; - } - - /** - * Set additional parameters of a brand new text asset, such as the parent - * ID, after the asset has been successfully uploaded - * - * @param state the current page state - * @param text the new TextAsset - */ - @Override - protected void updateTextAsset(final PageState state, - final LocalizedString text) { - - final Article article = getGenericArticle(state); - - // a.setParent(t); - article.setText(text); + article.getText().addValue(selectedLocale, text); final ContentItemRepository itemRepo = CdiUtil .createCdiUtil() .findBean(ContentItemRepository.class); @@ -139,59 +133,37 @@ public class GenericArticleBody extends TextAssetBody { } /** - * Get the current GenericArticle + * Get the current {@link Article} * - * @param state + * @param state The current page state. + * + * @return The currently selected article. */ - protected Article getGenericArticle(final PageState state) { + protected Article getSelectedArticle(final PageState state) { return (Article) itemSelectionModel.getSelectedObject(state); } @Override - protected String getTextAssetName() { - return "text"; + protected String getTextPropertyName() { + return "text"; } @Override - public LocalizedString getTextAsset(final PageState state) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } + public String getText(final PageState state) { - /** - * An ACSObjectSelectionModel that selects the current text asset for the - * text page - */ - private static class ItemAssetModel extends ItemSelectionModel { + final Article article = getSelectedArticle(state); - private RequestLocal requestLocal; - - public ItemAssetModel(final LongParameter parameter) { - - super(parameter); - - requestLocal = new RequestLocal() { - - @Override - protected Object initialValue(final PageState state) { -// final Article t -// = (Article) ((ItemSelectionModel) getSingleSelectionModel()) -// .getSelectedObject(state); -// Assert.exists(t); -// return t.getTextAsset(); - - throw new UnsupportedOperationException("ToDo"); - } - - }; - } - - - @Override - public boolean isSelected(PageState s) { - return (getSelectedObject(s) != null); + final String selectedLanguage = (String) state + .getValue(selectedLanguageParam); + final Locale selectedLocale; + if (selectedLanguage == null) { + selectedLocale = KernelConfig.getConfig().getDefaultLocale(); + } else { + selectedLocale = new Locale(selectedLanguage); } + return article.getText().getValue(selectedLocale); } } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageFileForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageFileForm.java new file mode 100644 index 000000000..7a9928c98 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageFileForm.java @@ -0,0 +1,269 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.arsdigita.cms.ui.authoring; + +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SaveCancelSection; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormValidationListener; +import com.arsdigita.bebop.form.FormErrorDisplay; +import com.arsdigita.bebop.parameters.NotNullValidationListener; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.ui.FileUploadSection; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.util.UncheckedWrapperException; + +import org.libreccm.l10n.LocalizedString; +import org.librecms.CmsConstants; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +import javax.activation.MimeType; + +/** + * A form for editing TextAsset items. Displays a "file upload" widget, + * auto-guesses mime type + */ +class PageFileForm extends Form implements FormProcessListener, + FormValidationListener { + + private final TextBody textBody; + + private SaveCancelSection saveCancelSection; + private FileUploadSection fileUploadSection; + // Variables saved by validate for processing + private RequestLocal fileUploadContent; + private RequestLocal fileUploadUsedINSO; + /** + * The text entry widget + */ + public static final String TEXT_ENTRY = "text_entry"; + + /** + * Construct a new PageFileForm + * + * @param itemSelectionModel + */ + public PageFileForm(final TextBody textBody) { + + super("PageFileUpload", new BoxPanel(BoxPanel.VERTICAL)); + + this.textBody = textBody; + + setMethod(Form.POST); + setEncType("multipart/form-data"); + + addWidgets(); + } + + private void addWidgets() { + + fileUploadSection = new FileUploadSection( + new GlobalizedMessage("cms.ui.authoring.text.mime_type"), + "text", + textBody.getDefaultMimeType()); + + fileUploadSection + .getFileUploadWidget() + .addValidationListener(new NotNullValidationListener()); + fileUploadSection + .getMimeTypeWidget() + .setDefaultValue(FileUploadSection.GUESS_MIME); + add(fileUploadSection); + + saveCancelSection = new SaveCancelSection(); + add(saveCancelSection); + + final FormErrorDisplay errorDisplay = new FormErrorDisplay(this); + add(errorDisplay); + + addValidationListener(this); + addProcessListener(this); + + fileUploadContent = new RequestLocal(); + fileUploadUsedINSO = new RequestLocal(); + + } + + protected String getFileUploadContent(PageState state) { + return (String) fileUploadContent.get(state); + } + + /** + * Make sure that files of this type can be uploaded + */ + private void validateFileType(final MimeType mime, final boolean textType) + throws FormProcessException { + // boolean validType = textType || ((mime instanceof TextMimeType) + // && ((TextMimeType) mime). + // allowINSOConvert().booleanValue()); + boolean validType = true; //ToDo + if (!validType) { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.authoring.invalid_file_type", + CmsConstants.CMS_BUNDLE)); + } + // boolean insoWorks = MimeTypeStatus.getMimeTypeStatus(). + // getInsoFilterWorks().intValue() == 1; + boolean insoWorks = true; //ToDo + if (!textType && !insoWorks) { + // Can't convert. inso filter is not working. Give message. + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.authoring.couldnt_convert_missing_inso", + CmsConstants.CMS_BUNDLE)); + } + } + + /** + * read in the content of the file (in bytes). + */ + private byte[] readFileBytes(final File file) throws FormProcessException { + byte[] fileBytes; + try (final FileInputStream fs = new FileInputStream(file)) { + fileBytes = new byte[fs.available()]; + fs.read(fileBytes); + } catch (IOException ex) { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.authoring.unable_to_load_file", + CmsConstants.CMS_BUNDLE)); + } + return fileBytes; + } + + /** + * Convert bytes to String, possibly using INSO filter to convert to HTML + * type + */ + private String convertBytes(final byte[] fileBytes, final boolean textType, + final boolean[] usedInso) throws + FormProcessException { + String fileContent; + // If mime type is not text type, try to convert to html + if (!textType) { + fileContent = new String(fileBytes); + if (fileContent != null) { + // Converted successfully, flag type should be html + usedInso[0] = true; + } else { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.authoring.couldnt_convert_inso_failed", + CmsConstants.CMS_BUNDLE)); + } + } else { + // Text type, no need to convert + final String enc = "UTF-8"; + try { + fileContent = new String(fileBytes, enc); + } catch (UnsupportedEncodingException ex) { + throw new UncheckedWrapperException( + "cannot convert to encoding " + enc, ex); + } + usedInso[0] = false; + } + return fileContent; + } + + /** + * Extract the contents of the HTML Body tag. (Done to prevent base and + * other header tags from interfering with page display). + */ + private String extractHTMLBody(final String htmlText) throws + FormProcessException { + final String lowerCase = htmlText.toLowerCase(); + int bodyStart = lowerCase.indexOf("", bodyStart); + int bodyEnd = lowerCase.indexOf("", bodyStart_v); + if (bodyStart == -1 || bodyEnd == -1) { + throw new FormProcessException(new GlobalizedMessage( + "cms.ui.authoring.html_file_missing_body_tags", + CmsConstants.CMS_BUNDLE)); + } + return htmlText.substring(bodyStart_v + 1, bodyEnd); + } + + /** + * Validate file upload + * + * @throws com.arsdigita.bebop.FormProcessException + */ + @Override + public void validate(final FormSectionEvent event) throws + FormProcessException { + MimeType mime = fileUploadSection.getMimeType(event); + // boolean textType = mime.getPrefix().equals(TextMimeType.TEXT_PREFIX); + final boolean textType = true; //ToDo + validateFileType(mime, textType); + // Convert the file to HTML, if possible + File file = fileUploadSection.getFile(event); + byte[] file_bytes = readFileBytes(file); + boolean[] usedInso = new boolean[1]; + String file_content = convertBytes(file_bytes, textType, usedInso); + // ToDo if (TextMimeType.MIME_TEXT_HTML.equals(mime.getMimeType())) { + file_content = extractHTMLBody(file_content); + // } + final PageState state = event.getPageState(); + fileUploadContent.set(state, file_content); + fileUploadUsedINSO.set(state, usedInso[0]); + } + + /** + * Process file upload. Must be validated first. + */ + @Override + public void process(final FormSectionEvent event) + throws FormProcessException { + + final FormData data = event.getFormData(); + final PageState state = event.getPageState(); + // Get the text asset or create a new one + final String text = textBody.getText(state); + final File file = fileUploadSection.getFile(event); + // Get info created during validation + final String uploadContent = (String) fileUploadContent.get(state); + boolean usedINSO = (Boolean) fileUploadUsedINSO.get(state); + // Set the mime type + // final MimeType mime = fileUploadSection.getMimeType(event); + // if (usedINSO) { + // mime = MimeType.loadMimeType("text/html"); + // } + // if (mime != null) { + // text.setMimeType(mime); + // } + // Save the uploaded content + //ToDo text.setText(uploadContent); + //t.setName(fileName); // ??? + // file = null; + // Save everything + textBody.updateText(state, text); + // if (text.isNew() || text.isModified()) { + // text.save(); + // } + } + + /** + * @return the save/cancel section for this form + */ + public SaveCancelSection getSaveCancelSection() { + return saveCancelSection; + } + + /** + * @return the save/cancel section for this form + */ + public FileUploadSection getFileUploadSection() { + return fileUploadSection; + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageTextForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageTextForm.java new file mode 100644 index 000000000..018dba30b --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageTextForm.java @@ -0,0 +1,177 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.arsdigita.cms.ui.authoring; + +import com.arsdigita.bebop.ColumnPanel; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SaveCancelSection; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.bebop.form.TextArea; +import com.arsdigita.cms.ui.CMSDHTMLEditor; +import com.arsdigita.globalization.GlobalizedMessage; + +import org.arsdigita.cms.CMSConfig; +import org.libreccm.l10n.LocalizedString; +import org.librecms.CmsConstants; + +/** + * A form for editing the body of the text. + */ +public class PageTextForm + extends Form + implements FormInitListener, + FormProcessListener, + FormSubmissionListener { + + private final TextBody textBody; + + // private SingleSelect mimeWidget; + // private Label mimeLabel; + private TextArea textWidget; + private SaveCancelSection saveCancelSection; + /** + * The text entry widget + */ + public static final String TEXT_ENTRY = "text_entry"; + /** + * The mime type widget + */ + public static final String MIME_TYPE = "mime_type"; + + /** + * Construct a new PageTextForm + * + */ + public PageTextForm(final TextBody textBody) { + + super("PageTextForm", new ColumnPanel(2)); + + this.textBody = textBody; + + setMethod(Form.POST); + setEncType("multipart/form-data"); + + addWidgets(); + } + + private void addWidgets() { + + final ColumnPanel panel = (ColumnPanel) getPanel(); + panel.setBorder(false); + panel.setPadColor("#FFFFFF"); + panel.setColumnWidth(1, "20%"); + panel.setColumnWidth(2, "80%"); + panel.setWidth("100%"); + + add(new Label(new GlobalizedMessage( + "cms.ui.authoring.edit_body_text", + CmsConstants.CMS_BUNDLE)), + ColumnPanel.LEFT | ColumnPanel.FULL_WIDTH); + + textWidget = new CMSDHTMLEditor(PageTextForm.TEXT_ENTRY); + textWidget.setRows(25); + textWidget.setCols(40); + // cg - sets editor size - closer to actual published page + // width, and similar size as htmlarea. + // could be configurable - unset means default 100% x 400px + textWidget.setMetaDataAttribute("width", "575"); + textWidget.setMetaDataAttribute("height", "500"); + textWidget.setWrap(CMSDHTMLEditor.SOFT); + add(textWidget, ColumnPanel.LEFT + | ColumnPanel.FULL_WIDTH); + + saveCancelSection = new SaveCancelSection(); + add(saveCancelSection, ColumnPanel.FULL_WIDTH); + + // optionally, we clear the text of MSWord tags every time + // the text is submitted/saved + if (CMSConfig.getConfig().isSaveTextCleansWordTags()) { + saveCancelSection.getSaveButton().setOnClick( + "wordClean_" + + PageTextForm.TEXT_ENTRY + + "();"); + } + + addInitListener(this); + addProcessListener(this); + + } + + // These are here so that TemplateBody can set them. + // public final void setMimeWidget(final SingleSelect widget) { + // mimeWidget = widget; + // } + public final void setTextWidget(final TextArea widget) { + textWidget = widget; + } + + public final void setSaveCancel(final SaveCancelSection widget) { + saveCancelSection = widget; + } + + /** + * Initialise the text area with the current value. + * + * @param event + * + * @throws FormProcessException + */ + public void init(final FormSectionEvent event) throws FormProcessException { + + final FormData data = event.getFormData(); + final PageState state = event.getPageState(); + + final String text = textBody.getText(state); + + if (text != null) { + data.put(TEXT_ENTRY, text); + } + } + + /** + * Cancels streamlined editing. + * + * @param event + */ + @Override + public void submitted(final FormSectionEvent event) { + + if (getSaveCancelSection() + .getCancelButton() + .isSelected(event.getPageState())) { + + textBody.cancelStreamlinedCreation(event.getPageState()); + } + } + + // process: update the mime type and content + @Override + public void process(final FormSectionEvent event) throws + FormProcessException { + + final FormData data = event.getFormData(); + final PageState state = event.getPageState(); + final String text = (String) data.get(TEXT_ENTRY); + textBody.updateText(state, text); + + textBody.maybeForwardToNextStep(event.getPageState()); + } + + /** + * @return the save/cancel section for this form + */ + public SaveCancelSection getSaveCancelSection() { + return saveCancelSection; + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBody.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBody.java deleted file mode 100755 index fb40cdaa6..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBody.java +++ /dev/null @@ -1,750 +0,0 @@ -/* - * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -package com.arsdigita.cms.ui.authoring; - -import java.io.File; -import java.io.FileInputStream; -import java.io.UnsupportedEncodingException; - -import org.apache.logging.log4j.Logger; - -import com.arsdigita.bebop.BoxPanel; -import com.arsdigita.bebop.ColumnPanel; -import com.arsdigita.bebop.Form; -import com.arsdigita.bebop.FormData; -import com.arsdigita.bebop.FormProcessException; -import com.arsdigita.bebop.Label; -import com.arsdigita.bebop.Page; -import com.arsdigita.bebop.PageState; -import com.arsdigita.bebop.RequestLocal; -import com.arsdigita.bebop.Resettable; -import com.arsdigita.bebop.SaveCancelSection; -import com.arsdigita.bebop.event.FormInitListener; -import com.arsdigita.bebop.event.FormProcessListener; -import com.arsdigita.bebop.event.FormSectionEvent; -import com.arsdigita.bebop.event.FormSubmissionListener; -import com.arsdigita.bebop.event.FormValidationListener; -import com.arsdigita.bebop.event.RequestEvent; -import com.arsdigita.bebop.event.RequestListener; -import com.arsdigita.bebop.form.FormErrorDisplay; -import com.arsdigita.bebop.form.SingleSelect; -import com.arsdigita.bebop.form.TextArea; -import com.arsdigita.bebop.parameters.NotNullValidationListener; -import com.arsdigita.bebop.parameters.StringParameter; - -import org.librecms.contentsection.ContentSection; - -import com.arsdigita.cms.ItemSelectionModel; -import com.arsdigita.cms.ui.CMSDHTMLEditor; -import com.arsdigita.cms.ui.ContentItemPage; -import com.arsdigita.cms.ui.FileUploadSection; -import com.arsdigita.cms.ui.SecurityPropertyEditor; -import com.arsdigita.globalization.Globalization; -import com.arsdigita.globalization.GlobalizedMessage; -import com.arsdigita.toolbox.ui.DomainObjectPropertySheet; -import com.arsdigita.util.UncheckedWrapperException; - -import org.apache.logging.log4j.LogManager; -import org.arsdigita.cms.CMSConfig; -import org.libreccm.l10n.LocalizedString; -import org.librecms.CmsConstants; - -import java.io.IOException; - -import javax.activation.MimeType; - -/** - * Displays the mime-type and the body of a single {@code TextAsset}. Maintains - * a form or uploading files into the text body of the asset, and a form for - * editing the text of the asset. - *

- * Unlike most other authoring components, this component does not require the - * asset to exist. If the asset does not exist (i.e., if - * !m_assetModel.isSelected(state)), the upload and editing forms - * will create a new asset and set it in the model by calling - * setSelectedObject on the asset selection model. Child classes - * should override the {@link #createTextAsset(PageState)} method in to create a - * valid text asset. - *

- * This component is used primarily in {@link GenericArticleBody} and - * {@link com.arsdigita.cms.ui.templates.TemplateBody} - * - * Note: In CCM NG (version 7 and newer) {@code TextAsset} does not - * longer exist. Instead fields of type {@link LocalizedString} are used. This - * class has been adapted to use {@link LocalizedString}. The name of the class - * etc. has been kept to make the migration easier. - * - * @author Stanislav Freidin (sfreidin@arsdigita.com) - * @version Jens Pelzetter - */ -public abstract class TextAssetBody - extends SecurityPropertyEditor - implements Resettable, AuthoringStepComponent, RequestListener { - - public static final String FILE_UPLOAD = "file"; - public static final String TEXT_ENTRY = "text"; - - private static final String STREAMLINED = "_streamlined"; - private static final String STREAMLINED_DONE = "1"; - private static final CMSConfig CMS_CONFIG = CMSConfig.getConfig(); - - private final StringParameter streamlinedCreationParam; - private final StringParameter selectedLanguageParam; - private ItemSelectionModel assetModel; - - /** - * Construct a new GenericArticleBody component - * - * @param assetModel The {@link ItemSelectionModel} which will be - * responsible for maintaining the current asset - * @param selectedLanguageParam - */ - public TextAssetBody(final ItemSelectionModel assetModel, - final StringParameter selectedLanguageParam) { - this(assetModel, null, selectedLanguageParam); - } - - /** - * Construct a new GenericArticleBody component - * - * @param assetModel The {@link ItemSelectionModel} which will be - * responsible for maintaining the current asset - * @param authoringKitWizard The parent wizard which contains the form. The - * form may use the wizard's methods, such as - * stepForward and stepBack, in its process - * listener. - * @param selectedLangugeParam - */ - public TextAssetBody(final ItemSelectionModel assetModel, - final AuthoringKitWizard authoringKitWizard, - final StringParameter selectedLangugeParam) { - - super(); - this.assetModel = assetModel; - - if (authoringKitWizard == null) { - streamlinedCreationParam = new StringParameter("item_body_done"); - } else { - streamlinedCreationParam = new StringParameter( - String.format("%s_body_done", - authoringKitWizard - .getContentType() - .getContentItemClass() - .getName())); - } - - this.selectedLanguageParam = selectedLangugeParam; - - if (!CMS_CONFIG.isHideTextAssetUploadFile()) { - final PageFileForm pageFileForm = getPageFileForm(); - addFileWidgets(pageFileForm); - add(FILE_UPLOAD, - new GlobalizedMessage("cms.ui.upload", CmsConstants.CMS_BUNDLE), - pageFileForm, - pageFileForm.getSaveCancelSection().getCancelButton()); - } - - final PageTextForm pageTextForm = new PageTextForm(); - addTextWidgets(pageTextForm); - add(TEXT_ENTRY, - new GlobalizedMessage("cms.ui.edit", CmsConstants.CMS_BUNDLE), - pageTextForm, - pageTextForm.getSaveCancelSection().getCancelButton()); - - // Specify full path to properties of the text asset - final DomainObjectPropertySheet sheet = getBodyPropertySheet(assetModel); - sheet.add(new GlobalizedMessage("cms.ui.authoring.body", - CmsConstants.CMS_BUNDLE), - getTextAssetName()); - - setDisplayComponent(sheet); - - getDisplayPane().setClassAttr("invertedPropertyDisplay"); - - } - - /** - * Determines the name of the property holding the text. - * - * @return The name of the property holding the text. - */ - protected abstract String getTextAssetName(); - - protected DomainObjectPropertySheet getBodyPropertySheet( - final ItemSelectionModel assetModel) { - - return new TextAssetBodyPropertySheet(assetModel, - selectedLanguageParam); - } - - /** - * Adds the options for the mime type select widget of - * GenericArticleForm and sets the default mime type. - * - */ - protected void setMimeTypeOptions(SingleSelect mimeSelect) { - FileUploadSection.addMimeOptions(mimeSelect, "text"); - mimeSelect.setOptionSelected("text/html"); - } - - /** - * To be overwritten by subclasses, should return the field. - * - * @param state - */ - public abstract LocalizedString getTextAsset(final PageState state); - - /** - * Reset this component to its original state - * - * @param state the current page state - */ - @Override - public void reset(final PageState state) { - showDisplayPane(state); - } - - // Create a text asset if it does not exist. - // This should probably be a method in GenericArticle ? - protected LocalizedString createOrGetTextAsset( - final ItemSelectionModel assetModel, - final PageState state) { - // Get the text asset or create a new one - LocalizedString text = getTextAsset(state); - - if (text == null) { - text = createTextAsset(state); - - } - - return text; - } - - /** - * Create a brand new TextAsset. Child classes should override - * this method to do the right thing. The default implementation creates a - * parent-less TextAsset with a unique name. - * - * @param state the current page state - * - * @return a valid TextAsset - */ - protected abstract LocalizedString createTextAsset(PageState state); - - /** - * Set additional parameters of a brand new text asset, such as the parent - * ID, after the asset has been successfully uploaded - * - * @param state the current page state - * @param text the new TextAsset - */ - protected abstract void updateTextAsset(PageState state, - LocalizedString text); - - /** - * Return the ItemSelectionModel which will be used to maintain - * the current text asset - * - * @return - */ - public ItemSelectionModel getAssetSelectionModel() { - return assetModel; - } - - /** - * Forward to the next step if the streamlined creation parameter is turned - * on _and_ the streamlined_creation global state parameter is set to - * 'active' - * - * @param state the PageState - */ - protected void maybeForwardToNextStep(final PageState state) { - if (ContentItemPage.isStreamlinedCreationActive(state) - && !STREAMLINED_DONE. - equals(state.getValue(streamlinedCreationParam))) { - state.setValue(streamlinedCreationParam, STREAMLINED_DONE); - fireCompletionEvent(state); - } - } - - /** - * Cancel streamlined creation for this step if the streamlined creation - * parameter is turned on _and_ the streamlined_creation global state param - * is set to 'active' - * - * @param state the PageState - */ - protected void cancelStreamlinedCreation(final PageState state) { - if (ContentItemPage.isStreamlinedCreationActive(state)) { - state.setValue(streamlinedCreationParam, STREAMLINED_DONE); - } - } - - /** - * Open the edit component if the streamlined creation parameter is turned - * on _and_ the streamlined_creation global state param is set to 'active' - * - * @param event - */ - @Override - public void pageRequested(RequestEvent event) { - - final PageState state = event.getPageState(); - - if (ContentItemPage.isStreamlinedCreationActive(state) - && !STREAMLINED_DONE. - equals(state.getValue(streamlinedCreationParam))) { - showComponent(state, TEXT_ENTRY); - } - //} - - } - - /** - * This is the form that is used to upload files. This method can be used so - * that a subclass can use their own subclass of PageFileForm. - * - * @return - */ - protected PageFileForm getPageFileForm() { - return new PageFileForm(); - } - - /** - * A form for editing TextAsset items. Displays a "file upload" widget, - * auto-guesses mime type - */ - public class PageFileForm extends Form - implements FormProcessListener, FormValidationListener { - - private SaveCancelSection saveCancelSection; - private FileUploadSection fileUploadSection; - // Variables saved by validate for processing - private RequestLocal fileUploadContent; - private RequestLocal fileUploadUsedINSO; - /** - * The text entry widget - */ - public static final String TEXT_ENTRY = "text_entry"; - - /** - * Construct a new PageFileForm - */ - public PageFileForm() { - super("PageFileUpload", new BoxPanel(BoxPanel.VERTICAL)); - setMethod(Form.POST); - setEncType("multipart/form-data"); - } - - protected String getFileUploadContent(PageState state) { - return (String) fileUploadContent.get(state); - } - - /** - * Make sure that files of this type can be uploaded - */ - private void validateFileType(final MimeType mime, - final boolean textType) - throws FormProcessException { - -// boolean validType = textType || ((mime instanceof TextMimeType) -// && ((TextMimeType) mime). -// allowINSOConvert().booleanValue()); - boolean validType = true; //ToDo - - if (!validType) { - throw new FormProcessException(new GlobalizedMessage( - "cms.ui.authoring.invalid_file_type", - CmsConstants.CMS_BUNDLE)); - } - -// boolean insoWorks = MimeTypeStatus.getMimeTypeStatus(). -// getInsoFilterWorks().intValue() == 1; - boolean insoWorks = true; //ToDo - - if (!textType && !insoWorks) { - // Can't convert. inso filter is not working. Give message. - throw new FormProcessException(new GlobalizedMessage( - "cms.ui.authoring.couldnt_convert_missing_inso", - CmsConstants.CMS_BUNDLE)); - } - } - - /** - * read in the content of the file (in bytes). - */ - private byte[] readFileBytes(final File file) - throws FormProcessException { - - byte[] fileBytes; - try (final FileInputStream fs = new FileInputStream(file)) { - fileBytes = new byte[fs.available()]; - fs.read(fileBytes); - } catch (IOException ex) { - throw new FormProcessException(new GlobalizedMessage( - "cms.ui.authoring.unable_to_load_file", - CmsConstants.CMS_BUNDLE)); - } - return fileBytes; - } - - /** - * Convert bytes to String, possibly using INSO filter to convert to - * HTML type - */ - private String convertBytes(final byte[] fileBytes, - final boolean textType, - final boolean[] usedInso) - throws FormProcessException { - String fileContent; - // If mime type is not text type, try to convert to html - if (!textType) { - fileContent = new String(fileBytes); - if (fileContent != null) { - // Converted successfully, flag type should be html - usedInso[0] = true; - } else { - throw new FormProcessException( - new GlobalizedMessage( - "cms.ui.authoring.couldnt_convert_inso_failed", - CmsConstants.CMS_BUNDLE)); - } - } else { - // Text type, no need to convert - final String enc = "UTF-8"; - try { - fileContent = new String(fileBytes, enc); - } catch (UnsupportedEncodingException ex) { - throw new UncheckedWrapperException( - "cannot convert to encoding " - + enc, ex); - } - usedInso[0] = false; - } - return fileContent; - } - - /** - * Extract the contents of the HTML Body tag. (Done to prevent base and - * other header tags from interfering with page display). - */ - private String extractHTMLBody(final String htmlText) - throws FormProcessException { - - final String lowerCase = htmlText.toLowerCase(); - int bodyStart = lowerCase.indexOf("", bodyStart); - int bodyEnd = lowerCase.indexOf("", bodyStart_v); - if (bodyStart == -1 || bodyEnd == -1) { - throw new FormProcessException(new GlobalizedMessage( - "cms.ui.authoring.html_file_missing_body_tags", - CmsConstants.CMS_BUNDLE)); - } - return htmlText.substring(bodyStart_v + 1, bodyEnd); - } - - /** - * Validate file upload - * - * @throws com.arsdigita.bebop.FormProcessException - */ - @Override - public void validate(final FormSectionEvent event) throws - FormProcessException { - - MimeType mime = fileUploadSection.getMimeType(event); -// boolean textType = mime.getPrefix().equals(TextMimeType.TEXT_PREFIX); - final boolean textType = true; //ToDo - - validateFileType(mime, textType); - - // Convert the file to HTML, if possible - File file = fileUploadSection.getFile(event); - byte[] file_bytes = readFileBytes(file); - boolean[] usedInso = new boolean[1]; - String file_content = convertBytes(file_bytes, textType, usedInso); - -// ToDo if (TextMimeType.MIME_TEXT_HTML.equals(mime.getMimeType())) { - file_content = extractHTMLBody(file_content); -// } - - final PageState state = event.getPageState(); - fileUploadContent.set(state, file_content); - fileUploadUsedINSO.set(state, new Boolean(usedInso[0])); - } - - /** - * Process file upload. Must be validated first. - */ - public void process(final FormSectionEvent event) - throws FormProcessException { - - final FormData data = event.getFormData(); - final PageState state = event.getPageState(); - // Get the text asset or create a new one - final LocalizedString text = createOrGetTextAsset(assetModel, state); - final File file = fileUploadSection.getFile(event); - - // Get info created during validation - final String uploadContent = (String) fileUploadContent.get(state); - boolean usedINSO = ((Boolean) fileUploadUsedINSO - .get(state)); - - // Set the mime type -// final MimeType mime = fileUploadSection.getMimeType(event); -// if (usedINSO) { -// mime = MimeType.loadMimeType("text/html"); -// } -// if (mime != null) { -// text.setMimeType(mime); -// } - // Save the uploaded content -//ToDo text.setText(uploadContent); - //t.setName(fileName); // ??? -// file = null; - // Save everything - updateTextAsset(state, text); -// if (text.isNew() || text.isModified()) { -// text.save(); -// } - - } - - /** - * @return the save/cancel section for this form - */ - public SaveCancelSection getSaveCancelSection() { - return saveCancelSection; - } - - /** - * @return the save/cancel section for this form - */ - public FileUploadSection getFileUploadSection() { - return fileUploadSection; - } - - } - - /** - * A form for editing the body of the text. - */ - public class PageTextForm - extends Form - implements FormInitListener, - FormProcessListener, - FormSubmissionListener { - -// private SingleSelect mimeWidget; -// private Label mimeLabel; - private TextArea textWidget; - private SaveCancelSection saveCancelSection; - /** - * The text entry widget - */ - public static final String TEXT_ENTRY = "text_entry"; - /** - * The mime type widget - */ - public static final String MIME_TYPE = "mime_type"; - - /** - * Construct a new PageTextForm - * - */ - public PageTextForm() { - - super("PageTextForm", new ColumnPanel(2)); - setMethod(Form.POST); - setEncType("multipart/form-data"); - } - - // These are here so that TemplateBody can set them. -// public final void setMimeWidget(final SingleSelect widget) { -// mimeWidget = widget; -// } - public final void setTextWidget(final TextArea widget) { - textWidget = widget; - } - - public final void setSaveCancel(final SaveCancelSection widget) { - saveCancelSection = widget; - } - - // Init: load the item and preset the textarea - public void init(final FormSectionEvent event) throws - FormProcessException { - // Ok, we need to stream out the text somehow, but for now - // we just fake it - final FormData data = event.getFormData(); - final PageState state = event.getPageState(); - -// ToDo -// final LocalizedString text = assetModel.getSelectedObject(state); -// if (text != null) { -// data.put(TEXT_ENTRY, text.getText()); -// MimeType m = text.getMimeType(); -// if (m != null) { -// data.put(MIME_TYPE, m.getMimeType()); -// } -// } - } - - /** - * Cancels streamlined editing. - */ - @Override - public void submitted(final FormSectionEvent event) { - if (getSaveCancelSection().getCancelButton().isSelected(event. - getPageState())) { - TextAssetBody.this.cancelStreamlinedCreation(event - .getPageState()); - } - } - - // process: update the mime type and content - @Override - public void process(final FormSectionEvent event) throws - FormProcessException { - - final FormData data = event.getFormData(); - final PageState state = event.getPageState(); - final LocalizedString text = createOrGetTextAsset(assetModel, state); - - // Set the mime type -// MimeType m = MimeType.loadMimeType((String) data.get(MIME_TYPE)); -// text.setMimeType(m); - // Get the string and normalize it - String textStr = (String) data.get(TEXT_ENTRY); - - if (textStr == null) { - textStr = ""; - } - -// ToDo textStr.setText((String) data.get(TEXT_ENTRY)); - // Save everything - updateTextAsset(state, text); - - TextAssetBody.this.maybeForwardToNextStep(event.getPageState()); - } - - /** - * @return the save/cancel section for this form - */ - public SaveCancelSection getSaveCancelSection() { - return saveCancelSection; - } - - } - - protected String getDefaultMimeType() { - return "text/plain"; - } - - /* overridable method to put together the PageFileForm Component */ - protected void addFileWidgets(final PageFileForm pageFileForm) { - - pageFileForm.fileUploadSection = new FileUploadSection("Text Type:", - "text", - getDefaultMimeType()); - pageFileForm.fileUploadSection.getFileUploadWidget() - .addValidationListener( - new NotNullValidationListener()); - // Default to -guess- because want to use file extension to determine type. - pageFileForm.fileUploadSection.getMimeTypeWidget().setDefaultValue( - FileUploadSection.GUESS_MIME); - pageFileForm.add(pageFileForm.fileUploadSection); - - pageFileForm.saveCancelSection = new SaveCancelSection(); - pageFileForm.add(pageFileForm.saveCancelSection); - - // add FormErrorDisplay component to display any error message - FormErrorDisplay fe = new FormErrorDisplay(pageFileForm); - pageFileForm.add(fe); - - pageFileForm.addValidationListener(pageFileForm); - pageFileForm.addProcessListener(pageFileForm); // process called from validationListener - - // Storage for file upload information - pageFileForm.fileUploadContent = new RequestLocal(); - pageFileForm.fileUploadUsedINSO = new RequestLocal(); - } - - - /* overridable method to put together the PageTextForm Component */ - protected void addTextWidgets(final PageTextForm pageTextForm) { - - ColumnPanel panel = (ColumnPanel) pageTextForm.getPanel(); - panel.setBorder(false); - panel.setPadColor("#FFFFFF"); - panel.setColumnWidth(1, "20%"); - panel.setColumnWidth(2, "80%"); - panel.setWidth("100%"); - -// c.add(new Label( -// GlobalizationUtil.globalize("cms.ui.authoring.text_type"))); -// c.mimeWidget = new SingleSelect(PageTextForm.MIME_TYPE); -// c.mimeWidget.setClassAttr("displayOneOptionAsLabel"); -// setMimeTypeOptions(c.mimeWidget); -// c.add(c.mimeWidget, ColumnPanel.LEFT); - pageTextForm.add(new Label(new GlobalizedMessage( - "cms.ui.authoring.edit_body_text", - CmsConstants.CMS_BUNDLE)), - ColumnPanel.LEFT | ColumnPanel.FULL_WIDTH); - - pageTextForm.textWidget = new CMSDHTMLEditor(PageTextForm.TEXT_ENTRY); - pageTextForm.textWidget.setRows(25); - pageTextForm.textWidget.setCols(40); - // cg - sets FCKEditor size - closer to actual published page - // width, and similar size as htmlarea. - // could be configurable - unset means default 100% x 400px - pageTextForm.textWidget.setMetaDataAttribute("width", "575"); - pageTextForm.textWidget.setMetaDataAttribute("height", "500"); - pageTextForm.textWidget.setWrap(CMSDHTMLEditor.SOFT); - pageTextForm.add(pageTextForm.textWidget, ColumnPanel.LEFT - | ColumnPanel.FULL_WIDTH); - - pageTextForm.saveCancelSection = new SaveCancelSection(); - pageTextForm.add(pageTextForm.saveCancelSection, ColumnPanel.FULL_WIDTH); - - // optionally, we clear the text of MSWord tags every time - // the text is submitted/saved - if (CMSConfig.getConfig().isSaveTextCleansWordTags()) { - pageTextForm.saveCancelSection.getSaveButton().setOnClick( - "wordClean_" - + PageTextForm.TEXT_ENTRY - + "();"); - } - - pageTextForm.addInitListener(pageTextForm); - pageTextForm.addProcessListener(pageTextForm); - - } - - /** - * Registers global state parameter for cancelling streamlined creation - */ - @Override - public void register(final Page page) { - super.register(page); - page.addGlobalStateParam(streamlinedCreationParam); - page.addRequestListener(this); - } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBody.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBody.java new file mode 100755 index 000000000..b09510bac --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBody.java @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.cms.ui.authoring; + +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Resettable; +import com.arsdigita.bebop.event.RequestEvent; +import com.arsdigita.bebop.event.RequestListener; +import com.arsdigita.bebop.form.SingleSelect; +import com.arsdigita.bebop.parameters.StringParameter; + +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.ui.ContentItemPage; +import com.arsdigita.cms.ui.FileUploadSection; +import com.arsdigita.cms.ui.SecurityPropertyEditor; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.toolbox.ui.DomainObjectPropertySheet; + +import org.arsdigita.cms.CMSConfig; +import org.libreccm.l10n.LocalizedString; +import org.librecms.CmsConstants; + +/** + * Displays the mime-type and the body of a single {@code TextAsset}. Maintains + * a form or uploading files into the text body of the asset, and a form for + * editing the text of the asset. + *

+ * Unlike most other authoring components, this component does not require the + * asset to exist. If the asset does not exist (i.e., if + * !m_assetModel.isSelected(state)), the upload and editing forms + * will create a new asset and set it in the model by calling + * setSelectedObject on the asset selection model. Child classes + * should override the {@link #createTextAsset(PageState)} method in to create a + * valid text asset. + *

+ * This component is used primarily in {@link GenericArticleBody} and + * {@link com.arsdigita.cms.ui.templates.TemplateBody} + * + * Note: In CCM NG (version 7 and newer) {@code TextAsset} does not + * longer exist. Instead fields of type {@link LocalizedString} are used. This + * class has been adapted to use {@link LocalizedString}. The name of the class + * etc. has been kept to make the migration easier. + * + * @author Stanislav Freidin (sfreidin@arsdigita.com) + * @version Jens Pelzetter + */ +public abstract class TextBody + extends SecurityPropertyEditor + implements Resettable, AuthoringStepComponent, RequestListener { + + public static final String FILE_UPLOAD = "file"; + public static final String TEXT_ENTRY = "text"; + + private static final String STREAMLINED_DONE = "1"; + private static final CMSConfig CMS_CONFIG = CMSConfig.getConfig(); + + private final StringParameter streamlinedCreationParam; + private final StringParameter selectedLanguageParam; + private final ItemSelectionModel itemSelectionModel; + + /** + * Construct a new GenericArticleBody component + * + * @param assetModel The {@link ItemSelectionModel} which will be + * responsible for maintaining the current + * asset + * @param selectedLanguageParam Parameter for the currently selected locale. + */ + public TextBody(final ItemSelectionModel assetModel, + final StringParameter selectedLanguageParam) { + + this(assetModel, null, selectedLanguageParam); + } + + /** + * Construct a new GenericArticleBody component + * + * @param itemSelectionModel The {@link ItemSelectionModel} which will be + * responsible for maintaining the current asset + * @param authoringKitWizard The parent wizard which contains the form. + * The form may use the wizard's methods, such + * as stepForward and stepBack, in its process + * listener. + * @param selectedLangugeParam Parameter for the currently selected locale. + */ + public TextBody(final ItemSelectionModel itemSelectionModel, + final AuthoringKitWizard authoringKitWizard, + final StringParameter selectedLangugeParam) { + + super(); + this.itemSelectionModel = itemSelectionModel; + + if (authoringKitWizard == null) { + streamlinedCreationParam = new StringParameter("item_body_done"); + } else { + streamlinedCreationParam = new StringParameter( + String.format("%s_body_done", + authoringKitWizard + .getContentType() + .getContentItemClass() + .getName())); + } + + this.selectedLanguageParam = selectedLangugeParam; + + if (!CMS_CONFIG.isHideTextAssetUploadFile()) { + final PageFileForm pageFileForm = getPageFileForm(); + add(FILE_UPLOAD, + new GlobalizedMessage("cms.ui.upload", CmsConstants.CMS_BUNDLE), + pageFileForm, + pageFileForm.getSaveCancelSection().getCancelButton()); + } + + final PageTextForm pageTextForm = new PageTextForm(this); + add(TEXT_ENTRY, + new GlobalizedMessage("cms.ui.edit", CmsConstants.CMS_BUNDLE), + pageTextForm, + pageTextForm.getSaveCancelSection().getCancelButton()); + + // Specify full path to properties of the text asset + final DomainObjectPropertySheet sheet = getTextBodyPropertySheet( + itemSelectionModel); + sheet.add(new GlobalizedMessage("cms.ui.article.text", + CmsConstants.CMS_BUNDLE), + getTextPropertyName()); + + setDisplayComponent(sheet); + + getDisplayPane().setClassAttr("invertedPropertyDisplay"); + + } + + /** + * Determines the name of the property holding the text. + * + * @return The name of the property holding the text. + */ + protected abstract String getTextPropertyName(); + + protected DomainObjectPropertySheet getTextBodyPropertySheet( + final ItemSelectionModel itemSelectionModel) { + + final DomainObjectPropertySheet sheet = new DomainObjectPropertySheet( + itemSelectionModel); + + return sheet; + +// return new TextBodyPropertySheet(itemSelectionModel, +// selectedLanguageParam); + } + + /** + * Adds the options for the mime type select widget of + * GenericArticleForm and sets the default mime type. + * + * @param mimeSelect + */ + protected void setMimeTypeOptions(final SingleSelect mimeSelect) { + FileUploadSection.addMimeOptions(mimeSelect, "text"); + mimeSelect.setOptionSelected("text/html"); + } + + /** + * To be overwritten by subclasses, should return the text for the currently + * selected locale. + * + * @param state The current page state + * + * @return The text of the currently selected locale. + */ + public abstract String getText(final PageState state); + + /** + * Reset this component to its original state + * + * @param state the current page state + */ + @Override + public void reset(final PageState state) { + showDisplayPane(state); + } + + /** + * Update the text for the currently selected locale. + * + * @param state the current page state + * @param text the new next text for the currently selected locale. + */ + protected abstract void updateText(PageState state, String text); + + /** + * Return the ItemSelectionModel which will be used to maintain + * the current text asset + * + * @return + */ + public ItemSelectionModel getItemSelectionModel() { + return itemSelectionModel; + } + + /** + * Forward to the next step if the streamlined creation parameter is turned + * on _and_ the streamlined_creation global state parameter is set to + * 'active' + * + * @param state the PageState + */ + protected void maybeForwardToNextStep(final PageState state) { + if (ContentItemPage.isStreamlinedCreationActive(state) + && !STREAMLINED_DONE. + equals(state.getValue(streamlinedCreationParam))) { + state.setValue(streamlinedCreationParam, STREAMLINED_DONE); + fireCompletionEvent(state); + } + } + + /** + * Cancel streamlined creation for this step if the streamlined creation + * parameter is turned on _and_ the streamlined_creation global state param + * is set to 'active' + * + * @param state the PageState + */ + protected void cancelStreamlinedCreation(final PageState state) { + if (ContentItemPage.isStreamlinedCreationActive(state)) { + state.setValue(streamlinedCreationParam, STREAMLINED_DONE); + } + } + + /** + * Open the edit component if the streamlined creation parameter is turned + * on _and_ the streamlined_creation global state param is set to 'active' + * + * @param event + */ + @Override + public void pageRequested(final RequestEvent event) { + + final PageState state = event.getPageState(); + + if (ContentItemPage.isStreamlinedCreationActive(state) + && !STREAMLINED_DONE. + equals(state.getValue(streamlinedCreationParam))) { + showComponent(state, TEXT_ENTRY); + } + //} + + } + + /** + * This is the form that is used to upload files. This method can be used so + * that a subclass can use their own subclass of PageFileForm. + * + * @return The form for uploading a text. + */ + protected PageFileForm getPageFileForm() { + return new PageFileForm(this); + } + + protected String getDefaultMimeType() { + return "text/plain"; + } + + /** + * Registers global state parameter for cancelling streamlined creation + */ + @Override + public void register(final Page page) { + super.register(page); + page.addGlobalStateParam(streamlinedCreationParam); + page.addRequestListener(this); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBodyPropertySheet.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBodyPropertySheet.java similarity index 93% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBodyPropertySheet.java rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBodyPropertySheet.java index 78300f2aa..1bbfac4a4 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBodyPropertySheet.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBodyPropertySheet.java @@ -42,17 +42,17 @@ import org.libreccm.l10n.LocalizedString; * it because it uses so many private inner classes * */ -public class TextAssetBodyPropertySheet extends DomainObjectPropertySheet { +public class TextBodyPropertySheet extends DomainObjectPropertySheet { /** * Construct a new TextAssetBodyPropertySheet * - * @param objModel The selection model which feeds domain objects to this - * property sheet. + * @param objModel The selection model which feeds domain + * objects to this property sheet. * @param selectedLanguageParam * */ - public TextAssetBodyPropertySheet( + public TextBodyPropertySheet( final ItemSelectionModel objModel, final StringParameter selectedLanguageParam) { @@ -62,8 +62,8 @@ public class TextAssetBodyPropertySheet extends DomainObjectPropertySheet { } // Build up the object properties model from the iterator over all properties - private static class TextAssetBodyPropertiesModel implements - PropertySheetModel { + private static class TextAssetBodyPropertiesModel + implements PropertySheetModel { // public final static String MIME_TYPE_KEY // = TextAssetBodyLabelCellRenderer.MIME_TYPE_KEY; @@ -140,8 +140,8 @@ public class TextAssetBodyPropertySheet extends DomainObjectPropertySheet { public PropertySheetModel makeModel(final PropertySheet sheet, final PageState state) { - TextAssetBodyPropertySheet propSheet - = (TextAssetBodyPropertySheet) sheet; + TextBodyPropertySheet propSheet + = (TextBodyPropertySheet) sheet; throw new UnsupportedOperationException("ToDo"); } diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/Article.java b/ccm-cms/src/main/java/org/librecms/contenttypes/Article.java index ecace1344..5101b08e2 100644 --- a/ccm-cms/src/main/java/org/librecms/contenttypes/Article.java +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/Article.java @@ -19,6 +19,7 @@ package org.librecms.contenttypes; import com.arsdigita.cms.contenttypes.ui.ArticlePropertiesStep; +import com.arsdigita.cms.ui.authoring.ArticleTextBody; import com.arsdigita.cms.ui.authoring.PageCreateForm; import java.io.Serializable; @@ -57,7 +58,15 @@ import org.librecms.contentsection.ContentItem; descriptionBundle = "org.librecms.CmsResources", descriptionKey = "cms.contenttypes.shared.basic_properties" + ".description", - order = 1) + order = 1), + @AuthoringStep( + component = ArticleTextBody.class, + labelBundle = "org.librecms.CmsResources", + labelKey = "cms.contenttypes.shared.body_text.title", + descriptionBundle = "org.librecms.CmsResources", + descriptionKey = "cms.contenttypes.shared.body_text.description", + order = 2 + ) }) public class Article extends ContentItem implements Serializable { diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties index 50423f1a1..2b67a44e2 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties @@ -347,3 +347,7 @@ cms.contenttypes.ui.event.event_type=Event type cms.contenttypes.ui.event.link_to_map=Link to map cms.contenttypes.ui.event.cost=Cost cms.contenttypes.ui.event.end_date_after_start_date=The end date must be later then the start date +cms.ui.upload=Upload +cms.ui.authoring.body=Text +cms.ui.article.text=Text +cms.ui.authoring.edit_body_text=Edit text diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties index 97dbb719a..994468bee 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties @@ -344,3 +344,7 @@ cms.contenttypes.ui.event.event_type=Art der Veranstaltung cms.contenttypes.ui.event.link_to_map=Link zur Karte cms.contenttypes.ui.event.cost=Kosten cms.contenttypes.ui.event.end_date_after_start_date=Das End-Datum muss nach dem Start-Datum liegen. +cms.ui.upload=Hochladen +cms.ui.authoring.body=Text +cms.ui.article.text=Text +cms.ui.authoring.edit_body_text=Text bearbeiten diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties index e81598c41..dd8807e92 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties @@ -303,3 +303,7 @@ cms.contenttypes.ui.event.event_type=Event type cms.contenttypes.ui.event.link_to_map=Link to map cms.contenttypes.ui.event.cost=Cost cms.contenttypes.ui.event.end_date_after_start_date=The end date must be later then the start date +cms.ui.upload=Upload +cms.ui.authoring.body=Text +cms.ui.article.text=Text +cms.ui.authoring.edit_body_text=Edit text