Our flexible Kanban board for managing tasks with drag drop


Post by ahelis »

Hi,

We have use case where we capture the activateTask event, and move the user's focus to an external component in the page. After completing the work in the external component, we want to re-focus the task that was previously selected. Display the selected background color and the outline border, so that users can move to a different task via the keyboard.

bryntum-select-task-external-component.png
bryntum-select-task-external-component.png (431.62 KiB) Viewed 339 times

I have validated using the taskboard built-in editor, that this flow functions correctly, pressing the 'esc' key closes the modal editor and the previous task is properly re-focused. The next arrow key moves focus to the next task.

I have create a simple example from your basic demo, that inserts a button into the header, and upon clicking the button, I do get the selectionChange event firing, but I have been unable to figure out how to refocus the selected task.

const taskBoard = new TaskBoard({
    appendTo : 'container',

// Url for resource avatar images
resourceImagePath : '../_shared/images/users/',

// Experimental, transition moving cards using the editor
useDomTransition : true,

// Columns to display
columns : [
    { id : 'todo', text : 'Todo', color : 'orange' },
    { id : 'doing', text : 'Doing', color : 'blue', tooltip : 'Items that are currently in progress' },
    { id : 'done', text : 'Done' }
],

// Field used to pair a task to a column
columnField : 'status',

// log events
listeners: {

    catchAll({ event, taskRecord, type}) {
        
        if (type.indexOf('mouse') === -1) {
            console.info('event =', type);
        }

        if (type === 'focusin') {
            const button = document.createElement('button');
            button.innerHTML = 'Focus Task 6 - Go To Airport';
            button.addEventListener('click', () => {
                console.info('click');
                window.taskboard.selectTask('6');
            });
            const header = document.querySelector('header');
            header.appendChild(button);
        }

    }
},

// Project using inline data
project : {
    tasks : [
        { id : 1, name : 'Book flight', status : 'done', prio : 'medium' },
        { id : 2, name : 'Book hotel', status : 'done', prio : 'medium' },
        { id : 3, name : 'Pack bags', status : 'doing', prio : 'low' },
        { id : 4, name : 'Get visa', status : 'doing', prio : 'high' },
        { id : 5, name : 'Book train', status : 'done', prio : 'medium' },
        { id : 6, name : 'Go to airport', status : 'todo', prio : 'low' },
        { id : 7, name : 'Renew passport', status : 'todo', prio : 'high' },
        { id : 8, name : 'Swim in pool', status : 'todo', prio : 'medium' },
        { id : 9, name : 'Scuba diving', status : 'todo', prio : 'medium' },
        { id : 10, name : 'Canyoning', status : 'todo', prio : 'low' },
        { id : 11, name : 'Snorkeling', status : 'doing', prio : 'medium' },
        { id : 12, name : 'Diving license', status : 'todo', prio : 'medium' },
        { id : 13, name : 'Book cab', status : 'done', prio : 'low' },
        { id : 14, name : 'Write postcards', status : 'todo', prio : 'medium' },
        { id : 15, name : 'Take pictures', status : 'todo', prio : 'low' },
        { id : 16, name : 'Take selfies', status : 'todo', prio : 'high' },
        { id : 17, name : 'Post on instagram', status : 'todo', prio : 'medium' },
        { id : 18, name : 'Call grandma', status : 'todo', prio : 'medium' },
        { id : 19, name : 'Buy swimming ring', status : 'done', prio : 'high' },
        { id : 20, name : 'Get in shape', status : 'doing', prio : 'medium' },
        { id : 21, name : 'Iron shirts', status : 'done', prio : 'low' }
    ],

    resources : [
        { id : 1, name : 'Angelo', image : 'angelo.jpg' },
        { id : 2, name : 'Celia', image : 'celia.jpg' },
        { id : 3, name : 'Dave', image : 'dave.jpg' },
        { id : 4, name : 'Emilia', image : 'emilia.jpg' },
        { id : 5, name : 'Gloria', image : 'gloria.jpg' },
        { id : 6, name : 'Henrik', image : 'henrik.jpg' },
        { id : 7, name : 'Kate', image : 'kate.jpg' },
        { id : 8, name : 'Lee', image : 'lee.jpg' },
        { id : 9, name : 'Lisa', image : 'lisa.jpg' },
        { id : 10, name : 'Mark', image : 'mark.jpg' },
        { id : 11, name : 'Steve', image : 'steve.jpg' }
    ],

    assignments : [
        { id : 1, event : 7, resource : 1 },
        { id : 2, event : 7, resource : 2 },
        { id : 3, event : 8, resource : 2 },
        { id : 4, event : 4, resource : 3 },
        { id : 5, event : 7, resource : 3 },
        { id : 6, event : 7, resource : 4 },
        { id : 7, event : 7, resource : 5 },
        { id : 8, event : 7, resource : 6 },
        { id : 9, event : 7, resource : 7 },
        { id : 10, event : 7, resource : 8 },
        { id : 11, event : 7, resource : 9 },
        { id : 12, event : 7, resource : 10 },
        { id : 13, event : 7, resource : 11 },
        { id : 14, event : 16, resource : 7 },
        { id : 15, event : 16, resource : 8 },
        { id : 16, event : 16, resource : 9 },
        { id : 17, event : 16, resource : 10 },
        { id : 18, event : 16, resource : 11 },
        { id : 19, event : 19, resource : 10 },
        { id : 20, event : 9, resource : 7 },
        { id : 21, event : 12, resource : 8 },
        { id : 22, event : 14, resource : 9 },
        { id : 23, event : 17, resource : 10 },
        { id : 24, event : 18, resource : 10 },
        { id : 25, event : 11, resource : 9 },
        { id : 26, event : 20, resource : 8 },
        { id : 27, event : 1, resource : 7 },
        { id : 28, event : 2, resource : 6 },
        { id : 29, event : 5, resource : 5 },
        { id : 30, event : 6, resource : 4 },
        { id : 31, event : 10, resource : 3 },
        { id : 32, event : 15, resource : 2 },
        { id : 33, event : 3, resource : 1 },
        { id : 34, event : 13, resource : 2 },
        { id : 36, event : 8, resource : 3 },
        { id : 37, event : 17, resource : 9 },
        { id : 38, event : 17, resource : 8 },
        { id : 39, event : 17, resource : 7 },
        { id : 40, event : 17, resource : 6 }
    ]
}
});

