如何开发一个表单提交统计生成器(MySQL)

Skip to end of metadata



Go to start of metadata


 

在本教程中,我们将遵循开发插件的  指导方针  来开发我们的表单提交统计信息生成器。 有关更多详细信息步骤,请参阅第一个教程  如何开发一个Bean Shell哈希变量插件


1.什么问题?

我们有2个SQL Chart菜单(使用的查询依赖于MySQL)来显示表单数据提交统计信息,这2个菜单总是需要复制不同的表单。


2.你有什么想法来解决这个问题?

我们可以开发一个  Generator插件  来简化这个过程,为其他表单复制2个SQL Chart菜单。


3.你的插件需要什么输入?

要为我们的2个SQL图表菜单开发Generator插件,我们可以考虑提供以下内容作为输入。

  1. Userview ID:哪个用户视图添加这2个SQL菜单
  2. “类别”标签,“菜单”标签和“图表”标签中的一些标签更改选项

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

2 SQL Chart菜单将被添加到选定的用户视图下一个新的类别。其中一个菜单将显示每月提交图表,另一个将显示基于年份和月份过滤器的每日提交图表。

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

首先,我们可以在现有的用户视图之一中构建我们的2个SQL图表菜单。然后,将包含我们的2个SQL Chart菜单的类别的JSON定义复制到Userview Builder的底部的“ADVANCED:JSON Definition” 。

我们将得到我们的类别的JSON定义如下。请注意在2个SQL图表菜单中使用的查询依赖于MySQL数据库。

