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
pull/2/head
jensp 2017-07-06 09:24:27 +00:00
parent 6a0fe2b25b
commit 0b9e5383fb
10 changed files with 818 additions and 838 deletions

View File

@ -30,11 +30,14 @@ import com.arsdigita.cms.ItemSelectionModel;
import org.librecms.contenttypes.Article; import org.librecms.contenttypes.Article;
import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess; import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
import com.arsdigita.kernel.KernelConfig;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.l10n.LocalizedString; import org.libreccm.l10n.LocalizedString;
import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemRepository;
import java.util.Locale;
/** /**
* Displays the current text body of the article and allows the user to edit it, * 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. * by uploading a file or entering text in a text box.
@ -45,10 +48,11 @@ import org.librecms.contentsection.ContentItemRepository;
* @author Stanislav Freidin (sfreidin@arsdigita.com) * @author Stanislav Freidin (sfreidin@arsdigita.com)
* @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public class GenericArticleBody extends TextAssetBody { public class ArticleTextBody extends TextBody {
protected AuthoringKitWizard authoringKitWizard; private final AuthoringKitWizard authoringKitWizard;
protected ItemSelectionModel itemSelectionModel; private final ItemSelectionModel itemSelectionModel;
private final StringParameter selectedLanguageParam;
/** /**
* Construct a new GenericArticleBody component * Construct a new GenericArticleBody component
@ -56,18 +60,20 @@ public class GenericArticleBody extends TextAssetBody {
* @param itemSelectionModel The {@link ItemSelectionModel} which will be * @param itemSelectionModel The {@link ItemSelectionModel} which will be
* responsible for loading the current item * responsible for loading the current item
* *
* @param authoringKitWizard The parent wizard which contains the form. The * @param authoringKitWizard The parent wizard which contains the form.
* form may use the wizard's methods, such as * The form may use the wizard's methods, such
* stepForward and stepBack, in its process * as stepForward and stepBack, in its process
* listener. * listener.
* @param selectedLanguageParam
*/ */
public GenericArticleBody(final ItemSelectionModel itemSelectionModel, public ArticleTextBody(final ItemSelectionModel itemSelectionModel,
final AuthoringKitWizard authoringKitWizard, final AuthoringKitWizard authoringKitWizard,
final StringParameter selectedLanguageParam) { final StringParameter selectedLanguageParam) {
super(new ItemAssetModel(null), selectedLanguageParam); super(itemSelectionModel, selectedLanguageParam);
this.itemSelectionModel = itemSelectionModel; this.itemSelectionModel = itemSelectionModel;
this.authoringKitWizard = authoringKitWizard; this.authoringKitWizard = authoringKitWizard;
this.selectedLanguageParam = selectedLanguageParam;
// Rest the component when it is hidden // Rest the component when it is hidden
authoringKitWizard authoringKitWizard
@ -91,6 +97,7 @@ public class GenericArticleBody extends TextAssetBody {
* Adds the options for the mime type select widget of * Adds the options for the mime type select widget of
* <code>GenericArticleForm</code> and sets the default mime type. * <code>GenericArticleForm</code> and sets the default mime type.
* *
* @param mimeSelect
*/ */
@Override @Override
protected void setMimeTypeOptions(final SingleSelect mimeSelect) { 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 * @param state the current page state
* * @param text the new text for the currently selected locale
* @return a valid TextAsset
*/ */
@Override @Override
protected LocalizedString createTextAsset(final PageState state) { protected void updateText(final PageState state,
final String text) {
final Article article = getGenericArticle(state); final Article article = getSelectedArticle(state);
final LocalizedString text = article.getText(); final String selectedLanguage = (String) state.getValue(
selectedLanguageParam);
// no need - cg. Text doesn't need a security context, final Locale selectedLocale;
// and ownership of text is recorded in text_pages if (selectedLanguage == null) {
// t.setParent(item); selectedLocale = KernelConfig.getConfig().getDefaultLocale();
return text; } else {
selectedLocale = new Locale(selectedLanguage);
} }
/** article.getText().addValue(selectedLocale, 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 <code>TextAsset</code>
*/
@Override
protected void updateTextAsset(final PageState state,
final LocalizedString text) {
final Article article = getGenericArticle(state);
// a.setParent(t);
article.setText(text);
final ContentItemRepository itemRepo = CdiUtil final ContentItemRepository itemRepo = CdiUtil
.createCdiUtil() .createCdiUtil()
.findBean(ContentItemRepository.class); .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); return (Article) itemSelectionModel.getSelectedObject(state);
} }
@Override @Override
protected String getTextAssetName() { protected String getTextPropertyName() {
return "text"; return "text";
} }
@Override @Override
public LocalizedString getTextAsset(final PageState state) { public String getText(final PageState state) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
} final Article article = getSelectedArticle(state);
/** final String selectedLanguage = (String) state
* An ACSObjectSelectionModel that selects the current text asset for the .getValue(selectedLanguageParam);
* text page final Locale selectedLocale;
*/ if (selectedLanguage == null) {
private static class ItemAssetModel extends ItemSelectionModel { selectedLocale = KernelConfig.getConfig().getDefaultLocale();
} else {
private RequestLocal requestLocal; selectedLocale = new Locale(selectedLanguage);
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);
} }
return article.getText().getValue(selectedLocale);
} }
} }

View File

@ -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("<body");
int bodyStart_v = lowerCase.indexOf(">", bodyStart);
int bodyEnd = lowerCase.indexOf("</body>", 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;
}
}