STR:

  1. Open the code editor in your basic demo.
  2. Copy the code into editor.
  3. Click on the left side of the learn button in the demo blue header.
  4. Press the tab key until focus is on the first task.
    • the external button will get appended on the end of the header.
  5. Click once more on the left side of the learn button so the taskboard loses focus
  6. Click 'Focus Task 6 - Go To Airport' button

Notice in the event names printed to the console:

click
selectionchange

If you press enter now, the selectionchange event continues to trigger, but none of the focus or keyboard navigation functionality is restored.

Is there a way to trigger a focus event on the selected task, so that arrow key navigation functions again?


Post by tasnim »

Hi,
You can just get the task element with getTaskElement. and then do element.focus().
Please check this: https://www.bryntum.com/docs/taskboard/api/TaskBoard/view/TaskBoard#function-getTaskElement

Best of luck,
Tasnim


Post by ahelis »

Hi Tasnim,

I updated my example code to use your suggestion, it actually does not work, there are errors in the console. You can modify my example code with the following:

Here are the important changes:

// window.taskboard.selectTask('6');
const elem = window.taskboard.getTaskElement(taskRecord);
if (elem) {
    elem.focus();
}

Here are the errors:

taskboard.module.js?460834:12 Uncaught TypeError: Cannot read properties of undefined (reading 'status')
at TaskBoard.getTaskColumnElement (taskboard.module.js?460834:12:687123)
at TaskBoard.getTaskElement (taskboard.module.js?460834:12:686974)
at HTMLButtonElement.<anonymous> (63cc184b-a22e-4252-b5e3-02b9c63fdd9c:38:51)
at TaskBoard.getTaskColumnElement (taskboard.module.js?460834:12:687123)
at TaskBoard.getTaskElement (taskboard.module.js?460834:12:686974)
at HTMLButtonElement.<anonymous> (63cc184b-a22e-4252-b5e3-02b9c63fdd9c:38:51)
getTaskColumnElement @ taskboard.module.js?460834:12
getTaskElement @ taskboard.module.js?460834:12
(anonymous) @ 63cc184b-a22e-4252-b5e3-02b9c63fdd9c:38
getTaskColumnElement @ taskboard.module.js?460834:12
getTaskElement @ taskboard.module.js?460834:12
(anonymous) @ 63cc184b-a22e-4252-b5e3-02b9c63fdd9c:38
taskboard.module.js?460834:12 Uncaught TypeError: Cannot read properties of undefined (reading 'status')
at TaskBoard.getTaskColumnElement (taskboard.module.js?460834:12:687123)
at TaskBoard.getTaskElement (taskboard.module.js?460834:12:686974)
at HTMLButtonElement.<anonymous> (63cc184b-a22e-4252-b5e3-02b9c63fdd9c:38:51)[/CODE]


Post by marcio »

Hey ahelis,

I tested the getTaskElement in your taskboard example and worked fine in the last Taskboard version (I attached a video to demonstrate working).

I set up the button listener like this

 button.addEventListener('click', () => {
	// window.taskboard.selectTask('6');
	const taskRecord = window.taskboard.project.taskStore.getById('6');
	const elem = window.taskboard.getTaskElement(taskRecord);        
if (elem) { elem.focus(); } });
Attachments
Bryntum TaskBoard - Basic demo.mp4
(425.74 KiB) Downloaded 20 times

Best regards,
Márcio


Post by ahelis »

Thanks Tasnim & Marcio,

Thanks for pointing out my mistake. Working now.


Post Reply