Before we start coding, make sure you don't move your right hand's fingers away from the kwyboard.

We are going to first find the library repo. 

Initialize an empty folder;

Since it's an mvvm framework, let's create mock data first.

After the UI is done.

It's time to set about to craft the backend part.

We are saving projects and tasks.

So there are two tables.

Let's write the sql:

create table project {

id int not null auto_increment,

name varchar(50),

status int,

primary key(id)

}

create table task{

id int not null auto_increment,

pid int,

project_id int,

name varchar(50),

remark varchar(500),

status int,

primary key(id)

}

project and task both have status enum, here we set the enum to  NoStarted, InProgress, Done, Archived.

So, it's to create the APIs, let's first define the APIs.

getProjects(condition), getTasks(projectId,condition), saveProject(info), saveTask(info,projectId),delProjects(projectIds), delTask(ids), next when the UI is ready, we will tailor the API definitions.

okay, we are here already, time to build now.


As to the UI, since this is a simple UI, I think I could just write the css.

Split the page into 3 columns, project list, task tree, project form and task form vertically.


As to the logic, now write pseudo code for the main logic:

GetProjects=>ProjectItem.onclick=> ajaxQueue(getTasks=>InitTasksTree

TaskNode.onclick=>addSubTask/DelTask


Actually, as to the plugin part, my thinking is to extend the page model( pluginName), then render the dom contents with symbols of the framework such as @click, @field.


Every field or control that the framework walks over has data-xpath, arrays have data-index, controls have @click,

Next we talk about the tree building, tree is using recursion to construct  <ul> and embed <ul> to <li> items.

If want to add checkbox to interact with sub nodes, other methods are needed, still use recursion, CollectSubNode(node), checkbox.onclick=>subNodesCollection=[], collectSubNodes(node), if node.hasChildren, subNodesCollection.push(children), iterate subNodes, still collectSubNodes, this is to set checkbox status of subnodes if parent node checkbox status changes.  

Still bind additional fields to dataset of the element which need the @click event, the method will receive the element as first argument in definition. To interact with checkbox, should use @change event to judge el.checked==true/false.

The code now is like below,


    

<!DOCTYPE html>

<html lang="en">


<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Document</title>

    <script src="./calo.utils.js"> </script>

    <script src="./calo.js"> </script>

    <script src="./pluginTree.js"></script>

    <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.6.0.min.js"></script>

    <style>

        li {

            list-style-type: none;

        }

    </style>

</head>


<body>


    <div id="app1">

        <span @click="n2">test</span>

        <input type="checkbox" @Change="n2" />

        <input type="text" @field="cur" />

        <select @Change="n3">

            <option>1</option>

            <option>2</option>

        </select>


        <ul>

            <li @field="projects|"></li>

        </ul>


        <div ref="taskTree">

        </div>

    </div>

    <script>


        var x = new calo(document.getElementById("app1"),

            {

                model: {

                    currentTaskId: 0,

                    projects: ["a", "b", "c", "d"]

                },

                global: { cur: 0 },

                n1: function (a) {

                    console.log(a)

                    if (a.dataset.url === undefined) {

                        console.log(a.parent)

                        a.parentNode.children[2].style.display = a.parentNode.children[2].style.display === 'none' ? '' : 'none'

                    }

                },

                n2: function (a) {

                    alert(a.checked)

                    this.settings.global.currentTaskId = 99

                },

                n3: function (a) {

                    alert(a.value)

                    this.settings.global.currentTaskId = 0

                }

            })

        x.callPlugin(x.refs.taskTree, pluginTree)



    </script>

</body>


</html>


image.png



没有登录不能评论