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-94f89814c4dfccm-docs
parent
9d8857ac8e
commit
7a6d194526
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue