Joget DX 8 Stable Released
The stable release for Joget DX 8 is now available, with a focus on UX and Governance.
...
In the properties definition options file, we will need to provide options as below. Please note that we can use "@@message.key@@" syntax to support i18n in our properties options.
Thai |
---|
ในไฟล์ตัวเลือกคำจำกัดความของคุณสมบัติเราจะต้องระบุตัวเลือกดังต่อไปนี้ โปรดทราบว่าเราสามารถใช้ไวยากรณ์ "@@ message.key @@" เพื่อรองรับ i18n ในตัวเลือกคุณสมบัติของเรา |
Code Block | ||
---|---|---|
| ||
[{ title : '@@userview.ganttchart.config@@', 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' }, { name : 'title', label : '@@userview.ganttchart.title@@', type : 'textfield' }, { name : 'binder', label : '@@userview.ganttchart.binder@@', type : 'elementselect', required : 'True', options_ajax : '[CONTEXT_PATH]/web/property/json/getElements?classname=org.joget.apps.datalist.model.DataListBinderDefault', url : '[CONTEXT_PATH]/web/property/json[APP_PATH]/getPropertyOptions' }, { label : '@@userview.ganttchart.mapping@@', type : 'header' }, { name : 'category', label : '@@userview.ganttchart.mapping.category@@', type : 'textfield', required : 'True' }, { name : 'task', label : '@@userview.ganttchart.mapping.task@@', type : 'textfield', required : 'True' }, { name : 'activity', label : '@@userview.ganttchart.mapping.activity@@', type : 'textfield', required : 'True' }, { name : 'fromDate', label : '@@userview.ganttchart.mapping.fromDate@@', type : 'textfield', required : 'True' }, { name : 'toDate', label : '@@userview.ganttchart.mapping.toDate@@', type : 'textfield', required : 'True' }, { name : 'dateFormat', label : '@@userview.ganttchart.mapping.dateFormat@@', type : 'textfield', required : 'True', value : 'yyyy-MM-dd' }, { name : 'taskId', label : '@@userview.ganttchart.mapping.taskId@@', type : 'textfield' }, { name : 'cssClass', label : '@@userview.ganttchart.mapping.cssClass@@', type : 'textfield' }] }, { title : '@@userview.ganttchart.advanced@@', properties : [ { name : 'itemsPerPage', label : '@@userview.ganttchart.itemsPerPage@@', type : 'textfield', required : 'True', value : '20' }, { name : 'navigate', label : '@@userview.ganttchart.navigate@@', type : 'selectbox', required : 'True', value : 'scroll', options : [{ value : 'buttons', label : '@@userview.ganttchart.navigate.buttons@@' }, { value : 'scroll', label : '@@userview.ganttchart.navigate.scroll@@' }] }, { name : 'scale', label : '@@userview.ganttchart.scale@@', type : 'selectbox', required : 'True', value : 'days', options : [{ value : 'hours', label : '@@userview.ganttchart.scale.hours@@' }, { value : 'days', label : '@@userview.ganttchart.scale.days@@' }, { value : 'weeks', label : '@@userview.ganttchart.scale.weeks@@' }, { value : 'months', label : '@@userview.ganttchart.scale.months@@' }] }, { name : 'maxScale', label : '@@userview.ganttchart.maxScale@@', type : 'selectbox', required : 'True', value : 'months', options : [{ value : 'hours', label : '@@userview.ganttchart.scale.hours@@' }, { value : 'days', label : '@@userview.ganttchart.scale.days@@' }, { value : 'weeks', label : '@@userview.ganttchart.scale.weeks@@' }, { value : 'months', label : '@@userview.ganttchart.scale.months@@' }] }, { name : 'minScale', label : '@@userview.ganttchart.minScale@@', type : 'selectbox', required : 'True', value : 'hours', options : [{ value : 'hours', label : '@@userview.ganttchart.scale.hours@@' }, { value : 'days', label : '@@userview.ganttchart.scale.days@@' }, { value : 'weeks', label : '@@userview.ganttchart.scale.weeks@@' }, { value : 'months', label : '@@userview.ganttchart.scale.months@@' }] }, { name : 'useCookie', label : '@@userview.ganttchart.useCookie@@', type : 'checkbox', options : [{ value : 'true', label : '' }] }, { name : 'scrollToToday', label : '@@userview.ganttchart.scrollToToday@@', type : 'checkbox', options : [{ value : 'true', label : '' }] }, { name : 'onItemClick', label : '@@userview.ganttchart.onItemClick@@', type : 'codeeditor', mode : 'javascript', value : '//console.log(data); //data obj hold all the columns value of a row' }, { name : 'onAddClick', label : '@@userview.ganttchart.onAddClick@@', type : 'codeeditor', mode : 'javascript', value : '//console.log(datetime); //the DateTime in ms for the clicked Cell\n//console.log(rowId); //the row ID of clicked Cell' }, { name : 'onRender', label : '@@userview.ganttchart.onRender@@', type : 'codeeditor', mode : 'javascript', value : '//console.log("chart rendered");' }, { name : 'customHeader', label : '@@userview.ganttchart.customHeader@@', type : 'codeeditor', mode : 'html' }, { name : 'customFooter', label : '@@userview.ganttchart.customFooter@@', type : 'codeeditor', mode : 'html' }] }] |
After done the properties option to collect input, we can work on the main method of the plugin which is getRenderPage method. Normally, what I will do before go into detail to populate the data to the view, I will first put the static content for the getRenderPage to build and test the plugin first. It everything is fine, then only we try to add data to the view.
Thai |
---|
หลังจากเสร็จสิ้นตัวเลือกคุณสมบัติเพื่อรวบรวมอินพุตเราสามารถทำงานกับวิธีหลักของปลั๊กอินซึ่งเป็นวิธี getRenderPage โดยปกติสิ่งที่ฉันจะทำก่อนลงรายละเอียดเพื่อเติมข้อมูลลงในมุมมองฉันจะใส่เนื้อหาแบบคงที่สำหรับ getRenderPage เพื่อสร้างและทดสอบปลั๊กอินก่อน มันทุกอย่างเรียบร้อยแล้วเราแค่พยายามเพิ่มข้อมูลลงในมุมมอง |
Code Block | ||
---|---|---|
| ||
@Override 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, getClass().getName(), "/templates/ganttChart.ftl", null); return content; } |
Then, let us create a template file locate at "/templates/ganttChart.ftl". Let us create a directory "resources/templates" under "gantt_chart_menu/src/main" directory. After create the directory, create a file named "ganttChartMenu.json" in the "templates" folder.
Thai |
---|
จากนั้นให้เราสร้างไฟล์เทมเพลตค้นหาที่ "/templates/ganttChart.ftl" ให้เราสร้างไดเรกทอรี "resources / templates" ภายใต้ไดเรกทอรี "gantt_chart_menu / src / main" หลังจากสร้างไดเรกทอรีให้สร้างไฟล์ชื่อ "ganttChartMenu.json" ในโฟลเดอร์ "templates" |
Put the static HTML we create previously into the template file as below. Remember to put all the dependencies javascript library and images under "gantt_chart_menu/src/main/resources/resources" and change the url as below accordingly. You project directory should look like the image below now.
Thai |
---|
ใส่ HTML แบบคงที่ที่เราสร้างไว้ก่อนหน้านี้ลงในไฟล์เทมเพลตดังต่อไปนี้ อย่าลืมใส่ javascript library และ images ทั้งหมดไว้ใน "gantt_chart_menu / src / main / resources / resources" และเปลี่ยน URL ตามด้านล่าง ไดเรกทอรีโครงการของคุณควรดูเหมือนภาพด้านล่างนี้ |
Code Block | ||
---|---|---|
| ||
<link href="${request.contextPath}/plugin/org.joget.tutorial.GanttChartMenu/lib/jquery/gantt/css/style.css" rel="stylesheet" type="text/css" /> <script src="${request.contextPath}/plugin/org.joget.tutorial.GanttChartMenu/lib/jquery/gantt/js/jquery.fn.gantt.min.js"></script> <div class="gantt_chart_menu_body"> <h3>Plugin Development</h3> <div class="gantt"></div> <script> $(function() { "use strict"; $(".gantt").gantt({ source: [{ name: "Sprint 0", desc: "Analysis", values: [{ from: "/Date(1320192000000)/", to: "/Date(1322401600000)/", label: "Requirement Gathering", customClass: "ganttRed" }] },{ name: " ", desc: "Scoping", values: [{ from: "/Date(1322611200000)/", to: "/Date(1323302400000)/", label: "Scoping", customClass: "ganttRed" }] },{ name: "Sprint 1", desc: "Development", values: [{ from: "/Date(1323802400000)/", to: "/Date(1325685200000)/", label: "Development", customClass: "ganttGreen" }] },{ name: " ", desc: "Showcasing", values: [{ from: "/Date(1325685200000)/", to: "/Date(1325695200000)/", label: "Showcasing", customClass: "ganttBlue" }] },{ name: "Sprint 2", desc: "Development", values: [{ from: "/Date(1326785200000)/", to: "/Date(1325785200000)/", label: "Development", customClass: "ganttGreen" }] },{ name: " ", desc: "Showcasing", values: [{ from: "/Date(1328785200000)/", to: "/Date(1328905200000)/", label: "Showcasing", customClass: "ganttBlue" }] },{ name: "Release Stage", desc: "Training", values: [{ from: "/Date(1330011200000)/", to: "/Date(1336611200000)/", label: "Training", customClass: "ganttOrange" }] },{ name: " ", desc: "Deployment", values: [{ from: "/Date(1336611200000)/", to: "/Date(1338711200000)/", label: "Deployment", customClass: "ganttOrange" }] },{ name: " ", desc: "Warranty Period", values: [{ from: "/Date(1336611200000)/", to: "/Date(1349711200000)/", label: "Warranty Period", customClass: "ganttOrange" }] }], navigate: "scroll", maxScale: "hours", itemsPerPage: 10 }); }); </script> </div> |
Now, for testing purpose, we can skip to c. Manage the dependency libraries of your plugin, d. Make your plugin internationalization (i18n) ready, e. Register your plugin to Felix Framework and f. Build it and testing then continue the below after testing it. You will get something similar to below in your userview.
Thai |
---|
ตอนนี้เพื่อการทดสอบเราสามารถข้ามไปที่ c. Manage the dependency libraries of your plugin, d. Make your plugin internationalization (i18n) ready, e. Register your plugin to Felix Framework และ f. Build it and testing จากนั้นทำต่อไปด้านล่างหลังจากทดสอบ คุณจะได้รับสิ่งที่คล้ายกับด้านล่างในมุมมองของเรา |
After verify the static HTML is working in our plugin, we can further enhance it by adding data to the view. Now, modify After verify the static HTML is working in our plugin, we can further enhance it by adding data to the view. Now, modify your getRenderPage method and ganttChart.ftl template as below.
Thai |
---|
หลังจากตรวจสอบว่า HTML แบบคงที่ทำงานในปลั๊กอินของเราเราสามารถปรับปรุงให้ดีขึ้นได้โดยการเพิ่มข้อมูลลงในมุมมอง ตอนนี้แก้ไขเมธอด getRenderPage และเทมเพลต ganttChart.ftl ดังนี้ |
Code Block | ||
---|---|---|
| ||
@Override public String getRenderPage() { Map model = new HashMap(); model.put("request", getRequestParameters()); model.put("element", this); //populate data in JSON format model.put("data", getData()); PluginManager pluginManager = (PluginManager)AppUtil.getApplicationContext().getBean("pluginManager"); String content = pluginManager.getPluginFreeMarkerTemplate(model, getClass().getName(), "/templates/ganttChart.ftl", MESSAGE_PATH); return content; } protected String getData() { String json = "[]"; try { DataListCollection data = null; String idColumn = getPropertyString("taskId"); //get the binder Object binderData = getProperty("binder"); if (binderData != null && binderData instanceof Map) { Map bdMap = (Map) binderData; if (bdMap != null && bdMap.containsKey("className") && !bdMap.get("className").toString().isEmpty()) { PluginManager pluginManager = (PluginManager) AppUtil.getApplicationContext().getBean("pluginManager"); DataListBinder binder = (DataListBinder) pluginManager.getPlugin(bdMap.get("className").toString()); if (binder != null) { Map bdProps = (Map) bdMap.get("properties"); binder.setProperties(bdProps); data = binder.getData(null, bdProps, new DataListFilterQueryObject[0], null, null, null, null); if (idColumn.isEmpty()) { idColumn = binder.getPrimaryKeyColumnName(); } } } } JSONArray dataArry = new JSONArray(); String dateFormat = getPropertyString("dateFormat"); SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); if (data != null && !data.isEmpty()) { String currentCategory = null; int cat_count = 0; String currentTask = null; int task_count = 0; int act_count = 0; JSONObject taskObj = null; JSONArray taskValuesArray = null; for (Object r : data) { String id = getValue(r, idColumn); String cat = getValue(r, getPropertyString("category")); String task = getValue(r, getPropertyString("task")); String act = getValue(r, getPropertyString("activity")); String formDate = getValue(r, getPropertyString("fromDate")); String toDate = getValue(r, getPropertyString("toDate")); String status = getValue(r, getPropertyString("cssClass")); if (currentTask == null || !currentTask.equals(task) || (currentTask.equals(task) && !cat.equals(currentCategory))) { currentTask = task; if (taskObj != null) { taskObj.put("values", taskValuesArray); dataArry.put(taskObj); } taskObj = new JSONObject(); taskValuesArray = new JSONArray(); taskObj.put("desc", task); taskObj.put("id", id); task_count++; } if (currentCategory == null || !currentCategory.equals(cat)) { currentCategory = cat; taskObj.put("name", cat); cat_count++; } JSONObject valueObj = new JSONObject(); JSONObject actObj = new JSONObject(); act_count++; actObj.put("taskId", id); actObj.put("category", cat); actObj.put("task", task); actObj.put("activity", act); actObj.put("formDate", formDate); actObj.put("toDate", toDate); actObj.put("status", status); valueObj.put("dataObj", actObj); valueObj.put("label", act); valueObj.put("from", "/Date("+sdf.parse(formDate).getTime()+")/"); valueObj.put("to", "/Date("+sdf.parse(toDate).getTime()+")/"); valueObj.put("customClass", "cat_"+cat_count+" task_"+task_count+" act_"+act_count+" "+status.replace(" ", "_")); taskValuesArray.put(valueObj); } if (taskObj != null) { taskObj.put("values", taskValuesArray); dataArry.put(taskObj); } } return dataArry.toString(); } catch (Exception e) { LogUtil.error(GanttChartMenu.class.getName(), e, json); } return json; } protected String getValue(Object o, String name) { String value = ""; try { Object v = LookupUtil.getBeanProperty(o, name); if (v != null) { return v.toString(); } } catch (Exception e) { LogUtil.error(GanttChartMenu.class.getName(), e, name); } return value; } |
...
Thai |
---|
จัดการไลบรารีการพึ่งพาของปลั๊กอินของคุณ |
Our plugin is using some libraries, we have to add all of them to our POM file.
Thai |
---|
ปลั๊กอินของเราใช้ห้องสมุดบางแห่งเราต้องเพิ่มทั้งหมดลงในไฟล์ POM ของเรา |
Code Block | ||
---|---|---|
| ||
<!-- Change plugin specific dependencies here --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20080701</version> </dependency> <dependency> <groupId>displaytag</groupId> <artifactId>displaytag</artifactId> <version>1.2</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> <exclusion> <artifactId>jcl104-over-slf4j</artifactId> <groupId>org.slf4j</groupId> </exclusion> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <!-- End change plugin specific dependencies here --> |
Thai |
---|
เตรียมปลั๊กอินสากลให้พร้อม (i18n) |
We are using i18n message key in getLabel and getDescription method. We also used i18n message key in our properties options definition as well. So, we will need to create a message resource bundle properties file for our plugin.
Thai |
---|
เรากำลังใช้คีย์ข้อความ i18n ในวิธี getLabel และ getDescription นอกจากนี้เรายังใช้คีย์ข้อความ i18n ในการกำหนดตัวเลือกคุณสมบัติของเราเช่นกัน ดังนั้นเราจะต้องสร้างไฟล์คุณสมบัติสำหรับปลั๊กอินของเรา |
Create directory "resources/messages" under "gantt_chart_menu/src/main" directory. Then, create a "GanttChartMenu.properties" file in the folder. In the properties file, let add all the message keys and its label as below.
Thai |
---|
สร้างไดเรกทอรี "ทรัพยากร / ข้อความ" ภายใต้ไดเรกทอรี "gantt_chart_menu / src / main" จากนั้นสร้างไฟล์ "GanttChartMenu.properties" ในโฟลเดอร์ ในไฟล์คุณสมบัติให้เพิ่มคีย์ข้อความทั้งหมดและป้ายกำกับของมันดังต่อไปนี้ |
Code Block |
---|
org.joget.tutorial.GanttChartMenu.pluginLabel=Gantt Chart Menu org.joget.tutorial.GanttChartMenu.pluginDesc=Display data in a Gantt Chart view userview.ganttchart.config=Configure Gantt Chart Menu userview.ganttchart.customId=Custom ID userview.ganttchart.invalidId=Only alpha-numeric and underscore characters allowed userview.ganttchart.label=Label userview.ganttchart.title=Page Title userview.ganttchart.binder=Data Binder userview.ganttchart.mapping=Column to Data Mappings userview.ganttchart.mapping.category=Category (column ID) userview.ganttchart.mapping.task=Task (column ID) userview.ganttchart.mapping.activity=Activity (column ID) userview.ganttchart.mapping.fromDate=Activity From Date (column ID) userview.ganttchart.mapping.toDate=Activity To Date (column ID) userview.ganttchart.mapping.dateFormat=Date format for Activity From/To Date userview.ganttchart.mapping.taskId=Task Id (column ID) userview.ganttchart.mapping.cssClass=Status (column ID, use as CSS class for styling) userview.ganttchart.advanced=Advanced userview.ganttchart.itemsPerPage=Item pre page userview.ganttchart.navigate=Navigator userview.ganttchart.navigate.buttons=Buttons userview.ganttchart.navigate.scroll=Scroll userview.ganttchart.scale=Default Scale userview.ganttchart.scale.hours=Hours userview.ganttchart.scale.days=Days userview.ganttchart.scale.weeks=Weeks userview.ganttchart.scale.months=Months userview.ganttchart.maxScale=Maximum Scale userview.ganttchart.minScale=Minimum Scale userview.ganttchart.useCookie=Use cookie for storing chart states userview.ganttchart.scrollToToday=Auto scroll to today after rendered userview.ganttchart.onItemClick=On Item Clicked Event (Javascript) userview.ganttchart.onAddClick=On Empty Space Clicked Event (Javascript) userview.ganttchart.onRender=On Rendered Event (Javascript) userview.ganttchart.customHeader=Custom Header (HTML) userview.ganttchart.customFooter=Custom Footer (HTML) userview.ganttChart.months.label="January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" userview.ganttChart.dow.label="S", "M", "T", "W", "T", "F", "S" userview.ganttChart.waitText=Loading... |
Thai |
---|
ลงทะเบียนปลั๊กอินของคุณไปที่ Felix Framework |
We will have to register our plugin class in Activator class (Auto generated in the same class package) to tell Felix Framework that this is a plugin.
Thai |
---|
เราจะต้องลงทะเบียนคลาสปลั๊กอินของเราในคลาส Activator (สร้างอัตโนมัติในแพ็คเกจคลาสเดียวกัน) เพื่อบอก Felix Framework ว่านี่คือปลั๊กอิน |
Code Block | ||
---|---|---|
| ||
Code Block | ||
| ||
public void start(BundleContext context) { registrationList = new ArrayList<ServiceRegistration>(); //Register plugin here registrationList.add(context.registerService(GanttChartMenu.class.getName(), new GanttChartMenu(), null)); } |
Thai |
---|
สร้างและทดสอบ |
Let build our plugin. Once the building process is done, we will found a "gantt_chart_menu-5.0.0.jar" file is created under "gantt_chart_menu/target" directory.
Thai |
---|
ให้สร้างปลั๊กอินของเรา เมื่อกระบวนการสร้างเสร็จสิ้นเราจะพบไฟล์ "gantt_chart_menu-5.0.0.jar" ถูกสร้างขึ้นภายใต้ไดเรกทอรี "gantt_chart_menu / target" |
Then, let upload the plugin jar to Manage Plugins. After upload the jar file, double check the plugin is uploaded and activated correctly.
Thai |
---|
จากนั้นให้อัปโหลด jar ปลั๊กอินไปที่ Manage Plugins หลังจากอัปโหลดไฟล์ jar ตรวจสอบอีกครั้งว่าปลั๊กอินถูกอัปโหลดและเปิดใช้งานอย่างถูกต้อง |
Open a userview, you will see the new plugin is added under "Marketplace". Drag it to one of your Userview Category.
Thai |
---|
เปิด userview คุณจะเห็นปลั๊กอินใหม่ถูกเพิ่มภายใต้ "Marketplace" ลากไปยังหมวดหมู่ Userview ของคุณ |
Edit the properties of the Gantt Chart Menu.
Thai |
---|
แก้ไขคุณสมบัติของเมนูแผนภูมิแกนต์ |
I selected "Form Data Binder" as "Data Binder" for testing. Fill all the mappings to corresponding Field Id/Column Id.
Thai |
---|
ฉันเลือก "Form Data Binder" เป็น "Data Binder" สำหรับการทดสอบ กรอกข้อมูลการแมปทั้งหมดให้สอดคล้องกับฟิลด์รหัส / หมายเลขคอลัมน์ |
Configure binder.
Thai |
---|
กำหนดค่า binder |
Advanced setting to configure the gantt chart.
Thai |
---|
การตั้งค่าขั้นสูงเพื่อกำหนดค่าแผนภูมิแกนต์ |
Writing some css styling in "Custom Footer (HTML)" option to give different colors for different status.
Thai |
---|
การเขียนสไตล์ CSS ในตัวเลือก "Custom Footer (HTML)" เพื่อให้สีแตกต่างกันสำหรับสถานะที่แตกต่างกัน |
Populate some data to the form for testing.
Thai |
---|
เติมข้อมูลลงในแบบฟอร์มสำหรับการทดสอบ |
The end result.
Thai |
---|
ผลลัพธ์ที่ได้ |
Thai |
---|
ก้าวไปอีกขั้นแบ่งปันหรือขายมัน |
You can download the source code from gantt_chart_menu.zip.
...
To download the ready-to-use plugin jar, please find it in http://marketplace.joget.org/.
Thai |
---|
คุณสามารถดาวน์โหลดซอร์สโค้ดได้จาก gantt_chart_menu.zip แอปทดสอบสำหรับบทช่วยสอนนี้คือ APP_testGanttChart-1-20151106194035.jwa หากต้องการดาวน์โหลด jar ปลั๊กอินที่พร้อมใช้งานโปรดค้นหาได้ที่ http://marketplace.joget.org/ |