{

    "className""org.joget.apps.userview.model.UserviewCategory",

    "properties": {

        "id""category-8722A52FFBB64D058E2CD41174922807",

        "label""Proposal Form Statistics"

    },

    "menus": [{

        "className""org.joget.plugin.enterprise.SqlChartMenu",

        "properties": {

            "id""807F165BFA9C4BB589E5B52E4C071250",

            "customId""crm_proposal_monthly",

            "label""Monthly Submission Chart",

            "chartType""bar",

            "title""Proposal Form Monthly Submission Chart",

            "categoryAxisLabel""Month",

            "xAxisDisplayAS""",

            "valueAxisLabel""Number",

            "yaxisPrefix""",

            "showLegend""",

            "showValueLabel""true",

            "stack""",

            "horizontal""",

            "chartWidth""100%",

            "chartHeight""80%",

            "colors""",

            "query""SELECT DATE_FORMAT(STR_TO_DATE(m.monthYear, '%c-%Y'),'%b %y') as monthYear, COUNT(fd.dateCreated) AS 'Number'\nFROM \n(\n   SELECT my.month, CONCAT(my.month, '-', IF(('#requestParam.year?sql#' REGEXP '^[0-9]{4}$'), '#requestParam.year?sql#' , '#date.yyyy?sql#')) AS monthYear FROM (\n       SELECT 1 AS month UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12\n   ) my\n) m\nLEFT JOIN \n(\n\t select dateCreated FROM app_fd_crm_proposal\n) fd\nON m.monthYear=DATE_FORMAT(fd.dateCreated,'%c-%Y')\nGROUP BY monthYear\nORDER BY m.month",

            "customHeader""<div class=\"filter\">\n   <form action=\"?\" method=\"GET\">\n       <label>Year: <\/label><input name=\"year\" value=\"#requestParam.year?html#\"\/>\n       <input type=\"submit\" value=\"Show\"\/>\n   <\/form>\n<\/div>\n<script>\n   $(function(){\n       if ($(\"[name='year']\").val() === \"\") {\n           $(\"[name='year']\").val(\"#date.yyyy#\");\n       }\n   });\n<\/script>\n<br\/>\n<br\/>",

            "customFooter""",

            "datasource""default",

            "keyName"""

        }

    }, {

        "className""org.joget.plugin.enterprise.SqlChartMenu",

        "properties": {

            "id""39E2163319D84FD693D164D92FA93C06",

            "customId""crm_proposal_daily",

            "label""Daily Submission Chart",

            "chartType""bar",

            "title""Proposal Form Daily Submission Chart",

            "categoryAxisLabel""Date",

            "xAxisDisplayAS""",

            "valueAxisLabel""Number",

            "yaxisPrefix""",

            "showLegend""",

            "showValueLabel""true",

            "stack""",

            "horizontal""true",

            "chartWidth""100%",

            "chartHeight""80%",

            "colors""",

            "query""SELECT d.date_field, COUNT(fd.dateCreated) AS 'Number'\nFROM\n(\n   SELECT\n       MAKEDATE(IF(('#requestParam.year?sql#' REGEXP '^[0-9]{4}$'), '#requestParam.year?sql#' , '#date.yyyy?sql#'),1) +\n       INTERVAL (IF(('#requestParam.month?sql#' REGEXP '^[0-9]{2}$'), '#requestParam.month?sql#' , '#date.MM?sql#') -1) MONTH +\n       INTERVAL daynum DAY date_field\n   FROM\n   (\n       SELECT t*10+u daynum\n       FROM\n           (SELECT 0 t UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) A,\n           (SELECT 0 u UNION SELECT 1 UNION SELECT 2 UNION SELECT 3\n           UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7\n           UNION SELECT 8 UNION SELECT 9) B\n       ORDER BY daynum\n   ) AA\n) d\nLEFT JOIN \n(\n\t select dateCreated FROM app_fd_crm_proposal\n) fd\nON d.date_field=DATE_FORMAT(fd.dateCreated,'%Y-%m-%d')\nWHERE DATE_FORMAT(d.date_field,'%m') = IF(('#requestParam.month?sql#' REGEXP '^[0-9]{2}$'), '#requestParam.month?sql#' , '#date.MM?sql#')\nGROUP BY d.date_field\nORDER BY d.date_field desc",

            "customHeader""<div class=\"filter\">\n   <form action=\"?\" method=\"GET\">\n       <label>Year: <\/label><input name=\"year\" value=\"#requestParam.year?html#\"\/>&nbsp;&nbsp;&nbsp;\n       <label>Month: <\/label><select name=\"month\"\/>\n           <option value=\"01\">Jan<\/option>\n           <option value=\"02\">Feb<\/option>\n           <option value=\"03\">Mar<\/option>\n           <option value=\"04\">Apr<\/option>\n           <option value=\"05\">May<\/option>\n           <option value=\"06\">Jun<\/option>\n           <option value=\"07\">Jul<\/option>\n           <option value=\"08\">Aug<\/option>\n           <option value=\"09\">Sep<\/option>\n           <option value=\"10\">Oct<\/option>\n           <option value=\"11\">Nov<\/option>\n           <option value=\"12\">Dec<\/option>\n       <\/select>\n       <input type=\"submit\" value=\"Show\"\/>\n   <\/form>\n<\/div>\n<script>\n   $(function(){\n       if ($(\"[name='year']\").val() === \"\") {\n           $(\"[name='year']\").val(\"#date.yyyy#\");\n       }\n       if ($(\"[name='month']\").val() !== \"#requestParam.month?javascript#\" \n           && '#requestParam.month?javascript#' !== \"\"\n           && $(\"[name='month'] option[value='#requestParam.month?javascript#']\").length > 0 ) {\n           $(\"[name='month']\").val('#requestParam.month?javascript#');\n       } else {\n           $(\"[name='month']\").val(\"#date.MM#\");\n       }\n   });\n<\/script>\n<br\/>\n<br\/>",

            "customFooter""",

            "datasource""default",

            "keyName"""

        }

    }]

}

之后,我们可以利用  GeneratorUtil  将类别JSON定义添加到我们选择的userview JSON定义中。


6. 准备你的开发环境

我们需要始终准备好Joget Workflow Source Code,并按照这个指导方针建立起来  。 

本教程的以下内容是使用Macbook Pro和Joget源代码5.0.0版编写的。 其他平台命令请参考  如何开发插件

让我们说我们的文件夹目录如下。 

 

- Home

  - joget

    - plugins

    - jw-community

      -5.0.0

“plugins”目录是我们要创建和存储我们所有插件的文件夹,“jw-community”目录是Joget Workflow源代码存储的地方。

运行以下命令在“plugins”目录下创建一个maven项目。

cd joget/plugins/

~/joget/jw-community/5.0.0/wflow-plugin-archetype/create-plugin.sh org.joget.tutorial form_submission_statistics_generator 5.0.0

然后,shell脚本将要求我们为您的插件输入一个版本,并在生成maven项目之前要求我们确认。

