Module:Kanban

A very basic module to display tasks in little separate boards ("kanban"), aimed at wiki editors. The module is split in 2 parts: the logic of the kanban itself, and the list of tasks.

Example

{{#invoke:kanban|main|src=NAME OF THE MODULE WITH THE TASKS}}
Low (1)
Bulba task

Lorem ipsum

Due Date: 21 Oct 2024

Medium (2)
Charizard task

Lorem ipsum

Due Date: 21 Oct 2024

Sensei task

Lorem ipsum

Due Date: 21 Oct 2024

Long-term (1)
My task

Lorem ipsuaaaam

Due Date: 21 Oct 2024

Completed (1)
Rubra task

Lorem ipsum

Due Date: 21 Oct 2024

Arguments

  • src: name of the module with the list of tasks.

List of tasks

The list of tasks is a table with nested tables within, each one contains the following parameters:

Parameter Description
title Title of the task
Description (optional) A brief description of the task
Priority
  • 1 = Low priority
  • 2 = Medium priority
  • 3 = High priority
  • 0 = Long-term (very low priority)
due_date (optional) If the task has a date to be completed
completed Marks the task as completed (independently of priority). Either true or false (boolean).

Example

local tasks = {
	{
        title = "First task",
        description = "Lorem ipsum",
        priority = 1,
        due_date = "21 Oct 2024",
        completed = true
    },
    {
        title = "Second task",
        description = "Lorem ipsuaaaam",
        priority = 0,
        due_date = "21 Oct 2024",
        completed = false
    },
   ...
}

return tasks

-- (c) 2024 Lakelimbo <[email protected]>
-- This code is licensed under Creative Commons BY-NC-SA 2.5
--[[
    A module to group and display tasks in little boards ("kanban").
    Very basic, and more useful for staff members.
]]

local kanban = {}
local container = mw.html.create("div")
    :tag("div")
    :css({
        display = "flex",
        ["flex-wrap"] = "wrap",
        gap = "0.5rem",
        ["max-width"] = "1048px"
    })

---Function that generates each board
---@param priority number|"complete"
---@param tasks table
local function group(priority, tasks)
    -- Basic lookup table for the name and colors
    -- the board
    local details = {
        [0] = {
            name = "Long-term",
            background = "#f8ebff",
            border = "#c61afc",
        },
        [1] = {
            name = "Low",
            background = "#ebf3ff",
            border = "#6161f0",
        },
        [2] = {
            name = "Medium",
            background = "#fcffeb",
            border = "#fc911a"
        },
        [3] = {
            name = "High",
            background = "#ffebeb",
            border = "#fc1a1a",
        },
        complete = {
            name = "Completed",
            background = "#ebffeb",
            border = "#0ac921",
        }
    }

    local group_container = container
        :tag("div")
        :css({
            flex = "216px",
            background = details[priority].background,
            border = "2px solid " .. details[priority].border,
            padding = "0.333rem",
            ["border-radius"] = "1rem",
        })

    group_container
        :tag("div")
        :css({
            ["font-size"] = "17px",
            ["font-weight"] = "bold",
            ["text-align"] = "center",
        })
        :wikitext(details[priority].name)
        :wikitext(" (" .. #tasks .. ")")

    for _, task in ipairs(tasks) do
        local task_container = group_container
            :tag("div")
            :css({
                background = "#fff",
                border = "1px solid #ddd",
                margin = "0.5rem 0",
                padding = "0.5rem",
                ["border-radius"] = "0.75rem",
            })

        task_container
            :tag("div")
            :css({ ["font-weight"] = "bold" })
            :wikitext(task.title)

        task_container:tag("p")
        if task.description then
            task_container:wikitext(task.description)
        else
            task_container
                :css({ ["font-style"] = "italic" })
                :wikitext("No description provided")
        end
        task_container:done()

        if task.due_date then
            task_container:tag("p"):wikitext("Due Date: " .. task.due_date)
        end
    end
end

---The kanban itself
---@return string
function kanban.main(frame)
    local src = require(frame.args["src"])

    local tasks = {}
    local tasks_completed = {}

    for _, v in ipairs(src) do
        if v.completed then
            table.insert(tasks_completed, v)
        else
            if not tasks[v.priority] then
                tasks[v.priority] = {}
            end

            table.insert(tasks[v.priority], v)
        end
    end

    for priority, items in pairs(tasks) do
        group(priority, items)
    end

    if #tasks_completed > 0 then
        group("complete", tasks_completed)
    end

    return tostring(container)
end

return kanban