feature/update-eslint-config (#2484)
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/2484 Reviewed-by: konrad <k@knt.li>
This commit is contained in:
commit
6f2dedcb48
22 changed files with 57 additions and 47 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
/* eslint-env node */
|
||||||
|
require("@rushstack/eslint-patch/modern-module-resolution")
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'root': true,
|
'root': true,
|
||||||
'env': {
|
'env': {
|
||||||
|
@ -9,7 +12,7 @@ module.exports = {
|
||||||
'extends': [
|
'extends': [
|
||||||
'eslint:recommended',
|
'eslint:recommended',
|
||||||
'plugin:vue/vue3-essential',
|
'plugin:vue/vue3-essential',
|
||||||
'@vue/typescript',
|
'@vue/eslint-config-typescript/recommended',
|
||||||
],
|
],
|
||||||
'rules': {
|
'rules': {
|
||||||
'vue/html-quotes': [
|
'vue/html-quotes': [
|
||||||
|
@ -28,7 +31,6 @@ module.exports = {
|
||||||
'error',
|
'error',
|
||||||
'never',
|
'never',
|
||||||
],
|
],
|
||||||
'vue/script-setup-uses-vars': 'error',
|
|
||||||
|
|
||||||
// see https://segmentfault.com/q/1010000040813116/a-1020000041134455 (original in chinese)
|
// see https://segmentfault.com/q/1010000040813116/a-1020000041134455 (original in chinese)
|
||||||
'no-unused-vars': 'off',
|
'no-unused-vars': 'off',
|
||||||
|
@ -40,6 +42,7 @@ module.exports = {
|
||||||
'parserOptions': {
|
'parserOptions': {
|
||||||
'parser': '@typescript-eslint/parser',
|
'parser': '@typescript-eslint/parser',
|
||||||
'ecmaVersion': 2022,
|
'ecmaVersion': 2022,
|
||||||
|
'sourceType': 'module',
|
||||||
},
|
},
|
||||||
'ignorePatterns': [
|
'ignorePatterns': [
|
||||||
'*.test.*',
|
'*.test.*',
|
|
@ -67,6 +67,7 @@
|
||||||
"@cypress/vite-dev-server": "3.2.0",
|
"@cypress/vite-dev-server": "3.2.0",
|
||||||
"@cypress/vue": "4.2.0",
|
"@cypress/vue": "4.2.0",
|
||||||
"@faker-js/faker": "7.5.0",
|
"@faker-js/faker": "7.5.0",
|
||||||
|
"@rushstack/eslint-patch": "^1.2.0",
|
||||||
"@types/dompurify": "2.3.4",
|
"@types/dompurify": "2.3.4",
|
||||||
"@types/flexsearch": "0.7.3",
|
"@types/flexsearch": "0.7.3",
|
||||||
"@types/marked": "4.0.7",
|
"@types/marked": "4.0.7",
|
||||||
|
|
|
@ -11,6 +11,7 @@ specifiers:
|
||||||
'@fortawesome/vue-fontawesome': 3.0.1
|
'@fortawesome/vue-fontawesome': 3.0.1
|
||||||
'@github/hotkey': 2.0.1
|
'@github/hotkey': 2.0.1
|
||||||
'@kyvg/vue3-notification': 2.4.1
|
'@kyvg/vue3-notification': 2.4.1
|
||||||
|
'@rushstack/eslint-patch': ^1.2.0
|
||||||
'@sentry/tracing': 7.14.1
|
'@sentry/tracing': 7.14.1
|
||||||
'@sentry/vue': 7.14.1
|
'@sentry/vue': 7.14.1
|
||||||
'@types/dompurify': 2.3.4
|
'@types/dompurify': 2.3.4
|
||||||
|
@ -133,6 +134,7 @@ devDependencies:
|
||||||
'@cypress/vite-dev-server': 3.2.0
|
'@cypress/vite-dev-server': 3.2.0
|
||||||
'@cypress/vue': 4.2.0_cypress@10.9.0+vue@3.2.40
|
'@cypress/vue': 4.2.0_cypress@10.9.0+vue@3.2.40
|
||||||
'@faker-js/faker': 7.5.0
|
'@faker-js/faker': 7.5.0
|
||||||
|
'@rushstack/eslint-patch': 1.2.0
|
||||||
'@types/dompurify': 2.3.4
|
'@types/dompurify': 2.3.4
|
||||||
'@types/flexsearch': 0.7.3
|
'@types/flexsearch': 0.7.3
|
||||||
'@types/marked': 4.0.7
|
'@types/marked': 4.0.7
|
||||||
|
@ -2667,6 +2669,10 @@ packages:
|
||||||
rollup: 2.79.1
|
rollup: 2.79.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@rushstack/eslint-patch/1.2.0:
|
||||||
|
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@samverschueren/stream-to-observable/0.3.1_rxjs@6.6.7:
|
/@samverschueren/stream-to-observable/0.3.1_rxjs@6.6.7:
|
||||||
resolution: {integrity: sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==}
|
resolution: {integrity: sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
|
@ -578,7 +578,7 @@ export default defineComponent({
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let ids = []
|
const ids = []
|
||||||
this[kind].forEach(u => {
|
this[kind].forEach(u => {
|
||||||
ids.push(kind === 'users' ? u.username : u.id)
|
ids.push(kind === 'users' ? u.username : u.id)
|
||||||
})
|
})
|
||||||
|
@ -613,7 +613,7 @@ export default defineComponent({
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let labelIDs = []
|
const labelIDs = []
|
||||||
this.labels.forEach(u => {
|
this.labels.forEach(u => {
|
||||||
labelIDs.push(u.id)
|
labelIDs.push(u.id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -75,8 +75,8 @@ async function load() {
|
||||||
await router.push(redirectTo)
|
await router.push(redirectTo)
|
||||||
}
|
}
|
||||||
ready.value = true
|
ready.value = true
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
error.value = e
|
error.value = String(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ async function addTask() {
|
||||||
return rel
|
return rel
|
||||||
})
|
})
|
||||||
await Promise.all(relations)
|
await Promise.all(relations)
|
||||||
} catch (e: any) {
|
} catch (e: { message?: string }) {
|
||||||
newTaskTitle.value = taskTitleBackup
|
newTaskTitle.value = taskTitleBackup
|
||||||
if (e?.message === 'NO_LIST') {
|
if (e?.message === 'NO_LIST') {
|
||||||
errorMessage.value = t('list.create.addListRequired')
|
errorMessage.value = t('list.create.addListRequired')
|
||||||
|
|
|
@ -278,13 +278,13 @@ export default defineComponent({
|
||||||
prepareGanttDays() {
|
prepareGanttDays() {
|
||||||
console.debug('prepareGanttDays; start date: ', this.startDate, 'end date:', this.endDate)
|
console.debug('prepareGanttDays; start date: ', this.startDate, 'end date:', this.endDate)
|
||||||
// Layout: years => [months => [days]]
|
// Layout: years => [months => [days]]
|
||||||
let years = {}
|
const years = {}
|
||||||
for (
|
for (
|
||||||
let d = this.startDate;
|
let d = this.startDate;
|
||||||
d <= this.endDate;
|
d <= this.endDate;
|
||||||
d.setDate(d.getDate() + 1)
|
d.setDate(d.getDate() + 1)
|
||||||
) {
|
) {
|
||||||
let date = new Date(d)
|
const date = new Date(d)
|
||||||
if (years[date.getFullYear() + ''] === undefined) {
|
if (years[date.getFullYear() + ''] === undefined) {
|
||||||
years[date.getFullYear() + ''] = {}
|
years[date.getFullYear() + ''] = {}
|
||||||
}
|
}
|
||||||
|
@ -353,7 +353,7 @@ export default defineComponent({
|
||||||
|
|
||||||
const didntHaveDates = newTask.startDate === null ? true : false
|
const didntHaveDates = newTask.startDate === null ? true : false
|
||||||
|
|
||||||
let startDate = new Date(this.startDate)
|
const startDate = new Date(this.startDate)
|
||||||
startDate.setDate(
|
startDate.setDate(
|
||||||
startDate.getDate() + newRect.left / this.dayWidth,
|
startDate.getDate() + newRect.left / this.dayWidth,
|
||||||
)
|
)
|
||||||
|
@ -362,7 +362,7 @@ export default defineComponent({
|
||||||
startDate.setUTCSeconds(0)
|
startDate.setUTCSeconds(0)
|
||||||
startDate.setUTCMilliseconds(0)
|
startDate.setUTCMilliseconds(0)
|
||||||
newTask.startDate = startDate
|
newTask.startDate = startDate
|
||||||
let endDate = new Date(startDate)
|
const endDate = new Date(startDate)
|
||||||
endDate.setDate(
|
endDate.setDate(
|
||||||
startDate.getDate() + newRect.width / this.dayWidth,
|
startDate.getDate() + newRect.width / this.dayWidth,
|
||||||
)
|
)
|
||||||
|
@ -430,7 +430,7 @@ export default defineComponent({
|
||||||
if (!this.newTaskFieldActive) {
|
if (!this.newTaskFieldActive) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let task = new TaskModel({
|
const task = new TaskModel({
|
||||||
title: this.newTaskTitle,
|
title: this.newTaskTitle,
|
||||||
listId: this.listId,
|
listId: this.listId,
|
||||||
})
|
})
|
||||||
|
|
|
@ -348,7 +348,7 @@ async function toggleTaskDone(task: ITask) {
|
||||||
|
|
||||||
// Find the task in the list and update it so that it is correctly strike through
|
// Find the task in the list and update it so that it is correctly strike through
|
||||||
Object.entries(relatedTasks.value).some(([kind, tasks]) => {
|
Object.entries(relatedTasks.value).some(([kind, tasks]) => {
|
||||||
return tasks.some((t, key) => {
|
return (tasks as ITask[]).some((t, key) => {
|
||||||
const found = t.id === task.id
|
const found = t.id === task.id
|
||||||
if (found) {
|
if (found) {
|
||||||
relatedTasks.value[kind as IRelationKind]![key] = task
|
relatedTasks.value[kind as IRelationKind]![key] = task
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
export default {
|
import type {Directive} from 'vue'
|
||||||
|
|
||||||
|
const focus = <Directive<HTMLElement,string>>{
|
||||||
// When the bound element is inserted into the DOM...
|
// When the bound element is inserted into the DOM...
|
||||||
mounted: (el, {modifiers}) => {
|
mounted(el, {modifiers}) {
|
||||||
// Focus the element only if the viewport is big enough
|
// Focus the element only if the viewport is big enough
|
||||||
// auto focusing elements on mobile can be annoying since in these cases the
|
// auto focusing elements on mobile can be annoying since in these cases the
|
||||||
// keyboard always pops up and takes half of the available space on the screen.
|
// keyboard always pops up and takes half of the available space on the screen.
|
||||||
|
@ -10,3 +12,5 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default focus
|
|
@ -4,7 +4,7 @@ import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||||
import AttachmentService from '@/services/attachment'
|
import AttachmentService from '@/services/attachment'
|
||||||
import {useTaskStore} from '@/stores/tasks'
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
export function uploadFile(taskId: number, file: File, onSuccess: (url: string) => void) {
|
export function uploadFile(taskId: number, file: File, onSuccess?: (url: string) => void) {
|
||||||
const attachmentService = new AttachmentService()
|
const attachmentService = new AttachmentService()
|
||||||
const files = [file]
|
const files = [file]
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ export async function uploadFiles(
|
||||||
attachmentService: AttachmentService,
|
attachmentService: AttachmentService,
|
||||||
taskId: number,
|
taskId: number,
|
||||||
files: File[] | FileList,
|
files: File[] | FileList,
|
||||||
onSuccess: Function = () => {},
|
onSuccess?: (attachmentUrl: string) => void,
|
||||||
) {
|
) {
|
||||||
const attachmentModel = new AttachmentModel({taskId})
|
const attachmentModel = new AttachmentModel({taskId})
|
||||||
const response = await attachmentService.create(attachmentModel, files)
|
const response = await attachmentService.create(attachmentModel, files)
|
||||||
|
@ -26,7 +26,7 @@ export async function uploadFiles(
|
||||||
taskId,
|
taskId,
|
||||||
attachment,
|
attachment,
|
||||||
})
|
})
|
||||||
onSuccess(generateAttachmentUrl(taskId, attachment.id))
|
onSuccess?.(generateAttachmentUrl(taskId, attachment.id))
|
||||||
})
|
})
|
||||||
|
|
||||||
if (response.errors !== null) {
|
if (response.errors !== null) {
|
||||||
|
|
|
@ -45,7 +45,6 @@ export async function refreshToken(persist: boolean): Promise<AxiosResponse> {
|
||||||
return response
|
return response
|
||||||
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
// @ts-ignore
|
|
||||||
throw new Error('Error renewing token: ', { cause: e })
|
throw new Error('Error renewing token: ', { cause: e })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
export const calculateItemPosition = (positionBefore: number | null, positionAfter: number | null): number => {
|
export const calculateItemPosition = (positionBefore: number | null, positionAfter: number | null): number => {
|
||||||
if (positionBefore === null && positionAfter === null) {
|
if (positionBefore === null) {
|
||||||
|
if (positionAfter === null) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no task before, our task is the first task in which case we let it have half of the position of the task after it
|
// If there is no task after it, we just add 2^16 to the last position to have enough room in the future
|
||||||
if (positionBefore === null && positionAfter !== null) {
|
|
||||||
return positionAfter / 2
|
return positionAfter / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no task after it, we just add 2^16 to the last position to have enough room in the future
|
// If there is no task after it, we just add 2^16 to the last position to have enough room in the future
|
||||||
if (positionBefore !== null && positionAfter === null) {
|
if (positionAfter === null) {
|
||||||
return positionBefore + Math.pow(2, 16)
|
return positionBefore + Math.pow(2, 16)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have both a task before and after it, we acually calculate the position
|
// If we have both a task before and after it, we acually calculate the position
|
||||||
// @ts-ignore - can never be null but TS does not seem to understand that
|
|
||||||
return positionBefore + (positionAfter - positionBefore) / 2
|
return positionBefore + (positionAfter - positionBefore) / 2
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
// https://stackoverflow.com/a/32108184/10924593
|
// https://stackoverflow.com/a/32108184/10924593
|
||||||
export function objectIsEmpty(obj: any): boolean {
|
export function objectIsEmpty(obj: Record<string, unknown>): boolean {
|
||||||
return obj
|
return obj
|
||||||
&& Object.keys(obj).length === 0
|
&& Object.keys(obj).length === 0
|
||||||
&& Object.getPrototypeOf(obj) === Object.prototype
|
&& Object.getPrototypeOf(obj) === Object.prototype
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {parseURL} from 'ufo'
|
||||||
import {createRandomID} from '@/helpers/randomId'
|
import {createRandomID} from '@/helpers/randomId'
|
||||||
import type {IProvider} from '@/types/IProvider'
|
import type {IProvider} from '@/types/IProvider'
|
||||||
|
|
||||||
export const redirectToProvider = (provider: IProvider, redirectUrl: string = '') => {
|
export const redirectToProvider = (provider: IProvider, redirectUrl = '') => {
|
||||||
|
|
||||||
// We're not using the redirect url provided by the server to allow redirects when using the electron app.
|
// We're not using the redirect url provided by the server to allow redirects when using the electron app.
|
||||||
// The implications are not quite clear yet hence the logic to pass in another redirect url still exists.
|
// The implications are not quite clear yet hence the logic to pass in another redirect url still exists.
|
||||||
|
|
|
@ -125,16 +125,16 @@ const addTimeToDate = (text: string, date: Date, previousMatch: string | null):
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDateFromText = (text: string, now: Date = new Date()) => {
|
export const getDateFromText = (text: string, now: Date = new Date()) => {
|
||||||
const fullDateRegex: RegExp = / ([0-9][0-9]?\/[0-9][0-9]?\/[0-9][0-9]([0-9][0-9])?|[0-9][0-9][0-9][0-9]\/[0-9][0-9]?\/[0-9][0-9]?|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?)/ig
|
const fullDateRegex = / ([0-9][0-9]?\/[0-9][0-9]?\/[0-9][0-9]([0-9][0-9])?|[0-9][0-9][0-9][0-9]\/[0-9][0-9]?\/[0-9][0-9]?|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?)/ig
|
||||||
|
|
||||||
// 1. Try parsing the text as a "usual" date, like 2021-06-24 or 06/24/2021
|
// 1. Try parsing the text as a "usual" date, like 2021-06-24 or 06/24/2021
|
||||||
let results: string[] | null = fullDateRegex.exec(text)
|
let results: string[] | null = fullDateRegex.exec(text)
|
||||||
let result: string | null = results === null ? null : results[0]
|
let result: string | null = results === null ? null : results[0]
|
||||||
let foundText: string | null = result
|
let foundText: string | null = result
|
||||||
let containsYear: boolean = true
|
let containsYear = true
|
||||||
if (result === null) {
|
if (result === null) {
|
||||||
// 2. Try parsing the date as something like "jan 21" or "21 jan"
|
// 2. Try parsing the date as something like "jan 21" or "21 jan"
|
||||||
const monthRegex: RegExp = new RegExp(` (${monthsRegexGroup} [0-9][0-9]?|[0-9][0-9]? ${monthsRegexGroup})`, 'ig')
|
const monthRegex = new RegExp(` (${monthsRegexGroup} [0-9][0-9]?|[0-9][0-9]? ${monthsRegexGroup})`, 'ig')
|
||||||
results = monthRegex.exec(text)
|
results = monthRegex.exec(text)
|
||||||
result = results === null ? null : `${results[0]} ${now.getFullYear()}`.trim()
|
result = results === null ? null : `${results[0]} ${now.getFullYear()}`.trim()
|
||||||
foundText = results === null ? '' : results[0].trim()
|
foundText = results === null ? '' : results[0].trim()
|
||||||
|
@ -142,7 +142,7 @@ export const getDateFromText = (text: string, now: Date = new Date()) => {
|
||||||
|
|
||||||
if (result === null) {
|
if (result === null) {
|
||||||
// 3. Try parsing the date as "27/01" or "01/27"
|
// 3. Try parsing the date as "27/01" or "01/27"
|
||||||
const monthNumericRegex: RegExp = / ([0-9][0-9]?\/[0-9][0-9]?)/ig
|
const monthNumericRegex = / ([0-9][0-9]?\/[0-9][0-9]?)/ig
|
||||||
results = monthNumericRegex.exec(text)
|
results = monthNumericRegex.exec(text)
|
||||||
|
|
||||||
// Put the year before or after the date, depending on what works
|
// Put the year before or after the date, depending on what works
|
||||||
|
@ -229,7 +229,7 @@ export const getDateFromTextIn = (text: string, now: Date = new Date()) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const getDateFromWeekday = (text: string): dateFoundResult => {
|
const getDateFromWeekday = (text: string): dateFoundResult => {
|
||||||
const matcher: RegExp = / (next )?(monday|mon|tuesday|tue|wednesday|wed|thursday|thu|friday|fri|saturday|sat|sunday|sun)($| )/g
|
const matcher = / (next )?(monday|mon|tuesday|tue|wednesday|wed|thursday|thu|friday|fri|saturday|sat|sunday|sun)($| )/g
|
||||||
const results: string[] | null = matcher.exec(text.toLowerCase()) // The i modifier does not seem to work.
|
const results: string[] | null = matcher.exec(text.toLowerCase()) // The i modifier does not seem to work.
|
||||||
if (results === null) {
|
if (results === null) {
|
||||||
return {
|
return {
|
||||||
|
@ -240,7 +240,7 @@ const getDateFromWeekday = (text: string): dateFoundResult => {
|
||||||
|
|
||||||
const date: Date = new Date()
|
const date: Date = new Date()
|
||||||
const currentDay: number = date.getDay()
|
const currentDay: number = date.getDay()
|
||||||
let day: number = 0
|
let day = 0
|
||||||
|
|
||||||
switch (results[2]) {
|
switch (results[2]) {
|
||||||
case 'mon':
|
case 'mon':
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
export function parseDateOrString(rawValue: string | undefined, fallback: any): string | Date {
|
export function parseDateOrString(rawValue: string | undefined, fallback: unknown) {
|
||||||
if (typeof rawValue === 'undefined') {
|
if (typeof rawValue === 'undefined') {
|
||||||
return fallback
|
return fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
const d = new Date(rawValue)
|
const d = new Date(rawValue)
|
||||||
|
|
||||||
// @ts-ignore if rawValue is an invalid date, isNan will return false.
|
return !isNaN(+d)
|
||||||
return !isNaN(d)
|
|
||||||
? d
|
? d
|
||||||
: rawValue
|
: rawValue
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ export function isNil(value: unknown) {
|
||||||
return value == null
|
return value == null
|
||||||
}
|
}
|
||||||
|
|
||||||
export function omitBy(obj: {}, check: (value: unknown) => boolean) {
|
export function omitBy(obj: Record<string, unknown>, check: (value: unknown) => boolean) {
|
||||||
if (isNil(obj)) {
|
if (isNil(obj)) {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,15 +31,14 @@ export const createNewIndexer = (name: string, fieldsToIndex: string[]) => {
|
||||||
return index.update(item.id, item)
|
return index.update(item.id, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(query: string | null): number[] | null {
|
function search(query: string | null) {
|
||||||
if (query === '' || query === null) {
|
if (query === '' || query === null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
return index.search(query)
|
return index.search(query)
|
||||||
?.flatMap(r => r.result)
|
?.flatMap(r => r.result)
|
||||||
.filter((value, index, self) => self.indexOf(value) === index)
|
.filter((value, index, self) => self.indexOf(value) === index) as number[]
|
||||||
|| null
|
|| null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ export interface IList extends IAbstract {
|
||||||
isArchived: boolean
|
isArchived: boolean
|
||||||
hexColor: string
|
hexColor: string
|
||||||
identifier: string
|
identifier: string
|
||||||
backgroundInformation: any // FIXME: improve type
|
backgroundInformation: unknown | null // FIXME: improve type
|
||||||
isFavorite: boolean
|
isFavorite: boolean
|
||||||
subscription: ISubscription
|
subscription: ISubscription
|
||||||
position: number
|
position: number
|
||||||
|
|
|
@ -19,7 +19,7 @@ export default class ListModel extends AbstractModel<IList> implements IList {
|
||||||
isArchived = false
|
isArchived = false
|
||||||
hexColor = ''
|
hexColor = ''
|
||||||
identifier = ''
|
identifier = ''
|
||||||
backgroundInformation: any = null
|
backgroundInformation: unknown | null = null
|
||||||
isFavorite = false
|
isFavorite = false
|
||||||
subscription: ISubscription = null
|
subscription: ISubscription = null
|
||||||
position = 0
|
position = 0
|
||||||
|
|
|
@ -149,7 +149,7 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
|
||||||
/**
|
/**
|
||||||
* Returns a fully-ready-ready-to-make-a-request-to route with replaced parameters.
|
* Returns a fully-ready-ready-to-make-a-request-to route with replaced parameters.
|
||||||
*/
|
*/
|
||||||
getReplacedRoute(path : string, pathparams : {}) : string {
|
getReplacedRoute(path : string, pathparams : Record<string, unknown>) : string {
|
||||||
const replacements = this.getRouteReplacements(path, pathparams)
|
const replacements = this.getRouteReplacements(path, pathparams)
|
||||||
return Object.entries(replacements).reduce(
|
return Object.entries(replacements).reduce(
|
||||||
(result, [parameter, value]) => result.replace(parameter, value as string),
|
(result, [parameter, value]) => result.replace(parameter, value as string),
|
||||||
|
|
|
@ -562,8 +562,8 @@ const hasAttachments = computed(() => attachmentStore.attachments.length > 0)
|
||||||
// HACK:
|
// HACK:
|
||||||
const shouldShowClosePopup = computed(() => (route.name as string).includes('kanban'))
|
const shouldShowClosePopup = computed(() => (route.name as string).includes('kanban'))
|
||||||
|
|
||||||
function attachmentUpload(...args: any[]) {
|
function attachmentUpload(file: File, onSuccess?: (url: string) => void) {
|
||||||
return uploadFile(taskId.value, ...args)
|
return uploadFile(taskId.value, file, onSuccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
const heading = ref<HTMLElement | null>(null)
|
const heading = ref<HTMLElement | null>(null)
|
||||||
|
|
Loading…
Reference in a new issue