Let's learn from example.
Throughout this tutorial, we will walk you through creating an advanced todo Application by using the awesome Enterprise Application Framework - Skyve.
This todo application will assign and manage tasks needed to be done for our project. We also try to put some effort in to create a report by using Jaspersoft BI tools which is embedded in the Skyve Framework.
In this project, we will try to cover as much of the Skyve development process and its concepts as possible.
This tutorial assumes familiarity with web technology and architecture, Java EE concepts, the Java language and the use of common development tools like Eclipse.
Before continuing with our tutorial, there are some pages you may want to visit:
-
What is Skyve? - Will answer what Skyve is, and how it will be useful in your Enterprise Application Development.
-
Getting Started - Will help give you some ideas on how to start with our Skyve Framework.
-
Dev Guide - Will help you learn and understand about our development. It also covers most Skyve Framework elements and concepts. There are many real examples for you to refer to also.
-
Join Us On Slack - If you get stuck, feel free to ask the team some questions on the Skyve Slack server.
Now, moving on to the next stage to learn how to create an application with Skyve Framework.
App Project To create a new Skyve Project, you can go to the Getting Started page, then scroll down to the Skyve For Developers section, and click the Create button. We recommend you watch the video guide first
Or, you can go directly to the Skyve Project Creator.
On the Skyve Project Creation page, fill in the below information:
- Email address: A valid email address that you will be using to receive the download link from Skyve
- Project Name: Your project name
- Customer Name: Your customer name
- Database Dialect: Select your Database Engine (H2 is suggested for ease, though there is a guide further on for setting up MySQL)
- Skyve Script: This field is optional - we will refer to Skyve Script later in this course
Finally, click the Create Project button.
Now, check your email inbox to find your Project Download Link. Download the project and extract it to your workspace.
Now we will import the project to Eclipse.
Once in Eclipse, right-click in the Project Explorer window, and choose Import.
Click the Maven dropdown box and select Existing Maven Projects. Then click the Next button.
The next step is to browse for your root project folder (Skyve Project (which you extracted in the last section of this guide), and select it.
Finally, click the Finish button.
Wait for the Eclipse Import Wizard to finish the importing process and re-index your project. Now we can continue to the next page to install and configure WildFly Server to run our application.
To run our todoApp we will need to install and configure for WildFly Server. Skyve works well on WildFly version 13+ (tested and runs smoothly on WildFly 17 - as of last revision of this tutorial).
You can skip this step if WildFly Server is already installed on your system.
Before installing WildFly Server, make sure JBoss Tools is installed on your system.
To install JBoss Tools, click on Help, then click Eclipse Marketplace.
In the searchbar, enter 'jboss' then search.
Select the JBoss Tools version that the search returns, and click Install.
To check if JBoss Tools is installed properly, click on Help, then click Eclipse Marketplace.
Click Installed.
If the JBoss Tools plugin is present, you are ready to continue.
After JBoss Tools was installed properly, follow these steps to install WildFly Server.
- Once Eclipse is opened, right-click under the Package Explorer tab and highlight New, then from the pop-out, click on Server
- Select the WildFly version you wish to work with and click Next
- Click Next again
- Once more, click the Next button
- Click on the Download and install runtime link
- Select the latest version of WildFly, then click Next
- Once you have read the terms of the licence agreement, check the box to accept the terms, and click Next
- Finally, select the path for where you wish your download and install locations to be found, then click Finish to complete the installation
- Wait for Eclipse to complete the download and installation process before moving on to the next step
It is easier to start your Skyve Application with H2 Database as it does not require any extra configurations. However, in this tutorial I want to place you on the real world of Enterprise Application Development by using MySQL Database.
You can check if MySQL installed on your system, if it is not you can go to MySQL Download, choose the right version for your system, and install MySQL on your system.
You may also need a SQL Client to work with your data, MySQL Workbench is perfect for it, however you may use any other tools which you are familiar with.
Once MySQL is ready on your system, let us configure WildFly datasource to support MySQL Engine.
- Download MySQL JDBC Driver Visit MySQL Connector JDBC page
At this moment, JDBC 8 connector is not supported. So we will go with the previous Generally Available (GA) release.
Select the Operating System that you are creating your todoApp on.
Download a suitable version for your Operating System. In this tutorial I am using Windows Operating System, so I go to download Platform Independent (Architecture Independent), ZIP Archive
-
Deploy MySQL JDBC Driver Navigate to the directory $WILDFLYHOME/modules/system/layers/base/com ($WILDFLYHOME - the Root Folder, which you selected when you install WildFly Server - For example: D:\JavaPrograms\EclipseWorkSpace\wildfly-16.0.0.Final)
-
Create mysql/main directory
-
Navigate to the main directory you just created and copy MySQL JDBC driver's jar there
-
Create a module.xml file with the content below:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="com.mysql">
<resources>
<resource-root path="mysql-connector-java-[VERSION]-bin.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
<module name="javax.servlet.api" optional="true"/>
</dependencies>
</module>
Replace [VERSION] with your JDBC Connector Version.
(If you already know how to create an xml file, continue on to Step 6 of Configuring Wildfly datasource to support MySQL)
To create an xml file, click on File, then select New, and click Other.
Scroll down and click the XML dropdown box, then select XML File, then click Next.
Select RemoteSystemsTempFiles, then rename the file to 'module.xml', and click Next.
Check the box to Create XML file from an XML template, and again, click Next.
Finally, click Finish.
- Navigate to the directory $WILDFLYHOME/standalone/configuration, and open the standalone.xml file. Look for datasources.
<subsystem xmlns="urn:jboss:domain:datasources:5.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true" statistics-enabled="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
And define MySQL driver here.
<subsystem xmlns="urn:jboss:domain:datasources:5.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true" statistics-enabled="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
<driver name="mysql" module="com.mysql"/>
</drivers>
</datasources>
</subsystem>
So far we have completed the initial configuration step. Now we will deploy our todoApp to our WildFly Server, then configure our database for todoApp and run it for the first time.
Its easy to deploy your Skyve project to your WildFly Server.
- Open WildFly deployments folder Right-click on the server and click on Show In, then click on File Browser
- Expand the todoApp Project, you will see the deployments folder Copy todoApp.json and todoApp-ds.xml from the todoApp deployments folder to the WildFly deployments folder that you opened in the previous step.
- Add todoApp project to Wildfly Server by right-clicking on your server, and click Add and Remove
- Select todoApp from Available, then click 'Add >', and lastly click the Finish button
We will need to do some configuration to run our project.
Change the content settings
Open your Eclipse Workspace folder and create a content folder called 'content'.
Open todoApp.json that you previously moved into your Wildfly deployments folder and look for Content settings.
// Content settings
content: {
// directory path (note that if you are running on Windows do not use backslashes)
directory: "${SKYVE_CONTENT:C:/_/skyve/skyve-ee/content/}",
// CRON Expression for CMS Garbage Collection job - run at 7 past the hour every hour
gcCron: "0 7 0/1 1/1 * ? *",
// Attachments stored on file system or inline
fileStorage: true
},
Change the directory path to your content folder. It will become something similar to below:
// Content settings
content: {
// directory path (note that if you are running on Windows do not use backslashes)
directory: "${SKYVE_CONTENT:D:/JavaPrograms/EclipseWorkSpace/content/}",
// CRON Expression for CMS Garbage Collection job - run at 7 past the hour every hour
gcCron: "0 7 0/1 1/1 * ? *",
// Attachments stored on file system or inline
fileStorage: true
},
Next, we will need to change the Environment Settings. By default, Skyve is set in production mode. So we will need to change this to development mode.
// Environment settings
environment: {
// test, sit, uat, dev etc: null = prod
identifier: "${IDENTIFIER:null}",
// Dev Mode does not cache the view metadata allowing the effects of view changes to be observed without redeploying
devMode: true,
// Customer Default
customer: "ezmasy",
// Run the jobs scheduled in the data store or not - set false for slave skyve instances
jobScheduler: true,
// Password hashing algorithm - usually bcrypt, pbkdf2, scrypt. MD5 and SHA1 are unsalted and obsolete.
passwordHashingAlgorithm: "bcrypt",
// Absolute path on the filesystem to the source directory where modules live for creating new documents
// via skyve script, e.g. c:/workspace/project/src/main/java
moduleDirectory: null,
// email address for system support
supportEmailAddress: "rucvan.pr@gmail.com"
},
We will need to change the identifier to dev.
One more concept we need to take note of; in todoApp.json, define your bootstrap user settings, later we will use this user information to login to our todoApp.
// bootstrap user settings - creates a user with all customer roles assigned, if the user does not already exist
bootstrap: {
customer: "ezmasy",
user: "${BOOTSTRAP_USERNAME:setup}",
email: "rucvan.pr@gmail.com",
password: "${BOOTSTRAP_PASSWORD:setup}"
}
We have now done the basic configurations needed to make sure our project can run.
Now we will move on to MySQL Data Source configuration.
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<datasource jndi-name="java:/todoAppDB" pool-name="todoApp" enabled="true" jta="true" use-ccm="false">
<connection-url>jdbc:mysql://todoApp_db:3306/todoApp?useCursorFetch=true&defaultFetchSize=100</connection-url>
<driver>mysql</driver>
<pool>
<min-pool-size>5</min-pool-size>
<max-pool-size>10</max-pool-size>
</pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
</datasources>
For example: my database is todoApp and it will deploy on my local computer at port 3306.
Then I will need to change the connection-url like below:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<datasource jndi-name="java:/todoAppDB" pool-name="todoApp" enabled="true" jta="true" use-ccm="false">
<connection-url>jdbc:mysql://localhost:3306/todoApp?useCursorFetch=true&defaultFetchSize=100</connection-url>
<driver>mysql</driver>
<pool>
<min-pool-size>5</min-pool-size>
<max-pool-size>10</max-pool-size>
</pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
</datasources>
Another change that will need to be applied is the security, you will need provide valid authentication to connect to your database.
For security reasons, we strongly recommend you to create a separate account for each application, so each application is not affected by other applications if one of the connections was revealed. It is good practice to use strong password for your applications. If you would rather leave it to a random generator, you can use this web application to generate a strong, secure password: https://passwordsgenerator.net/
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<datasource jndi-name="java:/todoAppDB" pool-name="todoApp" enabled="true" jta="true" use-ccm="false">
<connection-url>jdbc:mysql://localhost:3306/todoApp?useCursorFetch=true&defaultFetchSize=100</connection-url>
<driver>mysql</driver>
<pool>
<min-pool-size>5</min-pool-size>
<max-pool-size>10</max-pool-size>
</pool>
<security>
<user-name>todouser</user-name>
<password>Ggq"MBb,q5\KEzx*</password>
</security>
</datasource>
</datasources>
Before running your project, we will need to generate the domain class first.
-
Click on the dropdown for your todoApp in the Project Explorer and click Run As, then click on Run Configurations
-
Select the Maven Build dropdown, then click on todoApp - Generate Domain, then click Run
- Wait for a few seconds (this may take longer to run for the first time), once the process is complete you will see the result in the Console Window like below;
-
In the Servers window, right-click on the server and click Start.
-
When you see the below info in your Console Window, todoApp was deployed and is running on your localhost server.
If not, you may try to debug by yourself to find the source of the problem, or Join Us On Slack and ask any questions there. You will get support from the Skyve team or a community team member.
- Access todoApp from Web Browser at http://localhost:8080/todoApp
- You can login with your Bootstrap user info, by default:
User Name: setup
Password: setup
- After you login successfully, you will see something similar to this
By default, Skyve opens with the Admin module, the Admin module holds quite a few useful functions which are ready for you to evaluate Skyve Framework.
The user guide is available at https://skyvers.github.io/skyve-user-guide/. The user guide is for end users of Skyve applications and describes how to navigate around the user interface and make use of the built in functions that ship with Skyve.
Module concept and module components are defined at https://skyvers.github.io/skyve-dev-guide/modules/ so we will not repeat it in this tutorial.
To create the todo module, click on the dropdowns following the photo below to access the src/main/java folder, then right-click and add a new package.
Rename the module to 'todo' and click Finish.
Inside the todo
package, create an xml file named todo.xml
todo.xml
file will have below components:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<module name="todo" title="Todo Module" xmlns="http://www.skyve.org/xml/module" xsi:schemaLocation="http://www.skyve.org/xml/module ../../schemas/module.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<homeRef>edit</homeRef>
<homeDocument>Todo</homeDocument>
</module>
In this example, the home (or default) target for the module is the edit view of the Todo document.
Skyve uses the term document to indicate the business-focused nature of application objects.
In this tutorial we assume the app will have the below documents - objects involved
- Staff - who will create, assign, and complete tasks
- Projects - each project may contain multiple tasks, based on customer requirements
- Todo - task needed to be done for each project
So lets go define the above documents inside our todo.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<module name="todo" title="Todo Module" xmlns="http://www.skyve.org/xml/module" xsi:schemaLocation="http://www.skyve.org/xml/module ../../schemas/module.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<homeRef>edit</homeRef>
<homeDocument>Todo</homeDocument>
<documents>
<document ref="Project" />
<document ref="Todo" />
<document ref="Staff" />
<document ref="User" moduleRef="admin" />
<document ref="Contact" moduleRef="admin" />
</documents>
</module>
In this example, we defined documents User
, and Contact
as referent from the admin
module because each user in our application will associate with one staff.
Each role specifies the privilege levels for documents that the role will access (and associated actions). The role name is the name displayed when assigning roles to user security groups in the admin.
For each document, the privilege level is specified in terms of C (Create) R (Read) U (Update) D (Delete) and the document scope access level, either G (Global), C (Customer), D (Data Group) or U (User). The underscore character (_) means no permission is granted.
In our Todo App
, we will define below roles:
- Staff Manager - who are able to manage Staff
- Project Manager - to grant to Project Managers who are able to create projects & tasks
- Project Member - to grant to Project Team Members who are not able to create projects or tasks, but will work on said tasks to finish projects
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<module name="todo" title="Todo Module" xmlns="http://www.skyve.org/xml/module" xsi:schemaLocation="http://www.skyve.org/xml/module ../../schemas/module.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<homeRef>edit</homeRef>
<homeDocument>Todo</homeDocument>
<documents>
<document ref="Project" />
<document ref="Todo" />
<document ref="Staff" />
<document ref="User" moduleRef="admin" />
<document ref="Contact" moduleRef="admin" />
</documents>
<roles>
<role name="StaffManager">
<description>Staff Manager - who are able to manage Staff</description>
<privileges>
<document permission="CRUDC" name="Staff" />
</privileges>
</role>
<role name="ProjectManager">
<description>Project Manager - who are able to manage and create tasks for projects.</description>
<privileges>
<document permission="CRUDC" name="Project" />
<document permission="CRUDC" name="Todo" />
</privileges>
</role>
<role name="ProjectMember">
<description>Project Member - who are not able to create projects, tasks but will work with tasks to finish projects.</description>
<privileges>
<document permission="_RU_C" name="Project" />
<document permission="_RU_C" name="Todo" />
</privileges>
</role>
</roles>
</module>
The application menu is declared in terms of groups and items. A menu group is an expandable menu (submenu).
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<module name="todo" title="Todo Module" xmlns="http://www.skyve.org/xml/module" xsi:schemaLocation="http://www.skyve.org/xml/module ../../schemas/module.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<homeRef>edit</homeRef>
<homeDocument>Todo</homeDocument>
<documents>
<document ref="Project" />
<document ref="Todo" />
<document ref="Staff" />
<document ref="User" moduleRef="admin" />
<document ref="Contact" moduleRef="admin" />
</documents>
<roles>
<role name="StaffManager">
<description>Staff Manager - who are able to manage Staffs</description>
<privileges>
<document permission="CRUDC" name="Staff" />
</privileges>
</role>
<role name="ProjectManager">
<description>Project Manager - who are able to manage projects and create tasks for projects.</description>
<privileges>
<document permission="CRUDC" name="Project" />
<document permission="CRUDC" name="Todo" />
</privileges>
</role>
<role name="ProjectMember">
<description>Project Member - who are not able to create project, tasks but will work with tasks to finish projects.</description>
<privileges>
<document permission="_RU_C" name="Project" />
<document permission="_RU_C" name="Todo" />
</privileges>
</role>
</roles>
<menu>
<list document="Staff" name="Staff">
<role name="StaffManager" />
</list>
<list document="Project" name="Project">
<role name="ProjectManager" />
<role name="ProjectMember" />
</list>
<list document="Todo" name="To Do">
<role name="ProjectManager" />
<role name="ProjectMember" />
</list>
</menu>
</module>
Skyve uses the term document to indicate the business-focused nature of application objects. You can find more details about Skyve Documents by following this link https://skyvers.github.io/skyve-dev-guide/documents/
Within the application file structure, each document is assigned a package. For example the Staff
package will be assigned to the Staff
document, the Project
package will be assigned to the Project
document... etc.
The document
package includes declarations of actions, reports, views and the associated Bizlet file. The Bizlet file contains document-specific behaviours including overrides of default action behaviours and document bean lifecycle events (e.g. newInstance, preSave, etc.).
More info on Bizlets can be found at the following Skyve Developer Guide link: https://skyvers.github.io/skyve-dev-guide/bizlets/
In this tutorial we will define three Documents; Staff, Project and todo (task).
Inside our todo
module, create a new Staff
package.
Inside the document package, the document.xml
file defines aspects of a document, including(bold items are compulsory):
- document metadata (name, description, aliases),
- bizKey (business key),
- attributes (fields & references),
- conditions,
- constraints, and
- documentation (doc).
To define the Staff
document we will need to create a Staff.xml
file under the Staff
document package with definition of document metadata
, bizkey
, and attributes
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<document name="Staff"
xmlns="http://www.skyve.org/xml/document"
xsi:schemaLocation="http://www.skyve.org/xml/document ../../../schemas/document.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<persistent name="Todo_Staff" />
<singularAlias>Staff</singularAlias>
<pluralAlias>Staffs</pluralAlias>
<iconStyleClass>fa fa-users</iconStyleClass>
name
: Document namepersistent
: Name of document's database tablesingularAlias
: Singular aliaspluralAlias
: Plural aliasiconStyleClass
: Document icon on the menu. Skyve usesfontawesome
as an icons resource. You can look for any icon by following this link https://fontawesome.com/icons. Please take note of thefontawesome
version to find correct icons.
In some cases, may you need to define your own custom icons. Skyve support 16 and 32 pixel icons and you can refer to them through the admin
-> contact
document.
To enable the application to display references simply, each document must define a business key (bizKey) definition (similar to a Java toString() method for the document). The bizKey is the default representation of the entire document instance.
bizKey is defined like below:
<document name="Staff"
xmlns="http://www.skyve.org/xml/document"
xsi:schemaLocation="http://www.skyve.org/xml/document ../../../schemas/document.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<persistent name="Todo_Staff" />
<singularAlias>Staff</singularAlias>
<pluralAlias>Staffs</pluralAlias>
<iconStyleClass>fa fa-users</iconStyleClass>
<bizKey expression="{user.contact.name}"/>
Each document normally has multiple attributes which can be of different data types, and how it renders in the view can also be different. Please refer to this link https://skyvers.github.io/skyve-dev-guide/documents/#attributes to understand attribute types.
In this tutorial, the Staff
document will have the attributes below:
Attribute name | Data Type - length | Description |
---|---|---|
user | User | Associate User |
socialTitle | Enum | Social titles |
dateOfBirth | Date | Date Of Birth |
idCardNo | String - 20 | ID Card Number |
issuedDate | Date | ID Card issued date |
expiryDate | Date | ID Card expiry date |
bio | Text | Brief description about staff |
dept | String - 50 | Departure |
bu | String - 50 | Business Unit |
jobTitle | String - 100 | Job Title |
startDate | Date | Started Date |
To define the above attributes, follow this definition:
<attributes>
<association name="user" type="aggregation" required="true">
<displayName>User</displayName>
<documentName>User</documentName>
</association>
<enum name="socialTitle">
<displayName>Social Title</displayName>
<defaultValue>mr</defaultValue>
<values>
<value code="mr" name="mr" description="Mr" />
<value code="ms" name="ms" description="Ms" />
<value code="mrs" name="mrs" description="Mrs" />
<value code="dr" name="dr" description ="Dr"/>
</values>
</enum>
<!-- Contact Info will be loaded from Contact Document -->
<date name="dateOfBirth" required="true">
<displayName>Date Of Birth</displayName>
</date>
<text name="idCardNo" required="true">
<displayName>ID Card Number</displayName>
<length>20</length>
</text>
<date name="issuedDate">
<displayName>Issued Date</displayName>
</date>
<date name="expiredDate">
<displayName>Expired Date</displayName>
</date>
<memo name="bio">
<displayName>BIO</displayName>
<description>Brief BIO info</description>
</memo>
<text name="dept">
<displayName>Department</displayName>
<length>50</length>
</text>
<text name="bu">
<displayName>Business Unit</displayName>
<length>50</length>
</text>
<text name="jobTitle">
<displayName>Job Title</displayName>
<length>100</length>
</text>
<date name="startDate">
<displayName>Start Date</displayName>
</date>
</attributes>
After you are finished creating the Staff
document, you should be familiar with document definition. Creating a Project
document should be easy game for you.
Please go ahead and create the Project document with below attributes:
Attribute name | Data Type - length | Description |
---|---|---|
projectCode | String - 50 | Project Code |
projectName | String - 100 | Project Name |
projectDescription | Text | Project Description |
projectOwner | Association - Contact | Project Owner |
startDate | Date | Start Date |
endDate | Date | End Date |
projectManager | Association - Staff | Project Manager |
projectCoordinator | Association - Staff | Project Coordinator |
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<document name="Project"
xmlns="http://www.skyve.org/xml/document"
xsi:schemaLocation="http://www.skyve.org/xml/document ../../../schemas/document.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<persistent name="Todo_Project" />
<singularAlias>Project</singularAlias>
<pluralAlias>Projects</pluralAlias>
<iconStyleClass>fa fa-briefcase</iconStyleClass>
<bizKey expression="{projectCode} - {projectName}"/>
<attributes>
<text name="projectCode" required="true">
<displayName>Project Code</displayName>
<length>50</length>
</text>
<text name="projectName" required="true">
<displayName>Project Name</displayName>
<length>100</length>
</text>
<memo name="projectDescription">
<displayName>Project Description</displayName>
<description>Project Description</description>
</memo>
<association type="aggregation" name="projectOwner" required="true">
<displayName>Project Owner</displayName>
<documentName>Contact</documentName>
</association>
<date name="startDate" required="true">
<displayName>Start Date</displayName>
</date>
<date name="endDate" required="true">
<displayName>End Date</displayName>
</date>
<association type="aggregation" name="projectManager" required="true">
<displayName>Project Manager</displayName>
<documentName>Staff</documentName>
</association>
<association type="aggregation" name="projectCoordinator" required="true">
<displayName>Project Coordinator</displayName>
<documentName>Staff</documentName>
</association>
</attributes>
</document>
Next, we will go to create the Todo
document. This document will present the tasks in a project for staff to do.
In this tutorial, Todo
document will have the following attributes:
Attribute name | Data Type - length | Description |
---|---|---|
taskID | String - 20 | Task ID Number |
priorityLevel | Enum | Priority Level of the task |
project | Association - Project | Project that the task belongs to |
createdBy | Association - Staff | The staff that created the task |
recordedDateTime | DateTime | When task was recorded |
startDate | DateTime | When task was started |
targetDate | DateTime | When task was expected to be complete |
actualStartDate | DateTime | Actual Start Date |
actualFinishDate | DateTime | Actual Finish Date |
taskStatus | Enum | Status of task |
Task Description | Text | Task Description |
staff | Association - Staff | Who is involved in the task |
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<document name="Todo"
xmlns="http://www.skyve.org/xml/document"
xsi:schemaLocation="http://www.skyve.org/xml/document ../../../schemas/document.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<persistent name="Todo_Todo" />
<singularAlias>Todo</singularAlias>
<pluralAlias>Todo</pluralAlias>
<iconStyleClass>fa fa-tasks</iconStyleClass>
<bizKey expression="{taskID}"/>
<attributes>
<text name="taskID" required="true">
<displayName>Task ID</displayName>
<length>20</length>
</text>
<enum name="priorityLevel">
<displayName>Priority Level</displayName>
<defaultValue>medium</defaultValue>
<values>
<value code="med" name="medium" description="Medium"/>
<value code="urg" name="urg" description="Urgent"/>
<value code="low" name="low" description="Low Priority"/>
</values>
</enum>
<association type="aggregation" name="project" required="true">
<displayName>Project</displayName>
<documentName>Project</documentName>
</association>
<association type="aggregation" name="createdBy" required="true">
<displayName>Created By</displayName>
<documentName>Staff</documentName>
</association>
<dateTime name="recordedDateTime" required="true">
<displayName>Recorded Date Time</displayName>
</dateTime>
<dateTime name="startDate">
<displayName>Start Date</displayName>
</dateTime>
<dateTime name="targetDate">
<displayName>Target Date</displayName>
</dateTime>
<dateTime name="actualStartDate">
<displayName>Actual Start Date</displayName>
</dateTime>
<dateTime name="actualFinishDate">
<displayName>Actual Finish Date</displayName>
</dateTime>
<text name="taskDescription" required="true">
<displayName>Task Description</displayName>
<length>500</length>
</text>
<enum name="taskStatus">
<displayName>Task Status</displayName>
<defaultValue>defined</defaultValue>
<values>
<value code="defined" name="defined" description="Defined"/>
<value code="pending" name="pending" description="Pending" />
<value code="assign" name="assigned" description="Assigned"/>
<value code="inprogress" name="inprogress" description="In Progress" />
<value code="review" name="review" description="Review" />
<value code="uat" name="uat" description="UAT"/>
<value code="kiv" name="kiv" description="KIV"/>
<value code="completed" name="completed" description="Completed"/>
</values>
</enum>
<association type="aggregation" name="assignTo" required="true">
<displayName>Assign To</displayName>
<documentName>Staff</documentName>
</association>
</attributes>
</document>
Now, just one final step before generating our domain!
You will need to locate your customerName.xml file, customerName will be whatever you set your Customer Name as when you first built your project in the Skyve Project Creator.
In the case of this tutorial, the Customer Name is 'tutorial'.
Once you have located your customerName.xml file, you'll need to include your todo module in your project.
Definitions of our documents is now complete. Next we will need to generate domain classes from our defined documents.
To work with our defined documents we must run the generate domain
command.
Because we have already run generate domain
previously, this time it will be faster.
Click to the button to the right of the Run as
button.
Then choose todoApp - Generate Domain
.
After Generate Domain
runs successfully, we will start the server to see our Todo App
result.
After the server runs successfully, open your web browser and access the address https://localhost:8080/todoApp and log-in with your setup
user info.
To access the Todo
module links you will need to set roles
for user.
For example, I go to set full roles
for my setup
user.
-
Go to the
User
link onSecurity Admin
, then click setup user -
Scroll down to the very bottom, you will see our
todo
roles. Choose which role you want to assign to a user. In this case I assign all relatedtodo
roles for mysetup
user. We need to select roles one by one then click theZoom Out
button and clickAdd
button and repeat until allroles
are assigned properly -
Once done with
roles
setup, clickSave
to apply your changes
After finishing the roles
setup, you will need to re-login to see the effect.
Ta-da!! Surprise!!
Now on the left menu we see our todo
module and its links.
To take note:
When you set up
roles
for auser
, you worked with a very important concept in Skyve which we callZoom
. To get more details about this concept, please spend two minutes to read from this link https://skyvers.github.io/skyve-dev-guide/concepts/#zoom
Most applications present data in both list and detail views. Skyve assumes this fact and provides rich features for each type of view.
Typically, users of applications begin with a list view of all document instances and then select a document instance to edit. This pattern of behavior is assumed in Skyve.
Skyve will provide generic/default list and edit views unless specific definitions are provided in the application metadata by the developer. This supports rapid prototyping of the domain model and gives the developer an ability to begin interacting with the application at an early stage.
List views are based on queries which generally include only key document attributes for searching and review. Each row of the list corresponds to a document instance however the list may represent data from related documents within the document’s object hierarchy.
To learn more about queries, please follow this link https://skyvers.github.io/skyve-dev-guide/modules/#queries
Lets see our Staff
list. Currently, our Staff
list shows all the information which we defined in the document's attributes section. However, since the Staff
document is related to Contact
document, we expect to show some contact information in the Staff
list too. Let's say we will show Staff Image
, Staff Name
, Staff Mobile Phone Number
, and we also will hide some information from Staff list, for example Issued Date
, Expired Date
, BIO
.
Because we did not define the query for Staff document
yet, it is showing all columns by default. So we have to open todo.xml
file to declare the query for Staff
.
Right after the Menu
declaration, we will declare Queries
like below:
<queries>
<query documentName="Staff" name="qStaff">
<description>All Staff</description>
<columns>
<content display="thumbnail" binding="user.contact.image" pixelHeight="45" pixelWidth="45" />
<column binding="user.contact.name" sortOrder="ascending" />
<column binding="user.contact.mobile" sortOrder="ascending" />
<column binding="dateOfBirth" sortOrder="ascending" />
<column binding="idCardNo" sortOrder="ascending" />
<column binding="dept" sortOrder="ascending" />
<column binding="bu" sortOrder="ascending" />
<column binding="jobTitle" sortOrder="ascending" />
<column binding="startDate" sortOrder="ascending" />
</columns>
</query>
</queries>
Then you will need to provide defaultQueryName
attribute to your Staff
document in todo.xml
, like below:
<documents>
<document ref="Project" />
<document ref="Todo" />
<document ref="Staff" defaultQueryName="qStaff"/>
<document ref="User" moduleRef="admin" />
<document ref="Contact" moduleRef="admin" />
</documents>
To apply the change, stop the WildFly
server and run the Generate Domain
command, then start the WildFly
Server again.
Ta-da!!! Amazing!!!
This is the result after our changes, looks nice right?!
As you can see our Project list needs some enhancement too. We will alter it to show Project Owner
, Project Manager
and Project Coordinator
as well as hide the Project Description
from our Project List
.
You may spend few minutes to complete it by yourself, then compare with my declaration.
<query documentName="Project" name="qProject">
<description>All Project</description>
<columns>
<column binding="projectCode" sortOrder="ascending" />
<column binding="projectName" />
<column binding="projectDescription" />
<column binding="projectOwner.name" displayName="Project Owner"/>
<column binding="startDate" />
<column binding="endDate" />
<column binding="projectManager.user.contact.name" displayName="Project Manager" />
<column binding="projectCoordinator.user.contact.name" displayName="Project Coordinator"/>
</columns>
</query>
As you can see our Todo List
is not showing Created By
and Assign To
columns yet, and we also do not want to display the Actual Start Date
and Actual Finish Date
columns.
Give it a try! You can absolutely complete it by yourself!
Once you are done with your query declaration, you can compare with my query below:
<query documentName="Todo" name="qTodo">
<description>All Todo</description>
<columns>
<column binding="taskID" sortOrder="ascending" />
<column binding="priorityLevel" />
<column binding="project.projectCode" />
<column binding="createdBy.user.contact.name" displayName="Created By"/>
<column binding="recordedDateTime" />
<column binding="startDate" />
<column binding="targetDate" />
<column binding="taskStatus" />
<column binding="taskDescription" />
<column binding="assignTo.user.contact.name" displayName="Assign To"/>
</columns>
</query>
And this is the Todo List
which we have
Ta-da!!!
We have already completed List Main
for our Todo
module. We will now cover Views, widgets and layout in the next section
In this section we will override the default detail view which is generated by Skyve.
Skyve provides us with a very useful function to create default edit view
based on our document attributes and attributes type, the default widget will be applied for each attribute type.
So to create our Staff edit view
, we will go through the following steps:
- Create
edit view
- Customize
edit view
to match our requirements.
- Right click to your
Project Name
in theProject Explorer
window -> Run As -> Run Configurations - The
Run Configuration
window appears, looking atMaven Build
then clicktodoApp - Generate Edit View
option, then click theRun
button. - Take a look on the
Console
window. It will ask you formodule name
anddocument name
. I will inputtodo
as themodule name
andStaff
as thedocument name
.
It will run and create an edit view
for us automatically.
Now, take a look in your Staff
package, you will see a views
package was created. Expand the views
package and we will see the generatedEdit.xml
file.
Now we will need to rename the xml file to edit.xml
.
A-ha, now we will add something to the edit view for testing purposes.
I will add "This is my edit view" to the view for testing, like below:
Note that: After generating each view, you will need to re-deploy your application for the changes to take affect. After re-deploying any change on the view, except for condition, we do not need to Run Configuration and re-deploy application. Just change and refresh your browser, it will take effect immediately.
After refreshing the browser we will see the text we have added to edit view
like below:
Ta-da!!! It works like a charm!!!
In the previous step we generated an edit view
by using the Generate Edit View
function. Now we will enhance our edit view
to make it more visually appealing.
As of now, Staff attributes show one by one, from top to bottom. We will enhance the view by:
- Retrieving and showing more contact information: Name, Email, Mobile Number, and Contact Image.
- Group related information together: Contact Info, Personal Info, Work Info.
We will plan to split our view into 2 sections: left
and right
. We will show Staff information
on the left side and the Staff Image
will be shown on the right part.
To do that, we will need to understand about Skyve Containers - https://skyvers.github.io/skyve-dev-guide/views/#containers
After reading through the Skyve Containers document, you may have already guessed how to split our view into 2 parts.
Yes, hbox
container will help us on this.
We will try and test our hbox
to see how it works.
I will explain further:
- Line 3: We define a
hbox
container.border=true
allows us show the border for our horizontal boxes. - Line 5: We define
vbox
to hold our Staff data later.vbox
hasresponsiveWidth
andperscentageWidth
to allow us to set width.percentageWidth
can be set from 1 to 100, and will be used ondesktop
screens, whileresponsiveWidth
can be set from 1 to 12 and will be used for responsive screens. - Line 6: We define a form. Forms will be used to hold Data Fields.
- Line 7 and line 8: we define
column
. To make it responsive we should not declare width for the last column. - Line 10: We define a
row
. - Line 11 to Line 13 define an
item
. By default, an item will take 2 columns to display, 1 for label and another one forinput
data.
And after the above definition, we will have the resultant screen below. .
Now we will move the Contact Image on the right hand side and all Staff Data to the left hand side.
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="edit" title="Staff" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<hbox border="true">
<!-- left side -->
<vbox responsiveWidth="8" percentageWidth="60">
<form>
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="user"/>
</item>
</row>
<row>
<item>
<default binding="socialTitle"/>
</item>
</row>
<row>
<item>
<default binding="dateOfBirth"/>
</item>
</row>
<row>
<item>
<default binding="idCardNo"/>
</item>
</row>
<row>
<item>
<default binding="issuedDate"/>
</item>
</row>
<row>
<item>
<default binding="expiredDate"/>
</item>
</row>
<row>
<item>
<default binding="bio"/>
</item>
</row>
<row>
<item>
<default binding="dept"/>
</item>
</row>
<row>
<item>
<default binding="bu"/>
</item>
</row>
<row>
<item>
<default binding="jobTitle"/>
</item>
</row>
<row>
<item>
<default binding="startDate"/>
</item>
</row>
</form>
</vbox>
<!-- right side -->
<vbox responsiveWidth="4" percentageWidth="40">
<form>
<column percentageWidth="20" responsiveWidth="1" />
<column />
<row>
<item>
<spacer />
</item>
<item showLabel="false">
<contentImage binding="user.contact.image" pixelWidth="200" pixelHeight="200" />
</item>
</row>
</form>
</vbox>
</hbox>
<actions>
<defaults/>
</actions>
<newParameters/>
</view>
After we're finished with the above definition, we will have a view like this:
It looks better than before right? However there are still some improvements to be made here.
We also want to get contact info(Name, Email, Phone Number) from Contacts
to show here.
To do that, right after Social Title, we add the code below:
<row>
<item>
<default binding="user.contact.name"/>
</item>
</row>
<row>
<item>
<default binding="user.contact.email1"/>
</item>
</row>
<row>
<item>
<default binding="user.contact.mobile"/>
</item>
</row>
And we will get the result below:
Next, we will group related information together to make it easier to manage.
The easiest way is to use the border
and borderTitle
attributes of the Form
container.
Note that: Form
just plays a role as a container, which have rows and columns for us to place attributes, not like a HTML Form
. So feel free to have more than one form in your view. It will help you to manage the look of the view easier.
So for this case, I will have 3 forms, one for Contact Info
, one for Personal Info
, and another one for Work Info
.
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="edit" title="Staff" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<hbox border="true">
<!-- left side -->
<vbox responsiveWidth="8" percentageWidth="60">
<form border="true" borderTitle="Contact Info">
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="user"/>
</item>
</row>
<row>
<item>
<default binding="socialTitle"/>
</item>
</row>
<row>
<item>
<default binding="user.contact.name"/>
</item>
</row>
<row>
<item>
<default binding="user.contact.email1"/>
</item>
</row>
<row>
<item>
<default binding="user.contact.mobile"/>
</item>
</row>
</form>
<form border="true" borderTitle="Personal Info">
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="dateOfBirth"/>
</item>
</row>
<row>
<item>
<default binding="idCardNo"/>
</item>
</row>
<row>
<item>
<default binding="issuedDate"/>
</item>
</row>
<row>
<item>
<default binding="expiredDate"/>
</item>
</row>
<row>
<item>
<default binding="bio"/>
</item>
</row>
</form>
<form border="true" borderTitle="Work Info">
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="dept"/>
</item>
</row>
<row>
<item>
<default binding="bu"/>
</item>
</row>
<row>
<item>
<default binding="jobTitle"/>
</item>
</row>
<row>
<item>
<default binding="startDate"/>
</item>
</row>
</form>
</vbox>
<!-- right side -->
<vbox responsiveWidth="4" percentageWidth="40">
<form>
<column percentageWidth="20" responsiveWidth="1" />
<column />
<row>
<item>
<spacer />
</item>
<item showLabel="false">
<contentImage binding="user.contact.image" pixelWidth="200" pixelHeight="200" />
</item>
</row>
</form>
</vbox>
</hbox>
<actions>
<defaults/>
</actions>
<newParameters/>
</view>
After finishing the above definition, we have a view like below:
Hmm, looks like the right side is too empty when we only have the staff image. So we will move the bio
to the right hand side to see how it looks.
I guess you know how to do it already right?
So after we move bio from Personal Info
to the right hand side section. We will have the view below:
We can say that we have already made a nice view for Staff. However, I also want to introduce View Components
to you.
So, what is View Components
?
Lets imagine that your view is very complex, lots of sections and these sections can be reused in different views.
Skyve allows for reuse of view sections via the component widget
.
To demonstrate how to re-use components, we will split our view into four components:
- Contact Info
- Personal Info
- Work Info
- Photo and Bio
The view component must be declared according to the convention, with the file name matching the declared name. The component widget then refers to that name, with the addition of a module and document (if the referenced component declaration resides in another document package).
In the Staff > views package, create new _contactInfo.xml
file with below content:
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="_contactInfo" title="Staff Contact Info" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<form border="true" borderTitle="Contact Info">
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="user"/>
</item>
</row>
<row>
<item>
<default binding="socialTitle"/>
</item>
</row>
<row>
<item>
<default binding="user.contact.name"/>
</item>
</row>
<row>
<item>
<default binding="user.contact.email1"/>
</item>
</row>
<row>
<item>
<default binding="user.contact.mobile"/>
</item>
</row>
</form>
</view>
In the Staff -> views package, create new _personalInfo.xml
file with below content:
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="_personalInfo" title="Staff Personal Info" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<form border="true" borderTitle="Personal Info">
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="dateOfBirth"/>
</item>
</row>
<row>
<item>
<default binding="idCardNo"/>
</item>
</row>
<row>
<item>
<default binding="issuedDate"/>
</item>
</row>
<row>
<item>
<default binding="expiredDate"/>
</item>
</row>
</form>
</view>
In the Staff -> views package, create new _workInfo.xml
file with below content:
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="_workInfo" title="Staff Work Info" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<form border="true" borderTitle="Work Info">
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="dept"/>
</item>
</row>
<row>
<item>
<default binding="bu"/>
</item>
</row>
<row>
<item>
<default binding="jobTitle"/>
</item>
</row>
<row>
<item>
<default binding="startDate"/>
</item>
</row>
</form>
</view>
In the Staff -> views package, create new _photoBio.xml
file with below content:
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="_photoBio" title="Staff Photo and Bio" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<form>
<column percentageWidth="20" responsiveWidth="1" />
<column />
<row>
<item>
<spacer />
</item>
<item showLabel="false">
<contentImage binding="user.contact.image" pixelWidth="200" pixelHeight="200" />
</item>
</row>
<row>
<item>
<spacer />
</item>
<item showLabel="false">
<textArea binding="bio"></textArea>
</item>
</row>
</form>
</view>
After done with component creation, we will go to use it on our edit
view.
Change edit.xml
view like below:
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="edit" title="Staff" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<hbox border="true">
<!-- left side -->
<vbox responsiveWidth="8" percentageWidth="60">
<component name="_contactInfo" />
<component name="_personalInfo" />
<component name="_workInfo" />
</vbox>
<!-- right side -->
<vbox responsiveWidth="4" percentageWidth="40">
<component name="_photoBio"/>
</vbox>
</hbox>
<actions>
<defaults/>
</actions>
<newParameters/>
</view>
We will re-deploy our application to take affect. After re-deployment and re-login to the system. We will have the same view as our original before:
In the next section we will reuse our view component to create a different layout for desktop screens.
Desktop provides a good end user experience, and there are some features which are only available on desktop but not on other devices such as tablet, or mobile.
To demonstrate for desktop view, we will:
- Create view for desktop
- Change the layout to make left and right parts the same width
- Add Staff location which uses
Geometry
data.
- Create a new package named
desktop
inside theviews
package of the Staff Document. - Copy
edit.xml
file fromviews
package toviews.desktop
package. - Re-deploy the application to take effect.
We will change the layout of desktop view to make left and right sections have the same width.
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="edit" title="Staff" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<hbox border="true">
<!-- left side -->
<vbox responsiveWidth="6" percentageWidth="50">
<component name="_contactInfo" />
<component name="_personalInfo" />
<component name="_workInfo" />
</vbox>
<!-- right side -->
<vbox responsiveWidth="6" percentageWidth="50">
<component name="_photoBio"/>
</vbox>
</hbox>
<actions>
<defaults/>
</actions>
<newParameters/>
</view>
Login to the application.
Then switch to desktop view by click to the Switch
button on the top right corner.
Go to Staff
, then we will see the difference between desktop view and our normal view.
Skyve provides a Google maps API by default, however it is your responsibility to consider usage, licencing and billing implications when used in your application. Refer to Google terms to find out more.
Skyve applications can take advantage of other map APIs (for example; Leaflet, OpenStreetMap .etc) however these APIs are not included in the open-source Skyve distribution. For assistance, contact us at skyve.org to discuss detailed steps for other integration options.
In this section we will use Geometry
with Google Maps. So you will need to have a Google Map API V3 key
. You can follow this link https://developers.google.com/maps/documentation/javascript/get-api-key to get one.
After you have the key, you will need to set it in the APIs section of todoApp.json
(hopefully you still remember your key ;) )
In the Servers
window, right click on your Wildfly server and choose Show in
, then select File Browser
.
Locate the todoApp.json
file and open it in your code editor.
Look for 'API Settings', and set your googleMapsV3Key
with the key
you have.
Now, we will add Staff Location
to our Staff Document
.
<geometry name='staffLocation'>
<displayName>Staff Location</displayName>
</geometry>
Add this definition right after the bio definition.
After adding the Staff Location
attribute, we must run Generate Domain
.
Once, the Generate Domain
command runs successfully, we will amend our views.
Geometry
is not yet supported on responsive mode yet, so in this view, we will show a text to instruct user to go to desktop
mode to use Geometry
feature.
We will add Staff Location to the right side of the screen.
Staff Responsive View
.
<!-- right side -->
<vbox responsiveWidth="4" percentageWidth="40">
<component name="_photoBio"/>
<form>
<column percentageWidth="20" responsiveWidth="1" />
<column />
<row>
<item>
<spacer />
</item>
<item showLabel="false">
<blurb>To set Staff Location, please switch to Desktop Mode</blurb>
</item>
</row>
</form>
</vbox>
Staff Desktop View
<!-- right side -->
<vbox responsiveWidth="6" percentageWidth="50">
<component name="_photoBio"/>
<form>
<column percentageWidth="20" responsiveWidth="1" />
<column />
<row>
<item>
<default binding="staffLocation"/>
</item>
</row>
</form>
</vbox>
You can click to the right icon of Staff Location
to set Staff Location
.
In the previous section you explore and practice how to create an edit view
and customize it to meet project requirements. Now it should be easier for you to create an edit view
for your Project
document right?
Lets demonstrate that our project edit view
may look like below:
It includes 3 components
:
- Project Info: to show project information.
- Project Owner Info: to show project owner information.
- Project Operator: to show project operator information.
Here are some guidelines to help you finish this edit view by your self.
- Run
Generate edit view
command to generateProject edit view
- Create
view components
for each section - Combine
view components
together. - Run
Generate Domain
command and re-deploy the application. - Adjust your view if required.
You may choose to stop reading through this tutorial for 10 to 20 minutes in order to try to complete it by yourself, and then after you are done you can compare it with our work.
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="_projectInfo" title="Project" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<form border="true" borderTitle="Project Info">
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="projectCode"/>
</item>
</row>
<row>
<item>
<default binding="projectName"/>
</item>
</row>
<row>
<item>
<default binding="projectDescription"/>
</item>
</row>
<row>
<item>
<default binding="startDate"/>
</item>
</row>
<row>
<item>
<default binding="endDate"/>
</item>
</row>
</form>
</view>
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="_projectOwnerInfo" title="Project" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<form border="true" borderTitle="Project Owner Info">
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="projectOwner"/>
</item>
</row>
<row>
<item>
<default binding="projectOwner.name"/>
</item>
</row>
<row>
<item>
<default binding="projectOwner.email1"/>
</item>
</row>
<row>
<item>
<default binding="projectOwner.mobile"/>
</item>
</row>
<row>
<item>
<spacer />
</item>
<item showLabel="false">
<contentImage binding="projectOwner.image" pixelWidth="200" pixelHeight="200" />
</item>
</row>
</form>
</view>
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="_projectOperator" title="Project" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<form border="true" borderTitle="Project Operator">
<column percentageWidth="30" responsiveWidth="4"/>
<column/>
<row>
<item>
<default binding="projectManager"/>
</item>
</row>
<row>
<item>
<default binding="projectManager.user.contact.email1"/>
</item>
</row>
<row>
<item>
<default binding="projectManager.user.contact.mobile"/>
</item>
</row>
<row>
<item>
<spacer />
</item>
<item showLabel="false">
<contentImage binding="projectManager.user.contact.image" pixelWidth="200" pixelHeight="200" />
</item>
</row>
<row>
<item>
<default binding="projectCoordinator"/>
</item>
</row>
<row>
<item>
<default binding="projectCoordinator.user.contact.email1"/>
</item>
</row>
<row>
<item>
<default binding="projectCoordinator.user.contact.mobile"/>
</item>
</row>
<row>
<item>
<spacer />
</item>
<item showLabel="false">
<contentImage binding="projectCoordinator.user.contact.image" pixelWidth="200" pixelHeight="200" />
</item>
</row>
<row>
<item colspan="2">
<spacer />
</item>
</row>
</form>
</view>
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="edit" title="Project" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<hbox border="true">
<vbox responsiveWidth="6" percentageWidth="50">
<component name="_projectInfo" />
<component name="_projectOwnerInfo" />
</vbox>
<vbox responsiveWidth="6" percentageWidth="50">
<component name="_projectOperator" />
</vbox>
</hbox>
<actions>
<defaults/>
</actions>
<newParameters/>
</view>
In the previous section we finished the Project Edit view
. We will now create our final view for Todo Edit view
.
Todo Edit view
will have an interface like below:
It includes 2 parts:
- General Information
- Process
You can scroll up a bit to read the guideline on how to create Project Edit view
and apply to create Todo edit view
.
We suggest you stop reading for a while and attempt your Todo Edit view
before comparing with our definition below.
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="_generalInfo" title="Todo" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<form border="true" borderTitle="General Info">
<column percentageWidth="40" responsiveWidth="5"/>
<column/>
<row>
<item>
<default binding="taskID"/>
</item>
</row>
<row>
<item>
<default binding="priorityLevel"/>
</item>
</row>
<row>
<item>
<default binding="project"/>
</item>
</row>
<row>
<item>
<default binding="createdBy"/>
</item>
</row>
<row>
<item>
<default binding="taskDescription"/>
</item>
</row>
<row>
<item colspan="2">
<spacer />
</item>
</row>
</form>
</view>
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="_process" title="Todo" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<form border="true" borderTitle="Todo Process">
<column percentageWidth="40" responsiveWidth="5"/>
<column/>
<row>
<item>
<default binding="assignTo"/>
</item>
</row>
<row>
<item>
<default binding="recordedDateTime"/>
</item>
</row>
<row>
<item>
<default binding="startDate"/>
</item>
</row>
<row>
<item>
<default binding="targetDate"/>
</item>
</row>
<row>
<item>
<default binding="taskStatus"/>
</item>
</row>
<row>
<item>
<default binding="actualStartDate"/>
</item>
</row>
<row>
<item>
<default binding="actualFinishDate"/>
</item>
</row>
</form>
</view>
<?xml version="1.0" encoding="UTF-8"?>
<view xmlns="http://www.skyve.org/xml/view" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="edit" title="Todo" xsi:schemaLocation="http://www.skyve.org/xml/view ../../../../schemas/view.xsd">
<hbox>
<vbox responsiveWidth="6" percentageWidth="50">
<component name="_generalInfo" />
</vbox>
<vbox responsiveWidth="6" percentageWidth="50">
<component name="_process" />
</vbox>
</hbox>
<actions>
<defaults/>
</actions>
<newParameters/>
</view>
We've now finished our views. In the next section we will cover some advanced concepts such as condition, action and event handler. To apply these concepts, our Application will become more logical, aiming for a high production grade of an application.
In the todo document, when selecting which user to assign the task to, we may want to see some of the information about the user we have selected.
This can be achieved through further usage of conditions. In particular, we can have a condition to determine the visibility of some specified attributes on the screen.
To begin with, we define the condition in the Todo.xml
. Similarly to the before example, we want to add the conditions definition after the attributes definitions. We will define this condition as follows:
<conditions>
<condition name="assigned">
<expression>assignTo != null</expression>
</condition>
</conditions>
This condition will check if a user has been selected for the assignTo attribute.
Now we need to change the assignTo binding such that it will update the attributes on the selection of the user. This is done as follows in the _process.xml
:
<row>
<item>
<lookupDescription binding="assignTo" descriptionBinding="bizKey">
<onPickedHandlers>
<rerender clientValidation="false" />
</onPickedHandlers>
</lookupDescription>
</item>
</row>
Next, we need to define which elements of the user's information we want to show by editing the _process.xml
further. To do this, we need to add bindings for the attributes to be displayed within the todo view below the previous section. In this case we will display the name, email and mobile number of the user that is selected like below:
<row>
<item>
<textField binding="assignTo.name" visible="assigned" editable="false"/>
</item>
</row>
<row>
<item>
<textField binding="assignTo.email1" visible="assigned" editable="false"/>
</item>
</row>
<row>
<item>
<textField binding="assignTo.mobile" visible="assigned" editable="false"/>
</item>
</row>
Now, when we select a user to assign the task to in the todo document, it will display the name, email and mobile number of the corresponding user selected as shown in the photo below
In this section we will update our Todo
application to make it more powerful and closer to the production grade of an application.
We will go through and apply some concepts such as condition
, filter
, and action
and we also will touch on the bizlet and extension class
- Bizlet
, which is a class related to a document which extends default bean behaviours.
Firstly we will enhance the Staff
document to see how we can apply the above concepts to our document.
- Add
My Staff Information
menu item toProject Member
- Only allow
Staff Manager
to selectUser
. - When Staff Manager selects User from dropdown box, it will automatically update contact information and contact image.
User
dropbox should not show user which associates with anotherStaff
- Only allow
Staff Manager
to updateWork Info
data - Allow
Project Member
to updateContact Info
andPersonal Info
only.
I will login to the application by using a Project Member
user account.
I can find which users are under the Project Member
group by logging into the application through an admin account and opening Admin > Security Admin > Groups
and then opening the Project Member
group.
There is a Users in Group
tab which shows all users included in this group.
So I will re-login with one of these users accounts.
Please take a look at Todo Module
. We don't want people in Project Member
to see the details of Project
because there is Project Owner
information that should not be visible to a Project Member User
.
Open todo.xml
and locate the menu
definition section.
<menu>
<list document="Staff" name="Staff">
<role name="StaffManager" />
</list>
<list document="Project" name="Project">
<role name="ProjectManager" />
<role name="ProjectMember" />
</list>
<list document="Todo" name="To Do">
<role name="ProjectManager" />
<role name="ProjectMember" />
</list>
</menu>
We will remove the role ProjectMember
from Project
<menu>
<list document="Staff" name="Staff">
<role name="StaffManager" />
</list>
<list document="Project" name="Project">
<role name="ProjectManager" />
</list>
<list document="Todo" name="To Do">
<role name="ProjectManager" />
<role name="ProjectMember" />
</list>
</menu>
We also create My Staff Information
for Project Member
so they can see and update their information from here.
<menu>
<list document="Staff" name="Staff">
<role name="StaffManager" />
</list>
<edit document="Staff" name="My Staff Information">
<role name="ProjectMember" />
</edit>
<list document="Project" name="Project">
<role name="ProjectManager" />
</list>
<list document="Todo" name="To Do">
<role name="ProjectManager" />
<role name="ProjectMember" />
</list>
</menu>
Lets say we want to allow a Project Member
to create or update their Staff Information, however their Staff Information was created by a Staff Manager
previously. So in this case we will need to allow Project Member
to Create
,Read
,Update
their Staff document on Customer scope. But we will restrict it to show their own staff record only. To do this, we replace the previous role definition of Project Member
with the below code
<role name="ProjectMember">
<description>Project Member - who are not able to create project, tasks but will work with tasks to finish projects.</description>
<privileges>
<document permission="_RU_C" name="Todo" />
<document permission="CRU_C" name="Staff" />
</privileges>
</role>
After completing the above tasks, we will need to run Generate Domain
and re-deploy our application.
Now, we will login as a Project Member
to see the change.
However, it is not quite finished yet, when you click the menu link, it will show a new blank Staff
document.
We will have to change a little bit here to load in the correct user data. When loading My Staff Information
, we will check whether any Staff
are associated with the current user or not, if there is we will load it.
To do the above we will need to create a Bizlet
for the Staff
document and override the newInstance
method.
To learn more about Bizlet
, you can have a read at https://skyvers.github.io/skyve-dev-guide/bizlets/
Now, let me to show you how we can create StaffBizlet
to customize the document as we want.
Right-click to the Staff
package and select New
, then select Class
in the sub-menu.
The new Class window will appear like below:
- Name: set class name to StaffBizlet
- Superclass: click on Browse, and select BizLet as Superclass.
Then click Finish.
The StaffBizlet
class was created, however we will need to make some changes here.
We will fix these issues by using Eclipse Quick Fix suggestions (multiple class imports will be needed).
Alright, after following the Quick Fix suggestions we've fixed the above two issues.
Next, we will override the newInstance
method to read Staff information
if it has already been created.
Eclipse will generate newInstance
method and override anotation for us. We will need to update the method like below:
@Override
public Staff newInstance(Staff bean) throws Exception {
// Create Document Query for Staff Document
DocumentQuery dq = CORE.getPersistence().newDocumentQuery(Staff.MODULE_NAME, Staff.DOCUMENT_NAME);
dq.getFilter().addEquals(Staff.userPropertyName, ModulesUtil.currentAdminUser());
// Create staff from dq bean result
Staff staff = dq.beanResult();
// in case of staff is null, we will return an empty bean with User and Contact Information
if (staff == null) {
bean.setUser((UserExtension) ModulesUtil.currentAdminUser());
return bean;
}
// else return staff
return staff;
}
Save the StaffBizlet
class and run the Generate Domain
command, then re-deploy your application to your server.
Once done, login to your application as a Project Member
and click on the My Staff Information
link, now we can see the data loaded properly.
As you can see, when we login to the application as a Project
member I also can see the User
select box. This is not good practice in production application. So in this section we will enhance our application to make sure this User
select box is visible for Staff Manager
only.
To archive our purpose, we will work with condition
.
Huh, what is the document condition?
Quick answer is as below:
-
Document conditions are code snippets which return a Java boolean value, and which can be used by view declarations.
-
By restricting client-side view conditions to server-side compiled code rather than client-side Javascript (or other client script), the risks of developer bugs is significantly reduced. Only the result of the condition is passed to the client, so the chance of an invalid or unintended result is minimised. This also means that client interactions can have access to the results of the full breadth of the server-side code base, utilities and libraries, while all code is maintained in one central location. The additional benefit is that all application code is in one language.
Sound right for us right?
So how we can apply this to our case?
Let us define it first.
Lets open Staff.xml
file, scroll down to very bottom. Right after attributes definition we will add conditions definition like below:
<conditions>
<condition name="staffManager">
<expression><![CDATA[isUserInRole("todo","StaffManager")]]></expression>
</condition>
</conditions>
This condition will check if the logged in user's role is Staff Manager or not.
Then apply it to Staff
view.
Open _contactInfo.xml
and change user
binding like below:
<row>
<item>
<lookupDescription descriptionBinding="bizKey" binding="user" visible="staffManager"/>
</item>
</row>
Once done, save the file, run the Generate Domain
command and re-deploy your application to apply the condition.
Now when we are logged in as a Project Member
the User
dropdownbox will disappear.