Define value for property 'version': 1.0-SNAPSHOT: : 5.0.0

[INFO] Using property: package = org.joget.tutorial

Confirm properties configuration:

groupId: org.joget.tutorial

artifactId: form_submission_statistics_generator

version: 5.0.0

package: org.joget.tutorial

Y: : y

我们应该在终端上显示“BUILD SUCCESS”消息,在“plugins”文件夹中创建一个“form_submission_statistics_generator”文件夹。

用你喜欢的IDE打开maven项目。我将使用  NetBeans。 

7. 开始编码吧!

a. 继承插件类型抽象类

在“org.joget.tutorial”包下创建一个“FormSubmissionStatisticsGenerator”类。然后,使用org.joget.apps.generator.model.GeneratorPlugin  抽象类来扩展  该类。请参考  Generator插件


b. 实现所有抽象方法

像往常一样,我们必须执行所有的抽象方法。我们将使用AppPluginUtil.getMessage方法来支持i18n,并使用常量变量MESSAGE_PATH作为消息资源包目录

 

Implementation of all basic abstract methods

 Expand source


然后,我们必须为管理员用户提供一个UI来为我们的插件提供输入。在getPropertyOptions方法中,我们已经指定了我们的  插件属性选项和配置  定义文件位于“/properties/formSubmissionStatisticsGenerator.json”。让我们在“form_submission_statistics_generator / src / main”目录下创建一个目录“resources / properties”。创建目录后,在“properties”文件夹中创建一个名为“formSubmissionStatisticsGenerator.json”的文件。

在属性定义选项文件中,我们需要提供如下的选项。请注意,我们可以在我们的属性选项中使用“@@ message.key @@”语法来支持i18n。

[{

    title : '@@generator.formSubmissionStatistics.config@@',

    properties : [

    {

        name : 'userviewId',

        label : '@@generator.formSubmissionStatistics.userview@@',

        type : 'selectbox',

        value: '[default_userviewId]',

        options_ajax : '[CONTEXT_PATH]/web/json/console/app[APP_PATH]/userview/options'

    }]

},

{

    title : '@@generator.formSubmissionStatistics.advanced@@',

    properties : [

    {

        label : '@@generator.formSubmissionStatistics.label.options@@',

        type : 'header'

    },

    {

        name : 'monthlyChartTitle',

        label : '@@generator.formSubmissionStatistics.monthlyChartTitle@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.monthlyChartTitle.value@@'

    },

    {

        name : 'monthlyXAxisLabel',

        label : '@@generator.formSubmissionStatistics.monthlyXAxisLabel@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.monthlyXAxisLabel.value@@'

    },

    {

        name : 'dailyChartTitle',

        label : '@@generator.formSubmissionStatistics.dailyChartTitle@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.dailyChartTitle.value@@'

    },

    {

        name : 'dailyXAxisLabel',

        label : '@@generator.formSubmissionStatistics.dailyXAxisLabel@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.dailyXAxisLabel.value@@'

    },

    {

        name : 'yAxisLabel',

        label : '@@generator.formSubmissionStatistics.yAxisLabel@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.yAxisLabel.value@@'

    },

    {

        name : 'yearLabel',

        label : '@@generator.formSubmissionStatistics.yearLabel@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.yearLabel.value@@'

    },

    {

        name : 'monthLabel',

        label : '@@generator.formSubmissionStatistics.monthLabel@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.monthLabel.value@@'

    },

    {

        name : 'showLabel',

        label : '@@generator.formSubmissionStatistics.showLabel@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.showLabel.value@@'

    },

    {

        label : '@@generator.formSubmissionStatistics.useriewMenu.options@@',

        type : 'header'

    },

    {

        name : 'categoryLabel',

        label : '@@generator.formSubmissionStatistics.categoryLabel@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.categoryLabel.value@@'

    },

    {

        name : 'monthlyMenuId',

        label : '@@generator.formSubmissionStatistics.monthlyMenuId@@',

        type : 'textfield',

        required : 'true',

        regex_validation : '^[a-zA-Z0-9_]+$',

        validation_message : '@@generator.formSubmissionStatistics.menuId.invalidId@@',

        value : '[formId]_monthly'

    },

    {

        name : 'monthlyMenuLabel',

        label : '@@generator.formSubmissionStatistics.monthlyMenuLabel@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.monthlyMenuLabel.value@@'

    },

    {

        name : 'dailyMenuId',

        label : '@@generator.formSubmissionStatistics.dailyMenuId@@',

        type : 'textfield',

        required : 'true',

        regex_validation : '^[a-zA-Z0-9_]+$',

        validation_message : '@@generator.formSubmissionStatistics.menuId.invalidId@@',

        value : '[formId]_daily'

    },

    {

        name : 'dailyMenuLabel',

        label : '@@generator.formSubmissionStatistics.dailyMenuLabel@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.dailyMenuLabel.value@@'

    },

    {

        label : '@@generator.formSubmissionStatistics.createUserviewOptions@@',

        type : 'header',

        control_field: 'userviewId',

        control_value: '',

        control_use_regex: 'false',

    },   

    {

        name : 'userviewNewId',

        label : '@@generator.formSubmissionStatistics.userview.id@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.userview.id.value@@',

        regex_validation : '^[a-zA-Z0-9_]+$',

        validation_message : '@@generator.formSubmissionStatistics.userview.id.invalidId@@',

        control_field: 'userviewId',

        control_value: '',

        control_use_regex: 'false'

    },   

    {

        name : 'userviewName',

        label : '@@generator.formSubmissionStatistics.userview.name@@',

        type : 'textfield',

        required : 'true',

        value : '@@generator.formSubmissionStatistics.userview.name.value@@',

        control_field: 'userviewId',

        control_value: '',

        control_use_regex: 'false'

    },   

    {

        name : 'userviewDesc',

        label : '@@generator.formSubmissionStatistics.userview.description@@',

        type : 'textarea',

        rows : "3",

        control_field: 'userviewId',

        control_value: '',

        control_use_regex: 'false'

    }]

}]