View File

@ -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;
}
}

View File

@ -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.
* <p>
* Unlike most other authoring components, this component does not require the
* asset to exist. If the asset does not exist (i.e., if
* <code>!m_assetModel.isSelected(state)</code>), the upload and editing forms
* will create a new asset and set it in the model by calling
* <code>setSelectedObject</code> on the asset selection model. Child classes
* should override the {@link #createTextAsset(PageState)} method in to create a
* valid text asset.
* <p>
* This component is used primarily in {@link GenericArticleBody} and
* {@link com.arsdigita.cms.ui.templates.TemplateBody}
*
* <b>Note: </b> 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 <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
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
* <code>GenericArticleForm</code> 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 <code>TextAsset</code>. Child classes should override
* this method to do the right thing. The default implementation creates a
* parent-less <code>TextAsset</code> with a unique name.
*
* @param state the current page state
*
* @return a valid <code>TextAsset</code>
*/
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 <code>TextAsset</code>
*/
protected abstract void updateTextAsset(PageState state,
LocalizedString text);
/**
* Return the <code>ItemSelectionModel</code> 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("<body");
int bodyStart_v = lowerCase.indexOf(">", bodyStart);
int bodyEnd = lowerCase.indexOf("</body>", 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);
}
}

View File

@ -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.
* <p>
* Unlike most other authoring components, this component does not require the
* asset to exist. If the asset does not exist (i.e., if
* <code>!m_assetModel.isSelected(state)</code>), the upload and editing forms
* will create a new asset and set it in the model by calling
* <code>setSelectedObject</code> on the asset selection model. Child classes
* should override the {@link #createTextAsset(PageState)} method in to create a
* valid text asset.
* <p>
* This component is used primarily in {@link GenericArticleBody} and
* {@link com.arsdigita.cms.ui.templates.TemplateBody}
*
* <b>Note: </b> 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 <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
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
* <code>GenericArticleForm</code> 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 <code>ItemSelectionModel</code> 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);
}
}

View File

@ -42,17 +42,17 @@ import org.libreccm.l10n.LocalizedString;
* it because it uses so many private inner classes * it because it uses so many private inner classes
* *
*/ */
public class TextAssetBodyPropertySheet extends DomainObjectPropertySheet { public class TextBodyPropertySheet extends DomainObjectPropertySheet {
/** /**
* Construct a new TextAssetBodyPropertySheet * Construct a new TextAssetBodyPropertySheet
* *
* @param objModel The selection model which feeds domain objects to this * @param objModel The selection model which feeds domain
* property sheet. * objects to this property sheet.
* @param selectedLanguageParam * @param selectedLanguageParam
* *
*/ */
public TextAssetBodyPropertySheet( public TextBodyPropertySheet(
final ItemSelectionModel objModel, final ItemSelectionModel objModel,
final StringParameter selectedLanguageParam) { final StringParameter selectedLanguageParam) {
@ -62,8 +62,8 @@ public class TextAssetBodyPropertySheet extends DomainObjectPropertySheet {
} }
// Build up the object properties model from the iterator over all properties // Build up the object properties model from the iterator over all properties
private static class TextAssetBodyPropertiesModel implements private static class TextAssetBodyPropertiesModel
PropertySheetModel { implements PropertySheetModel {
// public final static String MIME_TYPE_KEY // public final static String MIME_TYPE_KEY
// = TextAssetBodyLabelCellRenderer.MIME_TYPE_KEY; // = TextAssetBodyLabelCellRenderer.MIME_TYPE_KEY;
@ -140,8 +140,8 @@ public class TextAssetBodyPropertySheet extends DomainObjectPropertySheet {
public PropertySheetModel makeModel(final PropertySheet sheet, public PropertySheetModel makeModel(final PropertySheet sheet,
final PageState state) { final PageState state) {
TextAssetBodyPropertySheet propSheet TextBodyPropertySheet propSheet
= (TextAssetBodyPropertySheet) sheet; = (TextBodyPropertySheet) sheet;
throw new UnsupportedOperationException("ToDo"); throw new UnsupportedOperationException("ToDo");
} }

View File

@ -19,6 +19,7 @@
package org.librecms.contenttypes; package org.librecms.contenttypes;
import com.arsdigita.cms.contenttypes.ui.ArticlePropertiesStep; import com.arsdigita.cms.contenttypes.ui.ArticlePropertiesStep;
import com.arsdigita.cms.ui.authoring.ArticleTextBody;
import com.arsdigita.cms.ui.authoring.PageCreateForm; import com.arsdigita.cms.ui.authoring.PageCreateForm;
import java.io.Serializable; import java.io.Serializable;
@ -57,7 +58,15 @@ import org.librecms.contentsection.ContentItem;
descriptionBundle = "org.librecms.CmsResources", descriptionBundle = "org.librecms.CmsResources",
descriptionKey = "cms.contenttypes.shared.basic_properties" descriptionKey = "cms.contenttypes.shared.basic_properties"
+ ".description", + ".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 { public class Article extends ContentItem implements Serializable {

View File

@ -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.link_to_map=Link to map
cms.contenttypes.ui.event.cost=Cost 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.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

View File

@ -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.link_to_map=Link zur Karte
cms.contenttypes.ui.event.cost=Kosten 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.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

View File

@ -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.link_to_map=Link to map
cms.contenttypes.ui.event.cost=Cost 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.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