2021-07-25 10:45:17 +00:00
|
|
|
import {parseDate} from '../helpers/time/parseDate'
|
2021-09-10 14:21:33 +00:00
|
|
|
import _priorities from '../models/constants/priorities.json'
|
2021-07-25 10:45:17 +00:00
|
|
|
|
2021-09-29 18:30:55 +00:00
|
|
|
const VIKUNJA_PREFIXES: Prefixes = {
|
|
|
|
label: '*',
|
|
|
|
list: '+',
|
|
|
|
priority: '!',
|
|
|
|
assignee: '@',
|
|
|
|
}
|
|
|
|
|
|
|
|
const TODOIST_PREFIXES: Prefixes = {
|
|
|
|
label: '@',
|
|
|
|
list: '#',
|
|
|
|
priority: '!',
|
|
|
|
assignee: '+',
|
|
|
|
}
|
|
|
|
|
|
|
|
export enum PrefixMode {
|
|
|
|
Disabled = 'disabled',
|
|
|
|
Default = 'vikunja',
|
|
|
|
Todoist = 'todoist',
|
|
|
|
}
|
|
|
|
|
|
|
|
export const PREFIXES = {
|
|
|
|
[PrefixMode.Disabled]: undefined,
|
|
|
|
[PrefixMode.Default]: VIKUNJA_PREFIXES,
|
|
|
|
[PrefixMode.Todoist]: TODOIST_PREFIXES,
|
|
|
|
}
|
2021-07-25 10:45:17 +00:00
|
|
|
|
|
|
|
const priorities: Priorites = _priorities
|
|
|
|
|
|
|
|
interface Priorites {
|
|
|
|
UNSET: number,
|
|
|
|
LOW: number,
|
|
|
|
MEDIUM: number,
|
|
|
|
HIGH: number,
|
|
|
|
URGENT: number,
|
|
|
|
DO_NOW: number,
|
|
|
|
}
|
2021-07-05 10:29:04 +00:00
|
|
|
|
2021-07-25 10:45:17 +00:00
|
|
|
interface ParsedTaskText {
|
|
|
|
text: string,
|
|
|
|
date: Date | null,
|
|
|
|
labels: string[],
|
|
|
|
list: string | null,
|
|
|
|
priority: number | null,
|
|
|
|
assignees: string[],
|
|
|
|
}
|
2021-07-05 10:29:04 +00:00
|
|
|
|
2021-09-29 18:30:55 +00:00
|
|
|
interface Prefixes {
|
|
|
|
label: string,
|
|
|
|
list: string,
|
|
|
|
priority: string,
|
|
|
|
assignee: string,
|
|
|
|
}
|
|
|
|
|
2021-07-05 10:29:04 +00:00
|
|
|
/**
|
|
|
|
* Parses task text for dates, assignees, labels, lists, priorities and returns an object with all found intents.
|
|
|
|
*
|
|
|
|
* @param text
|
|
|
|
*/
|
2021-09-29 18:30:55 +00:00
|
|
|
export const parseTaskText = (text: string, prefixesMode: PrefixMode = PrefixMode.Default): ParsedTaskText => {
|
2021-07-25 10:45:17 +00:00
|
|
|
const result: ParsedTaskText = {
|
2021-07-05 10:29:04 +00:00
|
|
|
text: text,
|
|
|
|
date: null,
|
|
|
|
labels: [],
|
|
|
|
list: null,
|
|
|
|
priority: null,
|
|
|
|
assignees: [],
|
|
|
|
}
|
|
|
|
|
2021-09-29 18:30:55 +00:00
|
|
|
const prefixes = PREFIXES[prefixesMode]
|
|
|
|
if (prefixes === undefined) {
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
result.labels = getItemsFromPrefix(text, prefixes.label)
|
2021-07-05 10:29:04 +00:00
|
|
|
|
2021-09-29 18:30:55 +00:00
|
|
|
const lists: string[] = getItemsFromPrefix(text, prefixes.list)
|
2021-07-05 10:29:04 +00:00
|
|
|
result.list = lists.length > 0 ? lists[0] : null
|
|
|
|
|
2021-09-29 18:30:55 +00:00
|
|
|
result.priority = getPriority(text, prefixes.priority)
|
2021-07-05 10:29:04 +00:00
|
|
|
|
2021-09-29 18:30:55 +00:00
|
|
|
result.assignees = getItemsFromPrefix(text, prefixes.assignee)
|
2021-07-05 10:29:04 +00:00
|
|
|
|
|
|
|
const {newText, date} = parseDate(text)
|
|
|
|
result.text = newText
|
|
|
|
result.date = date
|
|
|
|
|
2021-09-29 18:30:55 +00:00
|
|
|
return cleanupResult(result, prefixes)
|
2021-07-05 10:29:04 +00:00
|
|
|
}
|
|
|
|
|
2021-07-25 10:45:17 +00:00
|
|
|
const getItemsFromPrefix = (text: string, prefix: string): string[] => {
|
|
|
|
const items: string[] = []
|
2021-07-05 10:29:04 +00:00
|
|
|
|
|
|
|
const itemParts = text.split(prefix)
|
|
|
|
itemParts.forEach((p, index) => {
|
|
|
|
// First part contains the rest
|
|
|
|
if (index < 1) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
let labelText
|
2021-07-19 11:18:22 +02:00
|
|
|
if (p.charAt(0) === '\'') {
|
|
|
|
labelText = p.split('\'')[1]
|
|
|
|
} else if (p.charAt(0) === '"') {
|
|
|
|
labelText = p.split('"')[1]
|
2021-07-05 10:29:04 +00:00
|
|
|
} else {
|
|
|
|
// Only until the next space
|
|
|
|
labelText = p.split(' ')[0]
|
|
|
|
}
|
|
|
|
items.push(labelText)
|
|
|
|
})
|
|
|
|
|
|
|
|
return Array.from(new Set(items))
|
|
|
|
}
|
|
|
|
|
2021-09-29 18:30:55 +00:00
|
|
|
const getPriority = (text: string, prefix: string): number | null => {
|
|
|
|
const ps = getItemsFromPrefix(text, prefix)
|
2021-07-05 10:29:04 +00:00
|
|
|
if (ps.length === 0) {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const p of ps) {
|
2021-07-25 10:45:17 +00:00
|
|
|
for (const pi of Object.values(priorities)) {
|
|
|
|
if (pi === parseInt(p)) {
|
2021-07-05 10:29:04 +00:00
|
|
|
return parseInt(p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2021-07-25 10:45:17 +00:00
|
|
|
const cleanupItemText = (text: string, items: string[], prefix: string): string => {
|
2021-07-05 10:29:04 +00:00
|
|
|
items.forEach(l => {
|
|
|
|
text = text
|
|
|
|
.replace(`${prefix}'${l}' `, '')
|
|
|
|
.replace(`${prefix}'${l}'`, '')
|
|
|
|
.replace(`${prefix}"${l}" `, '')
|
|
|
|
.replace(`${prefix}"${l}"`, '')
|
|
|
|
.replace(`${prefix}${l} `, '')
|
|
|
|
.replace(`${prefix}${l}`, '')
|
|
|
|
})
|
|
|
|
return text
|
|
|
|
}
|
|
|
|
|
2021-09-29 18:30:55 +00:00
|
|
|
const cleanupResult = (result: ParsedTaskText, prefixes: Prefixes): ParsedTaskText => {
|
|
|
|
result.text = cleanupItemText(result.text, result.labels, prefixes.label)
|
|
|
|
result.text = result.list !== null ? cleanupItemText(result.text, [result.list], prefixes.list) : result.text
|
|
|
|
result.text = result.priority !== null ? cleanupItemText(result.text, [String(result.priority)], prefixes.priority) : result.text
|
|
|
|
result.text = cleanupItemText(result.text, result.assignees, prefixes.assignee)
|
2021-07-05 10:29:04 +00:00
|
|
|
result.text = result.text.trim()
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|