Joget DX 8 Stable Released
The stable release for Joget DX 8 is now available, with a focus on UX and Governance.
在本教程中,我们将遵循开发插件的 指导方针 来开发我们的表单提交统计信息生成器。 有关更多详细信息步骤,请参阅第一个教程 如何开发一个Bean Shell哈希变量插件。
我们有2个SQL Chart菜单(使用的查询依赖于MySQL)来显示表单数据提交统计信息,这2个菜单总是需要复制不同的表单。
我们可以开发一个 Generator插件 来简化这个过程,为其他表单复制2个SQL Chart菜单。
要为我们的2个SQL图表菜单开发Generator插件,我们可以考虑提供以下内容作为输入。
2 SQL Chart菜单将被添加到选定的用户视图下一个新的类别。其中一个菜单将显示每月提交图表,另一个将显示基于年份和月份过滤器的每日提交图表。
首先,我们可以在现有的用户视图之一中构建我们的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#\"\/> \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定义中。
我们需要始终准备好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。
在“org.joget.tutorial”包下创建一个“FormSubmissionStatisticsGenerator”类。然后,使用org.joget.apps.generator.model.GeneratorPlugin 抽象类来扩展 该类。请参考 Generator插件。
像往常一样,我们必须执行所有的抽象方法。我们将使用AppPluginUtil.getMessage方法来支持i18n,并使用常量变量MESSAGE_PATH作为消息资源包目录
然后,我们必须为管理员用户提供一个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' }] }]
public String getPropertyOptions() { String options = AppUtil.readPluginResource(getClassName(), "/properties/formSubmissionStatisticsGenerator.json", null, true, 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(), true, null); 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#\"\/> \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": "" } }] }
我们的插件使用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 -->
我们在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!
我们将不得不在Activator类(在同一个类包中自动生成)中注册我们的插件类,以告诉Felix框架这是一个插件。
public void start(BundleContext context) { registrationList = new ArrayList<ServiceRegistration>(); //Register plugin here registrationList.add(context.registerService(FormSubmissionStatisticsGenerator.class.getName(), new FormSubmissionStatisticsGenerator(), null)); }
让我们建立我们的插件。一旦构建过程完成,我们将在“form_submission_statistics_generator / target”目录下创建一个“form_submission_statistics_generator-5.0.0.jar”文件。
然后,让插件jar上传到 管理插件。上传jar文件后,仔细检查插件是否正确上传和激活。
现在,我们可以在Form Builder中为我们的表单打开一个测试生成器。点击Form Builder右上方的“Generate App”按钮。请参阅 生成应用程序。
让我们检查“高级生成器”的属性页面。
生成过程完成后。
一个新的类别被添加到我们的用户视图。
SQL图表菜单将显示如下。
您可以从form_submission_statistics_generator.zip下载源代码 。
要下载现成的插件jar,请在http://marketplace.joget.org/上找到它 。