001/*
002 *  Copyright 2022 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.forms.workflow;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.stream.Collectors;
023
024import org.apache.avalon.framework.configuration.Configuration;
025import org.apache.avalon.framework.configuration.ConfigurationException;
026import org.apache.avalon.framework.configuration.DefaultConfiguration;
027import org.apache.commons.collections.ListUtils;
028
029import org.ametys.cms.clientsideelement.WorkflowStepsClientSideElement;
030import org.ametys.core.ui.Callable;
031import org.ametys.runtime.i18n.I18nizableText;
032
033import com.opensymphony.workflow.loader.ActionDescriptor;
034import com.opensymphony.workflow.loader.WorkflowDescriptor;
035
036/**
037 * This class creates multiple toggle buttons each representing a workflow step on form entries
038 */
039public abstract class AbstractFormEntriesWorkflowStepsClientSideElement extends WorkflowStepsClientSideElement
040{
041    @Override
042    protected void _configureWorkflowStep(WorkflowDescriptor workflowDescriptor, Integer stepId, Map<String, Object> stepParameters, Configuration stepConfiguration, List<Integer> allowedActionIds) throws ConfigurationException
043    {
044        super._configureWorkflowStep(workflowDescriptor, stepId, stepParameters, stepConfiguration, allowedActionIds);
045        
046        List<Integer> sendMailIds = new ArrayList<>();
047        
048        List<Integer> currentStepActions = workflowDescriptor.getStep(stepId)
049                .getActions()
050                .stream()
051                .mapToInt(action -> ((ActionDescriptor) action).getId())
052                .boxed()
053                .collect(Collectors.toList());
054        List<Integer> allowedStepActions = ListUtils.intersection(currentStepActions, allowedActionIds);
055
056        if (stepConfiguration != null)
057        {
058            Configuration stepWorkflowSendMail = stepConfiguration.getChild("send-mail", false);
059            if (stepWorkflowSendMail != null)
060            {
061                sendMailIds.addAll(_configureWorkflowStepActions(workflowDescriptor.getName(), stepId, currentStepActions, allowedStepActions, stepWorkflowSendMail));
062            }
063            else
064            {
065                sendMailIds.addAll(allowedStepActions);
066            }
067        }
068        else
069        {
070            sendMailIds.addAll(allowedStepActions);
071        }
072        
073        stepParameters.put("workflow-send-mail-ids", sendMailIds);
074    }
075    
076    @Override
077    protected Script _configureScript(Configuration configuration) throws ConfigurationException
078    {
079        List<ScriptFile> scriptsImports = _configureImports(configuration.getChild("scripts"));
080        List<ScriptFile> cssImports = _configureImports(configuration.getChild("css"));
081        
082        Script script = new Script(this.getId(), "", scriptsImports, cssImports, new HashMap<>());
083        List<ScriptFile> scriptFiles = _getAdditionalScriptFiles();
084        script.getScriptFiles().addAll(scriptFiles);
085        
086        return script;
087    }
088
089    /**
090     * Get the additional script files to import
091     * @return the list of script
092     */
093    protected abstract List<ScriptFile> _getAdditionalScriptFiles();
094    
095    @Override
096    protected String _getDefaultPluginName()
097    {
098        return "forms";
099    }
100    
101    @SuppressWarnings("unchecked")
102    @Override
103    protected void _additionalMenuItemConfiguration(Configuration itemConf, DefaultConfiguration classConf, int actionId, Map<String, Object> parameters)
104    {
105        super._additionalMenuItemConfiguration(itemConf, classConf, actionId, parameters);
106        
107        // Multiselection enabled ?
108        DefaultConfiguration multiselectConf = new DefaultConfiguration("selection-enable-multiselection");
109        multiselectConf.setValue(itemConf.getChild("menu-" + actionId + "-enable-multiselection").getValueAsBoolean(true));
110        classConf.addChild(multiselectConf);
111
112        // Send mail
113        DefaultConfiguration sendMailConf = new DefaultConfiguration("send-mail");
114        sendMailConf.setValue(itemConf.getChild("menu-" + actionId + "-send-mail").getValueAsBoolean(((List<Integer>) parameters.get("workflow-send-mail-ids")).contains(actionId)));
115        classConf.addChild(sendMailConf);
116        
117        // Dialog title for the mails
118        if (itemConf.getChild("menu-" + actionId + "-dialog-title", false) != null)
119        {
120            DefaultConfiguration dialogTitleConf = new DefaultConfiguration("dialog-title");
121            dialogTitleConf.setAttribute("i18n", itemConf.getChild("menu-" + actionId + "-dialog-title").getAttribute("i18n", "true"));
122            dialogTitleConf.setValue(itemConf.getChild("menu-" + actionId + "-dialog-title").getValue(null));
123            classConf.addChild(dialogTitleConf);
124        }
125        
126        // i18n key for the subject  
127        if (itemConf.getChild("menu-" + actionId + "-subject-key", false) != null)
128        {
129            DefaultConfiguration subjectKeyConf = new DefaultConfiguration("subject-key");
130            subjectKeyConf.setAttribute("i18n", itemConf.getChild("menu-" + actionId + "-subject-key").getAttribute("i18n", "true"));
131            subjectKeyConf.setValue(itemConf.getChild("menu-" + actionId + "-subject-key").getValue(null));
132            classConf.addChild(subjectKeyConf);
133        }
134        
135        // i18n key for the body
136        if (itemConf.getChild("menu-" + actionId + "-body-key", false) != null)
137        {
138            DefaultConfiguration bodyKeyConf = new DefaultConfiguration("body-key");
139            bodyKeyConf.setAttribute("i18n", itemConf.getChild("menu-" + actionId + "-body-key").getAttribute("i18n", "true"));
140            bodyKeyConf.setValue(itemConf.getChild("menu-" + actionId + "-body-key").getValue(null));
141            classConf.addChild(bodyKeyConf);
142        }
143            
144    }
145
146    @Override
147    protected void _configureDefaultDescriptions(Map<String, Object> parameters)
148    {
149        // One entry selected
150        if (!parameters.containsKey("entryselected-description"))
151        {
152            parameters.put("entryselected-description", new I18nizableText("plugin.forms", "ENTRY_WORKFLOW_DESCRIPTION"));
153        }
154        
155        // Several entries selected
156        if (!parameters.containsKey("several-entryselected-description"))
157        {
158            parameters.put("several-entryselected-description", new I18nizableText("plugin.forms", "ENTRIES_WORKFLOW_DESCRIPTION"));
159        }
160        
161        // Empty selection
162        if (!parameters.containsKey("selection-description-empty"))
163        {
164            parameters.put("selection-description-empty", new I18nizableText("plugin.forms", "ENTRY_WORKFLOW_NOSELECTION_DESCRIPTION"));
165        }
166        
167        // No match selection
168        if (!parameters.containsKey("selection-description-nomatch"))
169        {
170            parameters.put("selection-description-nomatch", new I18nizableText("plugin.forms", "ENTRY_WORKFLOW_NOMATCH_DESCRIPTION"));
171        }
172        
173        // Multiselection forbidden
174        if (!parameters.containsKey("selection-description-multiselectionforbidden"))
175        {
176            parameters.put("selection-description-multiselectionforbidden", new I18nizableText("plugin.forms", "ENTRY_WORKFLOW_NOMULTISELECT_DESCRIPTION"));
177        }
178        
179        // No available action
180        if (!parameters.containsKey("noaction-available-description"))
181        {
182            parameters.put("noaction-available-description", new I18nizableText("plugin.forms", "ENTRY_WORKFLOW_NOACTIONAVAILABLE_DESCRIPTION"));
183        }
184        
185        // Refreshing
186        if (!parameters.containsKey("refreshing-description"))
187        {
188            parameters.put("refreshing-description", new I18nizableText("plugin.forms", "ENTRY_WORKFLOW_REFRESH_DESCRIPTION"));
189        }
190    }
191
192    /**
193     * Get the workflow state of contents
194     * @param entryIds The ids of the selected entries
195     * @param formId The id of the form
196     * @param scriptId The id of the script
197     * @return The workflow state as a map
198     */
199    @Callable
200    public abstract Map<String, Object> getWorkflowState(List<Object> entryIds, String formId, String scriptId);
201    
202}