Custom Tab: Task Manager
In this example, we make a simple task manager, and enable task to become meta-object, task drag & drop, etc.
Register Task Object, Meta-Object and Tab
First, we need to define the task object type and meta-object type. Of course tab type.
declare module 'rendevoz' {
interface CustomTypes {
Object: {
specType: 'task'
taskBeginDate: number
taskFinishDate?: number
taskProgress: number
taskName: string
taskTargetMetaId: number
},
MetaObject: 'task',
Tab: {
type: 'taskManager'
// you can define custom instance, right now we just skip it
instance: never
objectId: never
}
}
}
Then, we register in plugin.
import { PluginApi } from 'rendevoz'
import { t } from 'i18next'
export default (plugin: PluginApi) => {
// first register your tab
plugin.register.registerTab({
type: 'taskManager',
content: () => (
<>
<plugin.Rendevoz.InnerComponents.TabTitle
title="I am task manager!"
/>
<TaskManager plugin={plugin} />
</>
)
})
// second register object and meta-object
plugin.register.registerObject('task', {
normalizeDraggingEleToMetaObject: async draggingTask => {
const taskId = draggingTask.id
const metaStore = plugin.api.getMetaStore()
let alreadyExist = false
const taskMeta = metaStore.getMetaObjectByObjectId(taskId)
let normalizedMeta = {}
if (taskMeta){
alreadyExist = true
normalizedMeta = taskMeta
}
// normalize your task object to task meta-object
else {
normalizedMeta = {
name: draggingTask.taskName,
description: `This task starts at ${draggingTask.taskBeginDate}`,
type: 'task'
}
}
return {
normalizedMetaObject: normalizedMeta,
alreadyHasMeta: alreadyExist,
// if true, will open edit meta modal
shouldOpenEditMetaModal: false,
// no prelinks, you can add links if you want
preLinks: []
}
}
})
plugin.register.registerMetaObject('task', {
i18nKey: 'task',
defaultName: 'Unnamed Task',
onAdd: m => console.log(m),
onUpdate: m => console.log(m),
// if navigate, open taskManager
onNavigate: m => {
plugin.Rendevoz.Actions.Layout.openNewTab({data: {type: 'taskManager'}})
}
})
// register in sidebar menu
plugin.register.registerInSidebarMenu('task-manager', {
icon: 'park-home',
name: () => t('general.taskManager'),
onClick: () => {
plugin.Rendevoz.Actions.Layout.openNewTab({data: {type: 'taskManager'}})
}
})
// at last, register i18n
plugin.register.registerI18N('en-US', {
general: {
task: 'Task',
taskManager: 'Task Manager'
}
})
}
Design React Component
Then, we make the React component TaskManager for tab.
const TaskManager = ({plugin}: {plugin: PluginApi}) => {
const taskStore = plugin.api.getObjectStore('task')
const allTasks = taskStore.useAll()
const globalEventEmitter = plugin.Rendevoz.Events.Emit.GlobalEventEmitter
const globalEventHandler = plugin.Rendevoz.Events.Emit.useEventHandler('global')
const containerRef = useRef<HTMLDivElement>(null)
globalEventHandler.on('globalDragPointerUp', ({event, draggingElement}) => {
// drop on container, and dragging element is meta-object
if(containerRef.current?.contains(event.target)){
if(draggingElement.type === 'metaElement'){
taskStore.addOne({
taskName: 'New Task',
taskBeginDate: Date.now(),
taskTargetMetaId: draggingElement.metaId
})
}
}
})
useEffect(() => {
taskStore.getAll()
globalEventEmitter.addListener('global', globalEventHandler)
return () => {
globalEventEmitter.removeListener('global', globalEventHandler)
}
}, [])
return (
<div ref={containerRef}>
{Array.from(allTasks.value()).map(task =>
<Task key={task.id} task={task} plugin={plugin}/>
)}
</div>
)
}
At last, we make task element.
const Task = ({task, plugin}) => {
const metaStore = plugin.api.getMetaStore()
const objectStore = plugin.api.getObjectStore('task')
const taskMeta = metaStore.useValue(task.taskTargetMetaId)
return (
<div>
<h5>Task Meta Name: {taskMeta.name}</h5>
<p>Task Name: {task.taskName}</p>
<p>Task Begin Date: {task.taskBeginDate}</p>
</div>
)
}
Last updated