Our flexible Kanban board for managing tasks with drag drop


Post by shimnx »

I want to customize the filter criteria, but that doesn't seem to work
Do I need to add eventStore, and how do I introduce eventStore

 tbar: [
        { type : 'taskfilterfield' },
        // Field for filtering columns
        // { type : 'columnfilterfield' },
        // Field for filtering swimlanes
        { type : 'swimlanefilterfield' },
        // Move the last items to the right
        '->',
        {
            type: 'filterfield',
            filterFunction : (record, value)  => {
                console.log(value)
               return record.text.includes(value);
            }
        }
        // Button to pick which columns are shown
        // { type : 'columnpickerbutton' },
        // Button to pick which swimlanes are shown
        // { type : 'swimlanepickerbutton' }
    ],

Post by tasnim »

You need to define the store :

{
	type: 'filterfield',
	store : taskStore,
	filterFunction : () => {...}
}

https://bryntum.com/docs/taskboard/api/Core/widget/FilterField

Best of luck,
Tasnim


Post by shimnx »

How do I introduce taskStore


Post by shimnx »

/*
 * @Description:
 * @Version: 2.0
 * @Autor: shimnx
 * @Date: 2022-07-27 09:11:33
 * @LastEditors: shimnx
 * @LastEditTime: 2022-08-12 19:41:35
 */
import { TaskBoardConfig, ProjectModelConfig, TaskModel } from '@bryntum/taskboard';
import { Button, TaskBoard, Toast, MessageDialog, StringHelper } from '@bryntum/taskboard';
import moment from 'moment';
import {ScrumBoardComponent} from './scrum-board/scrum-board.component'
import { ProjectTaskComponent } from './project-task/project-task.component'

export const projectConfig: Partial<ProjectModelConfig> = {};

class CustomTask extends TaskModel {
    static fields = [
        'priority',
        'progress'
    ];
}
const teamIcons = {
    medium  : 'pen-fancy',
    high : 'weight-hanging',
    low  : 'hammer',
};
export const taskBoardConfig: Partial<TaskBoardConfig,> = {
    useDomTransition     : true,  // Experimental, transition moving cards using the editor
    stickyHeaders        : true,  // Want headers to stick to the top,
    showCollapseInHeader : false, // Hide column collapse tool
    showCountInHeader    : false, // Hide task count from column headers
    resourceImagePath    : 'assets/users/', // Url for resource avatar images
    css: {
        background: '#fff',
        bodyPadding: '.5em',

    columnBackground: '#f9f9f9',
    columnHeaderBorderTop: '5px solid #00893d',

    cardBorderTop: '5px solid #00893d',
    cardFooterFontSize: '.8em'
},
features: {
    columnHeaderMenu : { disabled : true },
    simpleTaskEdit   : { disabled : false },
    taskMenu: true,
    swimlaneDrag: { disabled : false,
        listeners:(data)=>{
            console.log(data)
        }
    },
    taskEdit: {
        processItems(data) {
            console.log();
            // data.taskRecord.name = 'change';
            (window as any).ProjectTaskComponent.component.openTask(data.taskRecord);
            // console.log(new ScrumBoardComponent().drawer)
            // (window as any).ScrumBoardComponent.component.openDrawer();
            // console.log(data.taskRecord.stores)
            return false
        },
        items:{

            priority: {
                type: 'combo',
                items: Object.keys(teamIcons),
                label: 'Priority',
                onSelect:(event)=>{
                    console.log(event)
                }
            }
        }

    },

},
// swimlanes: [
//     { id: 'GroupA', text: 'GroupA', color: '#FF9800' },
//     { id: 'GroupB', text: 'GroupB', color: '#E62C27' },
//     { id: 'GroupC', text: 'GroupC', color: '#1CAA52' }
// ],
autoGenerateSwimlanes : true,
swimlaneField: 'groupName',
// Add a button to show the context menu to card header
headerItems: {
    menu: { type: 'taskMenu', order: 200 }
},

// Add a progress bar to card body
bodyItems: {
    // Progress bar, 0 - 100
    progress: { type: 'progress', max: 100 },

    // Image
    image: { type: 'image', baseUrl: 'resources/' },

    // Separator line, uncomment to show
    // separator : { type : 'separator' },

    // Rating (starts), uncomment to show
    // rating   : { type : 'rating', max : 5 },

    // Team icon + text

    prio: {
        type: 'template',
        template: ({ value }) => {
            if(value=='Medium'){
                return  `<div class="medium">${value}</div>`
            }
            if(value=='High'){
                return  `<div class="high">${value}</div>`
            }
            if(value=='Low'){
                return  `<div class="low">${value}</div>`
            }
        }
    },
    date: {
        type: 'template',
        template: ({ value }) => {
            const diff3 = moment(new Date()).diff(moment(value), 'days')
            if(diff3>0){
                return `<div class='late'>${value}</div>`
            }else{
                return `<div class='normal'>${value}</div>`
            }
        }
    }
},

// Add a template displaying priority to card footer
footerItems: {
    assigner:{
        type: 'template',
        template: ({ value }) => {
            return  `<div>${value}</div>`
        }
    },
    dailyTaskCount: { type: 'template', template: ({ value }) => `Daily Task ${value}` },
    actionCount: { type: 'template', template: ({ value }) => `Action ${value}` },

},

project: {
    taskModelClass : CustomTask,
    // empty to start with
},
tbar: [
    { type : 'taskfilterfield' },
    // Field for filtering columns
    // { type : 'columnfilterfield' },
    // Field for filtering swimlanes
    { type : 'swimlanefilterfield' },
    // Move the last items to the right
    '->',
    {
        type: 'filterfield',
        placeholder: 'Highlight tasks',
        // onChange({value}) {
        //     value = value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
        //     // A filter with an id replaces any previous filter with that id.
        //     // Leave any other filters which may be in use in place.
        //     console.log(value)
        //     window['ProjectTaskComponent'].component.taskboard.project.eventStore.filter({
        //         id       : 'eventNameFilter',
        //         filterBy : event => event.assigner.match(new RegExp(value, 'i'))
        //     });
        // },
        store : TaskBoard.project.eventStore,
        filterFunction : (record, value)  => {
            console.log(value)
           return record.text.includes(value);
        }
    }
    // Button to pick which columns are shown
    // { type : 'columnpickerbutton' },
    // Button to pick which swimlanes are shown
    // { type : 'swimlanepickerbutton' }
],
columns: [
    { id: 'Todo', text: 'TO DO', color: 'deep-orange' },
    { id: 'Doing', text: 'DOING', color: 'orange' },
    { id: 'Done', text: 'DONE', color: '#00893d' }
],
columnField: 'status'
};


