1.什么问题?

您有一个自定义要求,您发现Joget Workflow提供的内置插件或Marketplace中可用的插件  都无法满足您的要求。 

示例1:单击列表中的按钮时,下载表单的PDF版本。

示例2:提供您收集的表单数据的甘特图视图。 

示例3:Hash变量使用方便,但不提供条件检查的功能。

2.如何解决问题?

请参阅Joget Workflow支持的  插件类型,找到可以帮助您满足自定义要求的最合适的插件类型。

示例1:开发一个Datalist Action插件以显示用于生成PDF表单的按钮。

示例2:开发一个Userview Menu插件,该插件可用于将表单数据显示为甘特图。

示例3:开发一个可以执行Bean Shell脚本编写的Hash Variable插件。

3.您的插件需要什么输入信息?

找出您的插件功能/工作所需的信息。从用户的角度来看它,您将如何使用该插件。然后,从开发人员的角度来看它,使插件在更多用例中可重用。

您可以参考“  插件属性选项”,了解可以提供给插件用户的哪种输入字段。

示例1:要开发PDF Download Datalist Action插件,我们可以考虑提供以下内容作为输入。

    1. 表格ID:将用于生成PDF文件的表格。
    2. 记录ID:使用数据列表行的ID或列值来加载记录。
    3. 文件名:生成的PDF文件的文件名。
    4. 格式选项:用于格式化和自定义PDF输出的选项。 

示例2:要开发Gantt聊天用户视图菜单插件,我们可以考虑提供以下内容作为输入。

    1. 数据列表绑定器:我们可以在插件中重复使用数据列表绑定器以检索甘特图所需的数据。
    2. 映射:一个字段,用于将将从数据列表绑定程序返回的列映射到甘特图所需的数据。
    3. 样式:用于设置甘特图样式的选项。

示例3:Hash Variable插件没有为用户提供配置界面,但是要开发Bean Shell Hash Variable插件,我们需要放置Bean Shell脚本的地方。我们可以重用环境变量来存储脚本。因此,哈希变量语法将是带有环境变量键的前缀。

例如 #beanshell.EnvironmentVariableKey#

但是,这可能还不够。我们可能还需要其他方式来传递某些变量。我们可以考虑使用URL查询参数语法来传递变量,因为稍后解析起来会更容易。

例如 #beanshell.EnvironmentVariableKey [name=Joget&email=info@joget.org&message= {form.sample.message?url}]#

4.插件的输出和预期结果是什么?

普通用户(不是使用该插件提供功能的管理员用户)将如何使用以及查看其结果。

示例1:当PDF下载数据列表操作用作数据列表行或列操作时,普通用户将看到一个链接,用于下载数据列表中每行的PDF文件。单击链接后,将提示您下载PDF。

当将插件用作整个数据列表操作时,将提示下载包含每个选定行的所有生成的PDF的zip文件。

示例2:单击使用甘特图Userview菜单插件的菜单时,普通用户可以看到甘特图。用户可以导航甘特图或与甘特图进行交互。 

示例3:Bean Shell哈希变量插件适用于admin用户。一旦使用它,哈希变量将被Bean Shell解释器的输出返回所代替。

5.是否有可重用的资源/ API?

始终参考  现有的插件教程,以查找可以在任何可能的情况下引用的类似插件/插件类型。我们将尽最大努力丰富教程部分中的内容。

您可能还需要查看Utility&Service Methods,  JSON API,  Javascript API和  Bean Shell编程指南的文档  。这些文档可能包含一些可以帮助您进行开发的方法/示例。

示例1:要开发PDF Download Datalist Action插件,我们可以重用FormPdfUtil中的方法  以生成PDF表单。我们也可以参考Datalist Form Data Delete Action插件的源代码。除此之外, 当导出表单电子邮件工具也使用FormPdfUtil中的方法时,我们可以参考导出表单电子邮件工具中可以在插件中提供哪种插件属性选项。

示例2:要开发甘特图Userview Menu插件,我们可以参考所有Userview Menu插件的源代码。从那里,我们可以更好地了解如何使用FreeMaker  语法为插件制作模板  。 

示例3:要开发Bean Shell哈希变量插件,我们可以参考所有哈希变量插件和Bean Shell插件的源代码。特别是,我们可以参考《环境变量哈希变量》插件,了解如何使用变量键检索环境变量。我们也可以参考Bean Shell Tool或Bean Shell Form Binder插件,以了解如何使用Bean Shell解释器执行脚本。

6.准备您的开发环境

a.您将需要  准备并构建Joget Open Source 。我们将使用“ wflow-plugin-archetype”模块为我们的插件生成一个Maven项目。

b.生成一个Maven项目。

生成的项目文件将放置在命令提示符下指定的目录中,例如:在“ C:\”中运行命令会将项目文件放置在C驱动器的根目录中。

为了获得正确的jogetDependencyVersion以便构建具有正确依赖关系的正确项目文件,请检查在以下目录下的“ .m2”文件夹中指定的文件名:

C:\ Users \(您的计算机名)\.m2 \ repository \ org \ joget \ wflow-core \ 5.0.11

-  为Window运行以下命令 

"C:\Joget Source Code\wflow-plugin-archetype\create-plugin.bat" packageName pluginFolderName jogetDependencyVersion

-  在Linux或Mac上运行以下命令

/joget_src/wflow-plugin-archetype/create-plugin.sh packageName pluginFolderName jogetDependencyVersion

-Mac中的示例屏幕截图:                                                                                                                                        
 

c.使用您喜欢的IDE打开/导入maven项目。 

7.开始编写代码吧!

a.扩展插件类型的抽象类

请参阅“插件类型”中列出的插件类型的文档  。查找您的插件需要扩展和实现的抽象类和接口。