在插件属性选项中,您可能会注意到我们正在使用“userviewId”属性中的“[default_userviewId]”。我们将在一些属性中使用“[formName]”和“[formId]”。所以,我们需要修改getPropertyOptions方法来迎合这个值。

 

public String getPropertyOptions() {

    String options = AppUtil.readPluginResource(getClassName(), "/properties/formSubmissionStatisticsGenerator.json"nulltrue, MESSAGE_PATH);

     

    //populate value like [formName] and [formId]

    options = GeneratorUtil.populateFormMeta(options, getFormId(), getAppDefinition());

     

    //populate value of [default_userviewId]

    options = options.replace("[default_userviewId]", GeneratorUtil.getFirstAvailableUserviewId(getAppDefinition()));

     

    return options;

}

一旦我们完成了属性选项来收集输入, 我们可以在插件的主方法,format方法中工作

 

@Override

public GeneratorResult generate() {

    GeneratorResult result = new GeneratorResult();

    AppDefinition appDef = getAppDefinition();

 

    try {

        //get userview

        UserviewDefinitionDao userviewDefinitionDao = (UserviewDefinitionDao) AppUtil.getApplicationContext().getBean("userviewDefinitionDao");

        UserviewDefinition userviewDef = null;

        String json = null;

        String userviewId = getPropertyString("userviewId");

        String userviewName;

        String userviewDesc;

        if (userviewId != null && !userviewId.isEmpty()) {        

            userviewDef = userviewDefinitionDao.loadById(userviewId, appDef);

        }

        if (userviewDef != null) {

            userviewName = userviewDef.getName();

            userviewDesc = userviewDef.getDescription();

            json = userviewDef.getJson();

        else {

            userviewId = getPropertyString("userviewNewId");

            int count = 0;

            while (isExist(userviewId, userviewDefinitionDao)) {

                count++;

                userviewId = userviewId + count;

            }

            userviewName = getPropertyString("userviewName");

            userviewDesc = getPropertyString("userviewDesc");

        }

        if (json == null || json.isEmpty()) {

            //create a new userview json

            json = GeneratorUtil.createNewUserviewJson(userviewId, userviewName, userviewDesc);

        }

         

        //add the category json to userview json

        json = GeneratorUtil.addCategoryJsonToUserviewJson(getCategoryJson(appDef), json);

        

        //Store the userview json

        if (userviewDef != null) {

            userviewDef.setJson(json);

            userviewDefinitionDao.update(userviewDef);

        }else {

            userviewDef = new UserviewDefinition();

            userviewDef.setJson(json);

            userviewDef.setId(userviewId);

            userviewDef.setName(userviewName);

            userviewDef.setAppDefinition(appDef);

            userviewDefinitionDao.add(userviewDef);

             

            //Set current published version

            final AppDefinition currentAppDef = appDef;

            TransactionTemplate transactionTemplate = (TransactionTemplate)AppUtil.getApplicationContext().getBean("transactionTemplate");

            transactionTemplate.execute(new TransactionCallback<Object>() {

                public Object doInTransaction(TransactionStatus ts) {

                    AppService appService = (AppService)AppUtil.getApplicationContext().getBean("appService");

                    appService.publishApp(currentAppDef.getId(), currentAppDef.getVersion().toString());

                    return null;

                }

            });

        }

        

        //show message to continue edit

        String editLink = WorkflowUtil.getHttpServletRequest().getContextPath() + "/web/console/app/"+appDef.getAppId()+"/"+appDef.getVersion()+"/userview/builder/"+userviewId;

        String msg = AppPluginUtil.getMessage("generator.formSubmissionStatistics.msg.success", getClassName(), MESSAGE_PATH);

        msg = msg.replace("[url]", editLink);

         

        result.setMessage(msg);

    catch (Exception e) {

        result.setError(true);

        result.setMessage(AppPluginUtil.getMessage("generator.formSubmissionStatistics.msg.error", getClassName(), MESSAGE_PATH));

        LogUtil.error(getClassName(), e, "Not able to generate the menus");

    }

     

    return result;

}

 

/**

 * Retrieves the category JSON definition

 * @param appDef

 * @return

 */

protected String getCategoryJson(AppDefinition appDef) {

    Collection<String> args = new ArrayList<String>();

     

    AppService appService = (AppService)AppUtil.getApplicationContext().getBean("appService");

    String tabelName = appService.getFormTableName(appDef, getFormId());

     

    args.add(UuidGenerator.getInstance().getUuid()); //category id

    args.add(StringUtil.escapeString(getPropertyString("categoryLabel"), StringUtil.TYPE_JSON, null)); //category label

    args.add(UuidGenerator.getInstance().getUuid()); //monthly menu uuid

    args.add(StringUtil.escapeString(getPropertyString("monthlyMenuId"), StringUtil.TYPE_JSON, null)); //monthly menu custom id

    args.add(StringUtil.escapeString(getPropertyString("monthlyMenuLabel"), StringUtil.TYPE_JSON, null)); //monthly menu label

    args.add(StringUtil.escapeString(getPropertyString("monthlyChartTitle"), StringUtil.TYPE_JSON, null)); //monthly chart title

    args.add(StringUtil.escapeString(getPropertyString("monthlyXAxisLabel"), StringUtil.TYPE_JSON, null)); //monthly x-axis label

    args.add(StringUtil.escapeString(getPropertyString("yAxisLabel"), StringUtil.TYPE_JSON, null)); //monthly y-axis label

    args.add(StringUtil.escapeString(tabelName, StringUtil.TYPE_JSON, null)); //monthly form table name

    args.add(StringUtil.escapeString(getPropertyString("yearLabel"), StringUtil.TYPE_JSON, null)); //monthly year label

    args.add(StringUtil.escapeString(getPropertyString("showLabel"), StringUtil.TYPE_JSON, null)); //monthly show button label

    args.add(UuidGenerator.getInstance().getUuid()); //daily menu uuid

    args.add(StringUtil.escapeString(getPropertyString("dailyMenuId"), StringUtil.TYPE_JSON, null)); //daily menu custom id

    args.add(StringUtil.escapeString(getPropertyString("dailyMenuLabel"), StringUtil.TYPE_JSON, null)); //daily menu label

    args.add(StringUtil.escapeString(getPropertyString("dailyChartTitle"), StringUtil.TYPE_JSON, null)); //daily chart title

    args.add(StringUtil.escapeString(getPropertyString("dailyXAxisLabel"), StringUtil.TYPE_JSON, null)); //daily x-axis label

    args.add(StringUtil.escapeString(getPropertyString("yAxisLabel"), StringUtil.TYPE_JSON, null)); //daily y-axis label

    args.add(StringUtil.escapeString(tabelName, StringUtil.TYPE_JSON, null)); //daily form table name

    args.add(StringUtil.escapeString(getPropertyString("yearLabel"), StringUtil.TYPE_JSON, null)); //daily year label

    args.add(StringUtil.escapeString(getPropertyString("monthLabel"), StringUtil.TYPE_JSON, null)); //daily month label

    args.add(StringUtil.escapeString(getPropertyString("showLabel"), StringUtil.TYPE_JSON, null)); //daily show button label

     

    String json = AppUtil.readPluginResource(getClass().getName(), "/resources/category.json", args.toArray(), truenull);

     

    return json;

}

 

/**

 * Checks for a userview is already exist

 * @param id

 * @param userviewDefinitionDao

 * @return

 */

protected boolean isExist(String id, UserviewDefinitionDao userviewDefinitionDao) {

    Long count = userviewDefinitionDao.count("AND id = ?"new String[]{id}, getAppDefinition());

    return count > 0;

}

在getCategoryJson方法中,我们将检索类别JSON定义形式“/resources/category.json”文件。让我们在“form_submission_statistics_generator / src / main”目录下创建一个目录“resources / resources”。创建目录后,在“resources”文件夹中创建一个名为“category.json”的文件。然后,复制我们之前创建的类别JSON定义,并将其粘贴到此文件中。我们将需要将一些硬编码值替换为变量,并记住将使用String.format的AppUtil.readPluginResource转义为将现有的“%”转义为“%%”,以便将值注入到文件中。

{

    "className""org.joget.apps.userview.model.UserviewCategory",

    "properties": {

        "id""category-%s",

        "label""%s"

    },

    "menus": [{

        "className""org.joget.plugin.enterprise.SqlChartMenu",

        "properties": {

            "id""%s",

            "customId""%s",

            "label""%s",

            "chartType""bar",

            "title""%s",

            "categoryAxisLabel""%s",

            "xAxisDisplayAS""",

            "valueAxisLabel""%s",

            "yaxisPrefix""",

            "showLegend""",

            "showValueLabel""true",

            "stack""",

            "horizontal""",

            "chartWidth""100%%",

            "chartHeight""80%%",

            "colors""",

            "query""SELECT DATE_FORMAT(STR_TO_DATE(m.monthYear, '%%c-%%Y'),'%%b %%y') as monthYear, COUNT(fd.dateCreated) AS 'Number'\nFROM \n(\n   SELECT my.month, CONCAT(my.month, '-', IF(('#requestParam.year?sql#' REGEXP '^[0-9]{4}$'), '#requestParam.year?sql#' , '#date.yyyy?sql#')) AS monthYear FROM (\n       SELECT 1 AS month UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12\n   ) my\n) m\nLEFT JOIN \n(\n\t select dateCreated FROM app_fd_%s\n) fd\nON m.monthYear=DATE_FORMAT(fd.dateCreated,'%%c-%%Y')\nGROUP BY monthYear\nORDER BY m.month",

            "customHeader""<div class=\"filter\">\n   <form action=\"?\" method=\"GET\">\n       <label>%s: <\/label><input name=\"year\" value=\"#requestParam.year?html#\"\/>\n       <input type=\"submit\" value=\"%s\"\/>\n   <\/form>\n<\/div>\n<script>\n   $(function(){\n       if ($(\"[name='year']\").val() === \"\") {\n           $(\"[name='year']\").val(\"#date.yyyy#\");\n       }\n   });\n<\/script>\n<br\/>\n<br\/>",

            "customFooter""",

            "datasource""default",

            "keyName"""

        }

    }, {

        "className""org.joget.plugin.enterprise.SqlChartMenu",

        "properties": {

            "id""%s",

            "customId""%s",

            "label""%s",

            "chartType""bar",

            "title""%s",

            "categoryAxisLabel""%s",

            "xAxisDisplayAS""",

            "valueAxisLabel""%s",

            "yaxisPrefix""",

            "showLegend""",

            "showValueLabel""true",

            "stack""",

            "horizontal""true",

            "chartWidth""100%%",

            "chartHeight""80%%",

            "colors""",

            "query""SELECT d.date_field, COUNT(fd.dateCreated) AS 'Number'\nFROM\n(\n   SELECT\n       MAKEDATE(IF(('#requestParam.year?sql#' REGEXP '^[0-9]{4}$'), '#requestParam.year?sql#' , '#date.yyyy?sql#'),1) +\n       INTERVAL (IF(('#requestParam.month?sql#' REGEXP '^[0-9]{2}$'), '#requestParam.month?sql#' , '#date.MM?sql#') -1) MONTH +\n       INTERVAL daynum DAY date_field\n   FROM\n   (\n       SELECT t*10+u daynum\n       FROM\n           (SELECT 0 t UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) A,\n           (SELECT 0 u UNION SELECT 1 UNION SELECT 2 UNION SELECT 3\n           UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7\n           UNION SELECT 8 UNION SELECT 9) B\n       ORDER BY daynum\n   ) AA\n) d\nLEFT JOIN \n(\n\t select dateCreated FROM app_fd_%s\n) fd\nON d.date_field=DATE_FORMAT(fd.dateCreated,'%%Y-%%m-%%d')\nWHERE DATE_FORMAT(d.date_field,'%%m') = IF(('#requestParam.month?sql#' REGEXP '^[0-9]{2}$'), '#requestParam.month?sql#' , '#date.MM?sql#')\nGROUP BY d.date_field\nORDER BY d.date_field desc",

            "customHeader""<div class=\"filter\">\n   <form action=\"?\" method=\"GET\">\n       <label>%s: <\/label><input name=\"year\" value=\"#requestParam.year?html#\"\/>&nbsp;&nbsp;&nbsp;\n       <label>%s: <\/label><select name=\"month\"\/>\n           <option value=\"01\">Jan<\/option>\n           <option value=\"02\">Feb<\/option>\n           <option value=\"03\">Mar<\/option>\n           <option value=\"04\">Apr<\/option>\n           <option value=\"05\">May<\/option>\n           <option value=\"06\">Jun<\/option>\n           <option value=\"07\">Jul<\/option>\n           <option value=\"08\">Aug<\/option>\n           <option value=\"09\">Sep<\/option>\n           <option value=\"10\">Oct<\/option>\n           <option value=\"11\">Nov<\/option>\n           <option value=\"12\">Dec<\/option>\n       <\/select>\n       <input type=\"submit\" value=\"%s\"\/>\n   <\/form>\n<\/div>\n<script>\n   $(function(){\n       if ($(\"[name='year']\").val() === \"\") {\n           $(\"[name='year']\").val(\"#date.yyyy#\");\n       }\n       if ($(\"[name='month']\").val() !== \"#requestParam.month?javascript#\" \n           && '#requestParam.month?javascript#' !== \"\"\n           && $(\"[name='month'] option[value='#requestParam.month?javascript#']\").length > 0 ) {\n           $(\"[name='month']\").val('#requestParam.month?javascript#');\n       } else {\n           $(\"[name='month']\").val(\"#date.MM#\");\n       }\n   });\n<\/script>\n<br\/>\n<br\/>",

            "customFooter""",

            "datasource""default",

            "keyName"""

        }

    }]

}

c. 管理插件依赖库

我们的插件使用javax.servlet.http.HttpServletRequest和javax.servlet.http.HttpServletResponse类,因此我们需要将jsp-api库添加到我们的POM文件中。

<!-- Change plugin specific dependencies here -->

<dependency>

    <groupId>javax.servlet</groupId>

    <artifactId>jsp-api</artifactId>

    <version>2.0</version>

</dependency>

<!-- End change plugin specific dependencies here -->

d. 使你的插件国际化(i18n)

我们在getLabel和getDescription方法中使用i18n消息密钥。我们还在我们的属性选项定义中使用了i18n消息密钥。所以,我们需要为我们的插件创建一个消息资源包属性文件。

在“form_submission_statistics_generator / src / main”目录下创建目录“resources / messages”。然后,在该文件夹中创建一个“FormSubmissionStatisticsGenerator.properties”文件。在属性文件中,让我们添加所有的消息键和它的标签如下。

org.joget.tutorial.FormSubmissionStatisticsGenerator.pluginLabel=Generate Form Submission Statistics

org.joget.tutorial.FormSubmissionStatisticsGenerator.pluginDesc=Generate 2 SQL Chart Menus for form submission statistics

generator.formSubmissionStatistics.explanation=Create 2 SQL Chart Menus based on the current form for submission statistics. Note: This is dependent for MySQL database.

generator.formSubmissionStatistics.config=Options

generator.formSubmissionStatistics.userview=Userview

generator.formSubmissionStatistics.advanced=Advanced

generator.formSubmissionStatistics.label.options=Label Options

generator.formSubmissionStatistics.categoryLabel=Category Label

generator.formSubmissionStatistics.categoryLabel.value=[formName] Statistics

generator.formSubmissionStatistics.menuId.invalidId=Only alpha-numeric and underscore characters allowed

generator.formSubmissionStatistics.monthlyMenuId=Monthly Menu id

generator.formSubmissionStatistics.monthlyMenuLabel=Montly Menu Label

generator.formSubmissionStatistics.monthlyMenuLabel.value=Monthly Submission Chart

generator.formSubmissionStatistics.monthlyChartTitle=Montly Chart Title

generator.formSubmissionStatistics.monthlyChartTitle.value=[formName] Monthly Submission Chart

generator.formSubmissionStatistics.monthlyXAxisLabel=Montly X-axis Label

generator.formSubmissionStatistics.monthlyXAxisLabel.value=Month

generator.formSubmissionStatistics.dailyMenuId=Daily Menu Id

generator.formSubmissionStatistics.dailyMenuLabel=Daily Menu Label

generator.formSubmissionStatistics.dailyMenuLabel.value=Daily Submission Chart

generator.formSubmissionStatistics.dailyChartTitle=Daily Chart Title

generator.formSubmissionStatistics.dailyChartTitle.value=[formName] Daily Submission Chart

generator.formSubmissionStatistics.dailyXAxisLabel=Daily X-axis Label

generator.formSubmissionStatistics.dailyXAxisLabel.value=Date

generator.formSubmissionStatistics.yAxisLabel=Y-axis Label

generator.formSubmissionStatistics.yAxisLabel.value=Number

generator.formSubmissionStatistics.yearLabel=Year Label

generator.formSubmissionStatistics.yearLabel.value=Year

generator.formSubmissionStatistics.monthLabel=Month Label

generator.formSubmissionStatistics.monthLabel.value=Month

generator.formSubmissionStatistics.showLabel=Show Label

generator.formSubmissionStatistics.showLabel.value=Show

generator.formSubmissionStatistics.useriewMenu.options=Userview Label Options

generator.formSubmissionStatistics.createUserviewOptions=Create New Userview Options

generator.formSubmissionStatistics.userview.id=Userview ID

generator.formSubmissionStatistics.userview.id.value=v

generator.formSubmissionStatistics.userview.id.invalidId=Only alpha-numeric and underscore characters allowed

generator.formSubmissionStatistics.userview.name=Userview Name

generator.formSubmissionStatistics.userview.name.value=[appName]

generator.formSubmissionStatistics.userview.description=Userview Description

generator.formSubmissionStatistics.msg.success=Menus generated. Click <a href="[url]" target="_blank">here</a> to continue edit in Userview Builder.

generator.formSubmissionStatistics.msg.error=Error during generating Form Submission Statistics Menus!

e. 在Felix 框架中注册插件

我们将不得不在Activator类(在同一个类包中自动生成)中注册我们的插件类,以告诉Felix框架这是一个插件。

public void start(BundleContext context) {

    registrationList = new ArrayList<ServiceRegistration>();

    //Register plugin here

    registrationList.add(context.registerService(FormSubmissionStatisticsGenerator.class.getName(), new FormSubmissionStatisticsGenerator(), null));

f.构建并测试

让我们建立我们的插件。一旦构建过程完成,我们将在“form_submission_statistics_generator / target”目录下创建一个“form_submission_statistics_generator-5.0.0.jar”文件。

然后,让插件jar上传到  管理插件。上传jar文件后,仔细检查插件是否正确上传和激活。

现在,我们可以在Form Builder中为我们的表单打开一个测试生成器。点击Form Builder右上方的“Generate App”按钮。请参阅  生成应用程序

让我们检查“高级生成器”的属性页面。

生成过程完成后。

一个新的类别被添加到我们的用户视图。

SQL图表菜单将显示如下。


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

您可以从form_submission_statistics_generator.zip下载源代码  。

要下载现成的插件jar,请在http://marketplace.joget.org/上找到它  。

文档更新时间: 2018-11-06 06:19   作者:李庆