Post by shimnx »

And is there any way to clear all the query conditions


Post by shimnx »

  this.taskboard.project.eventStore.clearFilters()

That doesn't seem to work


Post by marcio »

Hi shimnx,

You need to get the right variable for your taskboard, I used the columns demo https://www.bryntum.com/examples/taskboard/columns/ and set it up like this

const taskBoard = new TaskBoard({
    ... other configurations
    tbar : [
    	... other tbar configurations
        {
            type        : 'filterfield',
            placeholder : 'Highlight tasks',
            onChange    : ({ value }) => {
                const filter = value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
                taskBoard.project.eventStore.filter({
                    id       : 'eventNameFilter',
                    // Filtering by name property
                    filterBy : event => event.name.match(new RegExp(filter, 'i'))
                });
            }
        }
    ]

Also with that configuration that I shared,

this.taskboard.project.eventStore.clearFilters()

worked correctly

Best regards,
Márcio


Post by shimnx »

marcio wrote: Fri Aug 12, 2022 3:32 pm

Hi shimnx,

You need to get the right variable for your taskboard, I used the columns demo https://www.bryntum.com/examples/taskboard/columns/ and set it up like this

const taskBoard = new TaskBoard({
    ... other configurations
    tbar : [
    	... other tbar configurations
        {
            type        : 'filterfield',
            placeholder : 'Highlight tasks',
            onChange    : ({ value }) => {
                const filter = value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
                taskBoard.project.eventStore.filter({
                    id       : 'eventNameFilter',
                    // Filtering by name property
                    filterBy : event => event.name.match(new RegExp(filter, 'i'))
                });
            }
        }
    ]

Also with that configuration that I shared,

this.taskboard.project.eventStore.clearFilters()

worked correctly

When I click, the page will be stuck for a long time, probably because of the large amount of data (about 100 pieces of data), which will not happen if the amount of data is small

Attachments
Media1.mp4
(1.38 MiB) Downloaded 18 times

Post by shimnx »

shimnx wrote: Fri Aug 12, 2022 2:24 pm
  this.taskboard.project.eventStore.clearFilters()

That doesn't seem to work

/*
 * @Description:
 * @Version: 2.0
 * @Autor: shimnx
 * @Date: 2022-07-26 10:02:43
 * @LastEditors: shimnx
 * @LastEditTime: 2022-08-16 13:01:03
 */
/**
 * App component script
 */
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { BryntumTaskBoardComponent, BryntumProjectModelComponent } from '@bryntum/taskboard-angular';
import { TaskBoard } from '@bryntum/taskboard';

import { taskBoardConfig } from './app.config';
import { projectData } from './app.data';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent implements AfterViewInit {

  taskBoardConfig = taskBoardConfig;
  projectData = projectData;

  // Bryntum TaskBoard Angular wrapper reference
  @ViewChild(BryntumTaskBoardComponent, { static: false }) taskboardComponent: BryntumTaskBoardComponent;
  @ViewChild(BryntumProjectModelComponent, { static: true }) project: BryntumProjectModelComponent;
  taskData = {
    tasksData: [
      { id: 1, name: 'My first task', "progress": 45, status: 'Todo', "prio": "medium", date: "2022-08-01", groupName: 'GroupA', dailyTask: 1, action: 3 },
      { id: 2, name: 'My second task', "progress": 45, status: 'Todo', "prio": "high", date: "2022-02-01", groupName: 'GroupB', dailyTask: 1, action: 3 },
      { id: 3, name: 'My third task', "progress": 45, status: '1', "prio": "high", date: "2022-02-01", groupName: 'GroupC', dailyTask: 1, action: 3 },



],
  }
  private taskboard: TaskBoard;

  ngAfterViewInit(): void {
    this.taskboard = this.taskboardComponent.instance;
    (this.taskboard.project as any).loadInlineData(this.taskData)
  }
  clear(){
    (this.taskboard.project as any).eventStore.clearFilters()
  }
}

This method does clear the query after the query condition, but the value is not

Attachments
Media2.mp4
(797.09 KiB) Downloaded 18 times

Post by shimnx »

I want to dynamically display the Swimlane titles, mainly because I want to modify the number of swimlanes per Swimlane

Attachments
11.png
11.png (37.66 KiB) Viewed 269 times

Post Reply