示例:要开发Userview Menu插件,插件类需要扩展  org.joget.apps.userview.model.UserviewMenu 抽象类。

b.实现所有抽象方法

插件将必须实现  Plugin Base Abstract Class and Interface的抽象方法,以及插件类型的各个抽象类和接口的抽象方法。 

示例:要开发  Userview Menu插件,该插件必须实现以下方法。有关每种方法的详细信息,请参阅插件文档。

  • getCategory
  • getClassName
  • getDecoratedMenu
  • getDescription
  • getIcon
  • getLabel
  • getName
  • getPropertyOptions
  • getRenderPage
  • getVersion
  • isHomePageSupported

c.管理插件的依赖库

由“ wflow-plugin-archetype”模块生成的插件文件夹是一个maven项目。因此,我们将使用Maven  提供  的依赖机制

d.准备您的插件国际化(i18n)

要准备好插件i18n,我们需要为插件创建消息资源束属性文件。

  • 在“ [Plugin项目目录]/src/main/resources/message”目录中创建具有插件类名称的属性文件。 

    示例:对于名为“ GanttChartMenu”的插件,我们需要在“ [Plugin项目目录] / src / main / resources / message”目录下创建一个“ GanttChartMenu.properties”文件。 

    GanttChartMenu.properties文件的样本内容

    org.joget.sample.GanttChartMenu.pluginLabel=Gantt Chart
    org.joget.sample.GanttChartMenu.pluginDesc=To display form data in Gantt Chart layout
    userview.ganttChart.label.title=Title
    userview.ganttChart.label.week=Week
  • 使用PluginManagerAppPluginUtil的 getMessage(String key,String pluginName,String translationPath)   检索i18n标签。

    示例:在getLabel和getDescription方法中使用getMessage方法可返回i18n标签和描述。

    public String getLabel() {
        return AppPluginUtil.getMessage("org.joget.sample.GanttChartMenu.pluginLabel", getClassName(), "message/GanttChartMenu");
    }
    public String getDescription() {
        return AppPluginUtil.getMessage("org.joget.sample.GanttChartMenu.pluginDesc", getClassName(), "message/GanttChartMenu");
    }
    
    
  • 我们可以在“ 插件属性选项 ”的JSON中使用“ @@message.key@@”  。

    示例:对于GanttChartMenu插件的属性选项,下面显示了getPropertyOptions方法和GanttChartMenu.json文件的示例代码实现。

    public String getPropertyOptions() {
        return AppUtil.readPluginResource(getClassName(), "/properties/GanttChartMenu.json", null, true, "message/GanttChartMenu");
    }
    [{
        title : '@@userview.ganttChart.edit@@',
        properties : [{
            name : 'id',
            label : 'Id',
            type : 'hidden'
        },
        {
            name : 'customId',
            label : '@@userview.ganttChart.customId@@',
            type : 'textfield',
            regex_validation : '^[a-zA-Z0-9_]+$',
            validation_message : '@@userview.ganttChart.invalidId@@'
        },
        {
            name : 'label',
            label : '@@userview.ganttChart.label@@',
            type : 'textfield',
            required : 'True',
            value : '@@userview.ganttChart.label.value@@'
        }]
    }]
  •  每当检索HTML模板时,将转换文件路径传递给PluginManager 的 getPluginFreeMarkerTemplate(Map data, final String pluginName, final String templatePath, String translationPath) 方法  。传递翻译文件路径后,我们可以在freemarker模板中使用“ @@message.key@@”来检索i18n标签。

    示例:对于GanttChartMenu插件的getRenderPage方法,下面显示了getRenderPage方法的示例代码实现和FreeMarker模板的“ GanttChartMenu.ftl”。 

    public String getRenderPage() {
        Map model = new HashMap();
        model.put("request", getRequestParameters());
        model.put("element", this);
         
        PluginManager pluginManager = (PluginManager)AppUtil.getApplicationContext().getBean("pluginManager");
        String content = pluginManager.getPluginFreeMarkerTemplate(model, getClasstName(), "/templates/GanttChartMenu.ftl", "message/GanttChartMenu");
        return content;
    }
    
    
    <div>
        <h1>@@userview.ganttChart.label.title@@ : ${element.properties.title!}</h1>
    </div>
    
    
  • 用下划线和语言代码对插件类名称进行后缀修复,以创建其他语言的消息资源包属性文件。 
    • 示例:GanttChartMenu_zh_CN.properties

e.将插件注册到Felix框架

您会发现在插件maven项目的软件包中自动生成了一个名为“ Activator.java”的类。该类用于将插件类注册到  Felix Framework。如果您的插件不是OSGI插件,则无需执行此操作。

在激活器类的start方法中,将插件类添加到“ registrationList”变量中。

public void start(BundleContext context) {
    registrationList = new ArrayList<ServiceRegistration>();
 
    //Register plugin here
    registrationList.add(context.registerService(MyPlugin.class.getName(), new MyPlugin(), null));
}


完成上述所有步骤后,您可以使用Maven使用IDE构建项目。您也可以在项目目录中运行“ mvn clean install”命令进行构建。构建项目后,将在插件项目文件夹中的“ target”文件夹下创建一个jar文件。将插件jar上传到“  管理插件”以测试您的插件。
f.构建并测试

示例:在NetBeans中,右键单击项目名称,然后选择“清理并生成”。

8.更进一步,分享或出售

您已经完成了一个非常有用的插件。不要只是将其自己保存,在Joget Marketplace中共享或出售您的插件,  甚至更好,您还可以在我们的知识库中编写一个教程,与他人分享您的工作。要分享或出售您的插件,请发送电子邮件至info@joget.org


  • No labels