DEV Community

Vesin Dusko
Vesin Dusko

Posted on

ToDo app with Sifu code generator

As part of promoting DRY (don't repeat yourself), MDD (model-driven development), and code generator, I would like to show its full power on a real-life example.

We will implement a simple ToDo app with backend and client app. Let's start.

ToDo project

First we will define the project with basic informations.

todo project[ url www.todo.com namespace com.todo version 1 . 0 . 0 . 0 environments prod developer(duskovesin) ]( 
Enter fullscreen mode Exit fullscreen mode

Backend

Now we will define the #backendpart of the app.

backend server[ owners(duskovesin) template springboot(tests fabut) ] 
Enter fullscreen mode Exit fullscreen mode

We are starting with the definition of User and Todo #models, with a few fields and Todo Status #enums.

 UserRole enum( ADMIN MEMBER ) Status enum( NOT_STARTED IN_PROGRESS DONE ) User model( firstName text[min 1, max 40, searchable] lastName text[min 1, max 60] ) Todo model( user User task text[min 1, max 255] date date status Status ) 
Enter fullscreen mode Exit fullscreen mode

We also need to specify the type of security that we want to use in the app, in this case, we are using role-based security on top of the User model with #username and #password as security #authentication.

 security( principal User role UserRole type username ) 
Enter fullscreen mode Exit fullscreen mode

Now we can focus on APIs. We will create two sets of #REST APIs.

UserApi

UserApi will have #CRUD API endpoints for manipulation with users in the system, that can be accessed only by ADMIN users, users endpoint to access to all users in the system, and one that Admin can use to check other users Todos.

UserApi api( user crud[model User, rest, secured ADMIN] users read[ select from User rest secured ADMIN ] userTodos read[ select from Todo where Todo.user == user orderable by Todo.task rest secured ADMIN ] ) 
Enter fullscreen mode Exit fullscreen mode

TodoApi

TodoApi with CRUD endpoints for users to be able to create ToDo and userTodos endpoint that will be used by any users to access ti his own ToDos.

 TodoApi api( todo crud[model Todo, rest] todos read[ select from Todo join User on Todo.user response list dto( Todo.id userUsername User.username Todo.task Todo.date Todo.status ) rest secured(ADMIN, MEMBER) ] ) 
Enter fullscreen mode Exit fullscreen mode

On average, for developers to implement all controllers, APIs, DTOs, models, enums and repositories, db-changelogs and all other parts of sping boot infrastructure code would take at least a few days...

WebApp

Now lets move to the client part of the app.

First, let's define the client app and specify which type of applications it will be generated to. Also, we will define, to which backend it will be connected. Also, we will define the application path and which page is the home page for admin and member users.

webapp client[ owners(duskovesin) connectedTo backend template angular path /webportal home todosPage(ADMIN, MEMBER) ] 
Enter fullscreen mode Exit fullscreen mode

Now we need to create two pages, one for users to organize their ToDos and the other one for admins to administrate with users.

ToDo page

ToDo page will have a list of user todos, add a button for creating new todo, edit button for opening edit form and delete button for todo deletions. All components will be connected with appropriate API calls which can be seen in the spec.

 todosPage page[ path /todos secured(ADMIN, MEMBER) ]( addTodo button { on click open createTodo(none) { on closed do todos.load } } todos table[ load TodoApi.todos ]( editTodo button { on click open editTodo(item.id) } deleteTodo button { on click open deleteTodo(item.id) } ) ) createTodo form[ submit TodoApi.createTodo ] { on success close } editTodo form[ load TodoApi.readTodo submit TodoApi.updateTodo ] { on success close } deleteTodo form[ load TodoApi.readTodo submit TodoApi.deleteTodo ] { on success close } 
Enter fullscreen mode Exit fullscreen mode

Users page

The users page will be organized in the same way, with a small difference that the admin user will be able to access the ToDos of the other users.

 usersPage page[ path /users secured ADMIN ]( addUser button { on click open createUser(none) { on closed do users.load } } users table[ load UserApi.users ]( viewUserTodos button { on click fire ViewTodos(item.id) } editUser button { on click open editUser(item.id) } deleteUser button { on click open deleteUser(item.id) } ) { ViewTodos event(id integer) external { on ViewTodos do userTodos.reload(event.id, none, none) } } userTodos table[ input(*, *, *) load UserApi.userTodos ] ) createUser form[ submit UserApi.createUser ] { on success close } editUser form[ load UserApi.readUser submit UserApi.updateUser ] { on success close } deleteUser form[ load UserApi.readUser submit UserApi.deleteUser ] { on success close } 
Enter fullscreen mode Exit fullscreen mode

Security page with sign-in form is automatically generated according to the best practices.

The amount of code that's necessary to write to do this basic implementation is:

Language files blank comment code ------------------------------------------------------------------------------- Java 148 2056 93 9193 TypeScript 45 660 113 3083 HTML 19 1 0 1114 XML 14 0 4 881 JSON 9 0 0 654 Maven 3 0 4 246 Sass 11 44 12 152 YAML 3 2 0 102 JavaScript 2 3 4 61 Markdown 2 13 0 16 ------------------------------------------------------------------------------- SUM: 256 2779 230 15502 ------------------------------------------------------------------------------------ 
Enter fullscreen mode Exit fullscreen mode

Thanks to code generator sifu we are able to implement it in under 30 minutes...

You can check the code on github

Top comments (0)