mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 11:31:57 +03:00
Tasks MVP
1. Creation of projects 2. Creation of tasks 3. Task table display 4. Task Editing Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
6b7a4b2474
commit
af096a0f66
@ -9864,7 +9864,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/dev-storage.tgz_typescript@4.4.3:
|
file:projects/dev-storage.tgz_typescript@4.4.3:
|
||||||
resolution: {integrity: sha512-SfTtSgH07SlBF5nTXqS/E5023gdeN5eFmaL4fdrvId5ixenWnSJ16Xcvj02R8nuQ7PAwkNkZMwO+707Ins3GlQ==, tarball: file:projects/dev-storage.tgz}
|
resolution: {integrity: sha512-MI95DMgzOe43SqSrvtR+wgcws3voLsrjvQAS87DGkq15UUxobrixatDGfk5rxFUJsGNpw68s0SQNB+XsYmB4Dw==, tarball: file:projects/dev-storage.tgz}
|
||||||
id: file:projects/dev-storage.tgz
|
id: file:projects/dev-storage.tgz
|
||||||
name: '@rush-temp/dev-storage'
|
name: '@rush-temp/dev-storage'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -10267,7 +10267,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/model-task.tgz_typescript@4.4.3:
|
file:projects/model-task.tgz_typescript@4.4.3:
|
||||||
resolution: {integrity: sha512-ECVFsBQDPeXBhwde4kBvnJlE8sXbSuSPOVa76QAdw4poccNaXabQbDUMNKNIquq4kTPGp7GhUUbaDk316zWmcw==, tarball: file:projects/model-task.tgz}
|
resolution: {integrity: sha512-BFTI2YyRTQa+3voYij2r8icUkp5QdKc69N3oPvir4XsfrRrlM90EiDYi0XKk2YCjRtnn+2DEa+pjT8q4CQke5g==, tarball: file:projects/model-task.tgz}
|
||||||
id: file:projects/model-task.tgz
|
id: file:projects/model-task.tgz
|
||||||
name: '@rush-temp/model-task'
|
name: '@rush-temp/model-task'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -10494,7 +10494,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/prod.tgz_sass@1.42.1+typescript@4.4.3:
|
file:projects/prod.tgz_sass@1.42.1+typescript@4.4.3:
|
||||||
resolution: {integrity: sha512-jYkFXSc3TaFdljpFFcRvEWTmtHKLA7nQUn+9kSDD9/J91/LmQEv3yEyJH89kb1ETNiTK6vnuLlp9br+RZipWVg==, tarball: file:projects/prod.tgz}
|
resolution: {integrity: sha512-YXR+9ndU1ibNRBgBG2s//HcelDIJmxvXqSPkrZ1A9z8qhjtnYGi7mwqIKpxS+mYVr5nS6JRCNLXcblAp7aDlXA==, tarball: file:projects/prod.tgz}
|
||||||
id: file:projects/prod.tgz
|
id: file:projects/prod.tgz
|
||||||
name: '@rush-temp/prod'
|
name: '@rush-temp/prod'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -10868,13 +10868,24 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/task-resources.tgz_e1367da94684b005adf08f025c517b1a:
|
file:projects/task-resources.tgz_e1367da94684b005adf08f025c517b1a:
|
||||||
resolution: {integrity: sha512-x8gVBObHY9bs86rKxU8Vq0uKMNgjvz5LFQqux6+l8aECuCJjjj70UcQqV+5hBGaY9m5GnlaxAJZed4VntxS4XA==, tarball: file:projects/task-resources.tgz}
|
resolution: {integrity: sha512-dxx9fOd472gS8ILbnRMpBhnd4KOT0xkpQRbSkGHn9sigBeRZ48ZdEXtfagTQSaVlgwhOoCbVm1QrFy67Ctpbcw==, tarball: file:projects/task-resources.tgz}
|
||||||
id: file:projects/task-resources.tgz
|
id: file:projects/task-resources.tgz
|
||||||
name: '@rush-temp/task-resources'
|
name: '@rush-temp/task-resources'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@typescript-eslint/eslint-plugin': 5.4.0_87dbf04088b125598d0271706532eaf3
|
||||||
|
'@typescript-eslint/parser': 5.4.0_eslint@7.32.0+typescript@4.4.3
|
||||||
|
eslint: 7.32.0
|
||||||
|
eslint-config-standard-with-typescript: 21.0.1_05a8ea1454e6ca4c9f98b94b8f3abf9c
|
||||||
|
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||||
|
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||||
|
eslint-plugin-promise: 5.1.1_eslint@7.32.0
|
||||||
|
eslint-plugin-svelte3: 3.2.1_eslint@7.32.0+svelte@3.43.1
|
||||||
|
prettier: 2.4.1
|
||||||
|
prettier-plugin-svelte: 2.5.0_prettier@2.4.1+svelte@3.43.1
|
||||||
sass: 1.42.1
|
sass: 1.42.1
|
||||||
svelte: 3.43.1
|
svelte: 3.43.1
|
||||||
|
svelte-check: 2.2.10_3708ed3db7329f2cbf76db19160094b1
|
||||||
svelte-loader: 3.1.2_svelte@3.43.1
|
svelte-loader: 3.1.2_svelte@3.43.1
|
||||||
svelte-preprocess: 4.9.8_b1ccfb371c7d68f75291f5a547be0b14
|
svelte-preprocess: 4.9.8_b1ccfb371c7d68f75291f5a547be0b14
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@ -10887,6 +10898,7 @@ packages:
|
|||||||
- pug
|
- pug
|
||||||
- stylus
|
- stylus
|
||||||
- sugarss
|
- sugarss
|
||||||
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@ -11009,7 +11021,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/tool.tgz_typescript@4.4.3:
|
file:projects/tool.tgz_typescript@4.4.3:
|
||||||
resolution: {integrity: sha512-4mquFHT6NpGnSQiTikfIdCakmJbxLsSCVn7f8X4j8DWwx+GKYLxi8O+NGHuB82dZ76XJoonako1CsiVGvrNpPA==, tarball: file:projects/tool.tgz}
|
resolution: {integrity: sha512-SwaepBCYg7nNx+Vb5vkowQ2QYwf6KLw8iKJGWmm8A261c9geGd8f2Sl2DYyxi9lhG946DRaMxxnQkSfzvNZkRg==, tarball: file:projects/tool.tgz}
|
||||||
id: file:projects/tool.tgz
|
id: file:projects/tool.tgz
|
||||||
name: '@rush-temp/tool'
|
name: '@rush-temp/tool'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -11189,7 +11201,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/workspace.tgz_typescript@4.4.3:
|
file:projects/workspace.tgz_typescript@4.4.3:
|
||||||
resolution: {integrity: sha512-Mey3vBH1eqNXrxrhsXI3d66AoIW4hqE34OWI7KN7hqY0nqVzUcex0GHBc78dw7vS+UDkW1Cc2J6rCiLvYQkzfw==, tarball: file:projects/workspace.tgz}
|
resolution: {integrity: sha512-RqzmT9xyUKDthUVU6kMT/yarSmB0yPv2q4VI6cJ+O/Iw7HiuKhTUV7ObyA6AJPIYiHZIGOqM4EMrMvX2G8rWNA==, tarball: file:projects/workspace.tgz}
|
||||||
id: file:projects/workspace.tgz
|
id: file:projects/workspace.tgz
|
||||||
name: '@rush-temp/workspace'
|
name: '@rush-temp/workspace'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
|
@ -20,7 +20,7 @@ import type { AnyComponent } from '@anticrm/ui'
|
|||||||
import type { Action } from '@anticrm/view'
|
import type { Action } from '@anticrm/view'
|
||||||
import { recruitId } from '@anticrm/recruit'
|
import { recruitId } from '@anticrm/recruit'
|
||||||
import recruit from '@anticrm/recruit-resources/src/plugin'
|
import recruit from '@anticrm/recruit-resources/src/plugin'
|
||||||
import { TxViewlet } from '../../chunter/node_modules/@anticrm/activity/lib'
|
import { TxViewlet } from '@anticrm/activity'
|
||||||
|
|
||||||
export default mergeIds(recruitId, recruit, {
|
export default mergeIds(recruitId, recruit, {
|
||||||
action: {
|
action: {
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
"@anticrm/model-workbench": "~0.6.1",
|
"@anticrm/model-workbench": "~0.6.1",
|
||||||
"@anticrm/model-contact": "~0.6.1",
|
"@anticrm/model-contact": "~0.6.1",
|
||||||
"@anticrm/task": "~0.6.0",
|
"@anticrm/task": "~0.6.0",
|
||||||
"@anticrm/task-resources": "~0.6.0"
|
"@anticrm/task-resources": "~0.6.0",
|
||||||
|
"@anticrm/model-chunter": "~0.6.0",
|
||||||
|
"@anticrm/workbench": "~0.6.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,34 +13,42 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import type { IntlString } from '@anticrm/platform'
|
|
||||||
import { Builder, Model, TypeString, UX, Prop } from '@anticrm/model'
|
|
||||||
import type { Ref, Doc, FindOptions } from '@anticrm/core'
|
|
||||||
import core, { TSpace, TDoc } from '@anticrm/model-core'
|
|
||||||
import type { Project, Task } from '@anticrm/task'
|
|
||||||
import type { Employee } from '@anticrm/contact'
|
import type { Employee } from '@anticrm/contact'
|
||||||
import type { AnyComponent } from '@anticrm/ui'
|
import contact from '@anticrm/contact'
|
||||||
|
import type { Doc, Domain, FindOptions, Ref } from '@anticrm/core'
|
||||||
import workbench from '@anticrm/model-workbench'
|
import { Builder, Model, Prop, TypeString, UX } from '@anticrm/model'
|
||||||
|
import chunter from '@anticrm/model-chunter'
|
||||||
|
import core, { TDoc, TSpace } from '@anticrm/model-core'
|
||||||
import view from '@anticrm/model-view'
|
import view from '@anticrm/model-view'
|
||||||
import contact from '@anticrm/model-contact'
|
import workbench from '@anticrm/model-workbench'
|
||||||
|
import type { IntlString } from '@anticrm/platform'
|
||||||
|
import type { Project, Task } from '@anticrm/task'
|
||||||
import task from './plugin'
|
import task from './plugin'
|
||||||
|
|
||||||
@Model(task.class.Project, core.class.Space)
|
@Model(task.class.Project, core.class.Space)
|
||||||
@UX('Project' as IntlString, task.icon.Task)
|
@UX('Project' as IntlString, task.icon.Task)
|
||||||
export class TProject extends TSpace implements Project {}
|
export class TProject extends TSpace implements Project {}
|
||||||
|
|
||||||
@Model(task.class.Task, core.class.Doc)
|
@Model(task.class.Task, core.class.Doc, 'task' as Domain)
|
||||||
|
@UX('Task' as IntlString, task.icon.Task, 'TASK' as IntlString)
|
||||||
export class TTask extends TDoc implements Task {
|
export class TTask extends TDoc implements Task {
|
||||||
@Prop(TypeString(), 'Title' as IntlString)
|
@Prop(TypeString(), 'No.' as IntlString)
|
||||||
title!: string
|
number!: number
|
||||||
|
|
||||||
|
@Prop(TypeString(), 'Name' as IntlString)
|
||||||
|
name!: string
|
||||||
|
|
||||||
@Prop(TypeString(), 'Description' as IntlString)
|
@Prop(TypeString(), 'Description' as IntlString)
|
||||||
description!: string
|
description!: string
|
||||||
|
|
||||||
@Prop(TypeString(), 'Assignee' as IntlString)
|
@Prop(TypeString(), 'Assignee' as IntlString)
|
||||||
assignee!: Ref<Employee>
|
assignee!: Ref<Employee>
|
||||||
|
|
||||||
|
@Prop(TypeString(), 'Comments' as IntlString)
|
||||||
|
comments!: number
|
||||||
|
|
||||||
|
@Prop(TypeString(), 'Labels' as IntlString)
|
||||||
|
labels!: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createModel (builder: Builder): void {
|
export function createModel (builder: Builder): void {
|
||||||
@ -52,19 +60,6 @@ export function createModel (builder: Builder): void {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.createDoc(view.class.Viewlet, core.space.Model, {
|
|
||||||
attachTo: task.class.Task,
|
|
||||||
descriptor: view.viewlet.Table,
|
|
||||||
open: 'ZX' as AnyComponent,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
||||||
options: {
|
|
||||||
lookup: {
|
|
||||||
assignee: contact.class.Employee
|
|
||||||
}
|
|
||||||
} as FindOptions<Doc>,
|
|
||||||
config: ['title', '$lookup.assignee']
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.createDoc(workbench.class.Application, core.space.Model, {
|
builder.createDoc(workbench.class.Application, core.space.Model, {
|
||||||
label: task.string.ApplicationLabelTask,
|
label: task.string.ApplicationLabelTask,
|
||||||
icon: task.icon.Task,
|
icon: task.icon.Task,
|
||||||
@ -79,11 +74,45 @@ export function createModel (builder: Builder): void {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}, task.app.Tasks)
|
||||||
|
|
||||||
|
builder.createDoc(view.class.Viewlet, core.space.Model, {
|
||||||
|
attachTo: task.class.Task,
|
||||||
|
descriptor: view.viewlet.Table,
|
||||||
|
open: task.component.EditTask,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||||
|
options: {
|
||||||
|
lookup: {
|
||||||
|
assignee: contact.class.Employee
|
||||||
|
}
|
||||||
|
} as FindOptions<Doc>,
|
||||||
|
config: [
|
||||||
|
'',
|
||||||
|
'name',
|
||||||
|
'$lookup.assignee',
|
||||||
|
{ presenter: chunter.component.AttachmentsPresenter, label: 'Files' },
|
||||||
|
{ presenter: chunter.component.CommentsPresenter, label: 'Comments' },
|
||||||
|
'modifiedOn'
|
||||||
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
builder.mixin(task.class.Task, core.class.Class, view.mixin.AttributePresenter, {
|
||||||
|
presenter: task.component.TaskPresenter
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.mixin(task.class.Task, core.class.Class, view.mixin.ObjectEditor, {
|
||||||
|
editor: task.component.EditTask
|
||||||
|
})
|
||||||
|
|
||||||
builder.createDoc(task.class.Project, core.space.Model, {
|
builder.createDoc(task.class.Project, core.space.Model, {
|
||||||
name: 'demo',
|
name: 'public',
|
||||||
description: 'Demo Project',
|
description: 'Public tasks',
|
||||||
private: false,
|
private: false,
|
||||||
members: []
|
members: []
|
||||||
|
}, task.space.TasksPublic)
|
||||||
|
|
||||||
|
builder.createDoc(view.class.Sequence, view.space.Sequence, {
|
||||||
|
attachedTo: task.class.Task,
|
||||||
|
sequence: 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -14,26 +14,31 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { taskId } from '@anticrm/task'
|
import type { Ref, Space } from '@anticrm/core'
|
||||||
import task from '@anticrm/task-resources/src/plugin'
|
|
||||||
import type { IntlString } from '@anticrm/platform'
|
import type { IntlString } from '@anticrm/platform'
|
||||||
import type { Ref, Class } from '@anticrm/core'
|
|
||||||
import type { Project } from '@anticrm/task'
|
|
||||||
import type { AnyComponent } from '@anticrm/ui'
|
|
||||||
import { mergeIds } from '@anticrm/platform'
|
import { mergeIds } from '@anticrm/platform'
|
||||||
|
import task, { taskId } from '@anticrm/task'
|
||||||
|
import type { AnyComponent } from '@anticrm/ui'
|
||||||
|
import { Application } from '@anticrm/workbench'
|
||||||
|
|
||||||
export default mergeIds(taskId, task, {
|
export default mergeIds(taskId, task, {
|
||||||
|
app: {
|
||||||
|
Tasks: '' as Ref<Application>
|
||||||
|
},
|
||||||
component: {
|
component: {
|
||||||
ProjectView: '' as AnyComponent,
|
ProjectView: '' as AnyComponent,
|
||||||
CreateProject: '' as AnyComponent,
|
CreateProject: '' as AnyComponent,
|
||||||
CreateTask: '' as AnyComponent
|
CreateTask: '' as AnyComponent,
|
||||||
},
|
EditTask: '' as AnyComponent,
|
||||||
class: {
|
TaskPresenter: '' as AnyComponent
|
||||||
Project: '' as Ref<Class<Project>>
|
|
||||||
},
|
},
|
||||||
string: {
|
string: {
|
||||||
|
Task: '' as IntlString,
|
||||||
ApplicationLabelTask: '' as IntlString,
|
ApplicationLabelTask: '' as IntlString,
|
||||||
Projects: '' as IntlString,
|
Projects: '' as IntlString,
|
||||||
CreateProject: '' as IntlString
|
CreateProject: '' as IntlString
|
||||||
|
},
|
||||||
|
space: {
|
||||||
|
TasksPublic: '' as Ref<Space>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -2,6 +2,19 @@
|
|||||||
"string": {
|
"string": {
|
||||||
"ApplicationLabelTask": "Tasks",
|
"ApplicationLabelTask": "Tasks",
|
||||||
"Projects": "Projects",
|
"Projects": "Projects",
|
||||||
"CreateProject": "New Project"
|
"CreateProject": "New Project",
|
||||||
|
"ProjectName": "Project",
|
||||||
|
"MakePrivate": "Make Private",
|
||||||
|
"MakePrivateDescription": "Only members can see it",
|
||||||
|
"CreateTask": "Create task",
|
||||||
|
"TaskProject": "selected project",
|
||||||
|
"SelectProject": "Select project",
|
||||||
|
"Task": "Task",
|
||||||
|
"TaskName": "Task name *",
|
||||||
|
"TaskAssignee": "Assignee",
|
||||||
|
"TaskDescription": "Description",
|
||||||
|
"UploadDropFilesHere": "Upload or drop files here",
|
||||||
|
"NoAttachmentsForTask": "There are no attachments for this task.",
|
||||||
|
"AssigneeRequired": "Assignee is required"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,10 +13,12 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { loadMetadata } from '@anticrm/platform'
|
import { addStringsLoader, loadMetadata } from '@anticrm/platform'
|
||||||
import task from '@anticrm/task'
|
import task, {taskId} from '@anticrm/task'
|
||||||
|
|
||||||
const icons = require('../assets/icons.svg')
|
const icons = require('../assets/icons.svg')
|
||||||
loadMetadata(task.icon, {
|
loadMetadata(task.icon, {
|
||||||
Task: `${icons}#task`,
|
Task: `${icons}#task`,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
addStringsLoader(taskId, async (lang: string) => await import(`../lang/${lang}.json`))
|
||||||
|
7
plugins/task-resources/.eslintrc.js
Normal file
7
plugins/task-resources/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['./node_modules/@anticrm/platform-rig/profiles/ui/config/eslint.config.json'],
|
||||||
|
parserOptions: { tsconfigRootDir: __dirname },
|
||||||
|
settings: {
|
||||||
|
'svelte3/ignore-styles': () => true
|
||||||
|
}
|
||||||
|
};
|
@ -14,7 +14,19 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"svelte-loader":"^3.1.2",
|
"svelte-loader":"^3.1.2",
|
||||||
"sass":"^1.37.5",
|
"sass":"^1.37.5",
|
||||||
"svelte-preprocess":"^4.7.4"
|
"svelte-preprocess":"^4.7.4",
|
||||||
|
"@anticrm/platform-rig":"~0.6.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||||
|
"@typescript-eslint/parser": "^5.4.0",
|
||||||
|
"eslint-config-standard-with-typescript": "^21.0.1",
|
||||||
|
"eslint-plugin-import": "^2.25.3",
|
||||||
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
"eslint-plugin-promise": "^5.1.1",
|
||||||
|
"eslint-plugin-svelte3": "~3.2.1",
|
||||||
|
"prettier-plugin-svelte": "^2.2.0",
|
||||||
|
"eslint": "^7.32.0",
|
||||||
|
"prettier": "^2.4.1",
|
||||||
|
"svelte-check": "^2.2.10"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anticrm/platform": "~0.6.5",
|
"@anticrm/platform": "~0.6.5",
|
||||||
@ -24,6 +36,11 @@
|
|||||||
"@anticrm/presentation": "~0.6.2",
|
"@anticrm/presentation": "~0.6.2",
|
||||||
"@anticrm/text-editor": "~0.6.0",
|
"@anticrm/text-editor": "~0.6.0",
|
||||||
"@anticrm/contact": "~0.6.2",
|
"@anticrm/contact": "~0.6.2",
|
||||||
"@anticrm/core": "~0.6.11"
|
"@anticrm/core": "~0.6.11",
|
||||||
|
"@anticrm/chunter": "~0.6.1",
|
||||||
|
"@anticrm/panel": "~0.6.0",
|
||||||
|
"@anticrm/view": "~0.6.0",
|
||||||
|
"@anticrm/view-resources": "~0.6.0",
|
||||||
|
"@anticrm/login": "~0.6.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
138
plugins/task-resources/src/components/Attachments.svelte
Normal file
138
plugins/task-resources/src/components/Attachments.svelte
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2020 Anticrm Platform Contributors.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import type { Attachment } from '@anticrm/chunter'
|
||||||
|
import chunter from '@anticrm/chunter'
|
||||||
|
import type { Class, Doc, Ref, Space } from '@anticrm/core'
|
||||||
|
import { setPlatformStatus, unknownError } from '@anticrm/platform'
|
||||||
|
import { createQuery, getClient } from '@anticrm/presentation'
|
||||||
|
import { CircleButton, IconAdd, Label, Spinner } from '@anticrm/ui'
|
||||||
|
import { Table } from '@anticrm/view-resources'
|
||||||
|
import { uploadFile } from '../utils'
|
||||||
|
import UploadDuo from './icons/UploadDuo.svelte'
|
||||||
|
import task from '../plugin'
|
||||||
|
|
||||||
|
export let objectId: Ref<Doc>
|
||||||
|
export let space: Ref<Space>
|
||||||
|
export let _class: Ref<Class<Doc>>
|
||||||
|
|
||||||
|
let attachments: Attachment[] = []
|
||||||
|
|
||||||
|
const query = createQuery()
|
||||||
|
$: query.query(chunter.class.Attachment, { attachedTo: objectId }, result => { attachments = result })
|
||||||
|
|
||||||
|
let inputFile: HTMLInputElement
|
||||||
|
let loading = 0
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
async function createAttachment (file: File) {
|
||||||
|
loading++
|
||||||
|
try {
|
||||||
|
const uuid = await uploadFile(space, file, objectId)
|
||||||
|
console.log('uploaded file uuid', uuid)
|
||||||
|
client.addCollection(chunter.class.Attachment, space, objectId, _class, 'attachments', {
|
||||||
|
name: file.name,
|
||||||
|
file: uuid,
|
||||||
|
type: file.type,
|
||||||
|
size: file.size,
|
||||||
|
lastModified: file.lastModified
|
||||||
|
})
|
||||||
|
} catch (err: any) {
|
||||||
|
setPlatformStatus(unknownError(err))
|
||||||
|
} finally {
|
||||||
|
loading--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fileSelected () {
|
||||||
|
console.log(inputFile.files)
|
||||||
|
const list = inputFile.files
|
||||||
|
if (list === null || list.length === 0) return
|
||||||
|
for (let index = 0; index < list.length; index++) {
|
||||||
|
const file = list.item(index)
|
||||||
|
if (file !== null) createAttachment(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fileDrop (e: DragEvent) {
|
||||||
|
const list = e.dataTransfer?.files
|
||||||
|
if (list === undefined || list.length === 0) return
|
||||||
|
for (let index = 0; index < list.length; index++) {
|
||||||
|
const file = list.item(index)
|
||||||
|
if (file !== null) createAttachment(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dragover = false
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="attachments-container">
|
||||||
|
<div class="flex-row-center">
|
||||||
|
<span class="title">Attachments</span>
|
||||||
|
{#if loading}
|
||||||
|
<Spinner/>
|
||||||
|
{:else}
|
||||||
|
<CircleButton icon={IconAdd} size={'small'} on:click={ () => { inputFile.click() } } />
|
||||||
|
{/if}
|
||||||
|
<input bind:this={inputFile} multiple type="file" name="file" id="file" style="display: none" on:change={fileSelected}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if attachments.length === 0 && !loading}
|
||||||
|
<div class="flex-col-center mt-5 zone-container" class:solid={dragover}
|
||||||
|
on:dragover|preventDefault={ () => { dragover = true } }
|
||||||
|
on:dragleave={ () => { dragover = false } }
|
||||||
|
on:drop|preventDefault|stopPropagation={fileDrop}
|
||||||
|
>
|
||||||
|
<UploadDuo size={'large'} />
|
||||||
|
<div class="small-text content-dark-color mt-2">
|
||||||
|
<Label label={task.string.NoAttachmentsForTask} />
|
||||||
|
</div>
|
||||||
|
<div class="small-text">
|
||||||
|
<a href={'#'} on:click={() => inputFile.click()}><Label label={task.string.UploadDropFilesHere} /></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<Table
|
||||||
|
_class={chunter.class.Attachment}
|
||||||
|
config={['', 'lastModified']}
|
||||||
|
options={ {} }
|
||||||
|
query={ { attachedTo: objectId } }
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.attachments-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-right: .75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: var(--theme-caption-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.zone-container {
|
||||||
|
padding: 1rem;
|
||||||
|
color: var(--theme-caption-color);
|
||||||
|
background: rgba(255, 255, 255, .03);
|
||||||
|
border: 1px dashed rgba(255, 255, 255, .16);
|
||||||
|
border-radius: .75rem;
|
||||||
|
}
|
||||||
|
</style>
|
56
plugins/task-resources/src/components/CreateProject.svelte
Normal file
56
plugins/task-resources/src/components/CreateProject.svelte
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2020 Anticrm Platform Contributors.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
import { IconFolder, EditBox, ToggleWithLabel, Grid } from '@anticrm/ui'
|
||||||
|
|
||||||
|
import { getClient, SpaceCreateCard } from '@anticrm/presentation'
|
||||||
|
|
||||||
|
import task from '../plugin'
|
||||||
|
import core from '@anticrm/core'
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
let name: string = ''
|
||||||
|
let description: string = ''
|
||||||
|
|
||||||
|
export function canClose(): boolean {
|
||||||
|
return name === ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
function createProject() {
|
||||||
|
client.createDoc(task.class.Project, core.space.Model, {
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
private: false,
|
||||||
|
members: []
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SpaceCreateCard
|
||||||
|
label={task.string.CreateProject}
|
||||||
|
okAction={createProject}
|
||||||
|
canSave={name ? true : false}
|
||||||
|
on:close={() => { dispatch('close') }}
|
||||||
|
>
|
||||||
|
<Grid column={1} rowGap={1.5}>
|
||||||
|
<EditBox label={task.string.ProjectName} icon={IconFolder} bind:value={name} placeholder={'Project name'} focus/>
|
||||||
|
<ToggleWithLabel label={task.string.MakePrivate} description={task.string.MakePrivateDescription}/>
|
||||||
|
</Grid>
|
||||||
|
</SpaceCreateCard>
|
@ -14,46 +14,119 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import contact, { Employee, EmployeeAccount } from '@anticrm/contact'
|
||||||
|
import type { Data, Ref, Space } from '@anticrm/core'
|
||||||
|
import { generateId } from '@anticrm/core'
|
||||||
|
import { Card, getClient, UserBox } from '@anticrm/presentation'
|
||||||
|
import { Task } from '@anticrm/task'
|
||||||
|
import { EditBox, Grid, Status as StatusControl } from '@anticrm/ui'
|
||||||
|
import { Status, OK, Severity } from '@anticrm/platform'
|
||||||
|
import view from '@anticrm/view'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import type { Ref, Space } from '@anticrm/core'
|
|
||||||
import { DatePicker, EditBox, Dialog, Tabs, Section, Grid, Row, TextArea, IconFile } from '@anticrm/ui'
|
|
||||||
import { UserBox } from '@anticrm/presentation'
|
|
||||||
import { ReferenceInput } from '@anticrm/text-editor'
|
|
||||||
import type { Person } from '@anticrm/contact'
|
|
||||||
|
|
||||||
import { getClient } from '@anticrm/presentation'
|
|
||||||
|
|
||||||
import contact from '@anticrm/contact'
|
|
||||||
import task from '../plugin'
|
import task from '../plugin'
|
||||||
|
|
||||||
export let space: Ref<Space>
|
export let space: Ref<Space>
|
||||||
|
|
||||||
|
let _space = space
|
||||||
|
const status: Status = OK
|
||||||
|
|
||||||
|
let assignee: Ref<EmployeeAccount> // | null = null
|
||||||
|
|
||||||
|
const object: Data<Task> = {
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
assignee: undefined as unknown as Ref<Employee>,
|
||||||
|
number: 0
|
||||||
|
}
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
let title: string
|
|
||||||
let assignee: Ref<Person>
|
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
const taskId = generateId()
|
||||||
|
|
||||||
function createCandidate() {
|
export function canClose (): boolean {
|
||||||
client.createDoc(task.class.Task, space, {
|
return object.name !== ''
|
||||||
title,
|
}
|
||||||
|
|
||||||
|
async function createTask () {
|
||||||
|
const sequence = await client.findOne(view.class.Sequence, { attachedTo: task.class.Task })
|
||||||
|
if (sequence === undefined) {
|
||||||
|
throw new Error('sequence object not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
const incResult = await client.updateDoc(view.class.Sequence, view.space.Sequence, sequence._id, {
|
||||||
|
$inc: { sequence: 1 }
|
||||||
|
}, true)
|
||||||
|
|
||||||
|
const value: Data<Task> = {
|
||||||
|
name: object.name,
|
||||||
|
description: object.description,
|
||||||
assignee,
|
assignee,
|
||||||
})
|
number: (incResult as any).object.sequence
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.createDoc(task.class.Task, _space, value, taskId)
|
||||||
|
dispatch('close')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Dialog label={'Create Task'}
|
<!-- <DialogHeader {space} {object} {newValue} {resume} create={true} on:save={createCandidate}/> -->
|
||||||
okLabel={'Create Task'}
|
|
||||||
okAction={createCandidate}
|
<Card label={task.string.CreateTask}
|
||||||
|
okAction={createTask}
|
||||||
|
canSave={object.name.length > 0 && assignee !== undefined}
|
||||||
|
spaceClass={task.class.Project}
|
||||||
|
spaceLabel={task.string.ProjectName}
|
||||||
|
spacePlaceholder={task.string.SelectProject}
|
||||||
|
bind:space={_space}
|
||||||
on:close={() => { dispatch('close') }}>
|
on:close={() => { dispatch('close') }}>
|
||||||
<Tabs/>
|
<StatusControl slot="error" {status} />
|
||||||
<Section icon={IconFile} label={'General Information'}>
|
<Grid column={1} rowGap={1.5}>
|
||||||
<Grid>
|
<EditBox label={task.string.TaskName} bind:value={object.name} icon={task.icon.Task} placeholder="The boring task" maxWidth="39rem" focus/>
|
||||||
<Row><EditBox label={'Title *'} placeholder={'The Secret Project'} bind:value={title} focus /></Row>
|
<UserBox _class={contact.class.EmployeeAccount} title='Assignee *' caption='Assign this task' bind:value={assignee} />
|
||||||
<UserBox _class={contact.class.Person} title='Assignee' caption='Employees' bind:value={assignee} />
|
|
||||||
<DatePicker title={'Pick due date'} />
|
|
||||||
<Row><ReferenceInput /></Row>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Section>
|
</Card>
|
||||||
</Dialog>
|
|
||||||
|
<style lang="scss">
|
||||||
|
.channels {
|
||||||
|
margin-top: 1.25rem;
|
||||||
|
span { margin-left: .5rem; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.locations {
|
||||||
|
span {
|
||||||
|
margin-bottom: .125rem;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: .75rem;
|
||||||
|
color: var(--theme-content-accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: .75rem;
|
||||||
|
color: var(--theme-caption-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
margin: 1rem 0;
|
||||||
|
height: 1px;
|
||||||
|
background-color: var(--theme-card-divider);
|
||||||
|
}
|
||||||
|
|
||||||
|
.resume {
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding: .75rem;
|
||||||
|
background: rgba(255, 255, 255, .05);
|
||||||
|
border: 1px dashed rgba(255, 255, 255, .2);
|
||||||
|
border-radius: .5rem;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
&.solid { border-style: solid; }
|
||||||
|
}
|
||||||
|
// .resume a {
|
||||||
|
// font-size: .75rem;
|
||||||
|
// color: var(--theme-content-dark-color);
|
||||||
|
// &:hover { color: var(--theme-content-color); }
|
||||||
|
// }
|
||||||
|
</style>
|
||||||
|
68
plugins/task-resources/src/components/EditTask.svelte
Normal file
68
plugins/task-resources/src/components/EditTask.svelte
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2020 Anticrm Platform Contributors.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import type { Ref } from '@anticrm/core'
|
||||||
|
import { Panel } from '@anticrm/panel'
|
||||||
|
import { createQuery, getClient } from '@anticrm/presentation'
|
||||||
|
import type { Task } from '@anticrm/task'
|
||||||
|
import { EditBox, Grid } from '@anticrm/ui'
|
||||||
|
import view from '@anticrm/view'
|
||||||
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
import task from '../plugin'
|
||||||
|
import Attachments from './Attachments.svelte'
|
||||||
|
import TaskHeader from './TaskHeader.svelte'
|
||||||
|
|
||||||
|
export let _id: Ref<Task>
|
||||||
|
let object: Task
|
||||||
|
|
||||||
|
const query = createQuery()
|
||||||
|
$: query.query(task.class.Task, { _id }, result => { object = result[0] })
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
function change (field: string, value: any) {
|
||||||
|
client.updateDoc(task.class.Task, object.space, object._id, { [field]: value })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if object !== undefined}
|
||||||
|
<Panel icon={view.icon.Table} title={object.name} {object} on:close={() => { dispatch('close') }}>
|
||||||
|
<TaskHeader {object} slot="subtitle" />
|
||||||
|
|
||||||
|
|
||||||
|
<Grid column={1} rowGap={1.5}>
|
||||||
|
<EditBox label={task.string.TaskName} bind:value={object.name} icon={task.icon.Task} placeholder="The boring task" maxWidth="39rem" focus on:change={(evt) => change('name', object.name)}/>
|
||||||
|
<EditBox label={task.string.TaskDescription} bind:value={object.description} icon={task.icon.Task} placeholder="Description" maxWidth="39rem" on:change={(evt) => change('description', object.description)}/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<div class="mt-14">
|
||||||
|
<Attachments objectId={object._id} _class={object._class} space={object.space} />
|
||||||
|
</div>
|
||||||
|
</Panel>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.attachments {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-cards {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
column-gap: 1.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
41
plugins/task-resources/src/components/TaskHeader.svelte
Normal file
41
plugins/task-resources/src/components/TaskHeader.svelte
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||||
|
// Copyright © 2021 Hardcore Engineering Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import contact from '@anticrm/contact'
|
||||||
|
import { getClient, UserBox } from '@anticrm/presentation'
|
||||||
|
import { Task } from '@anticrm/task'
|
||||||
|
import task from '../plugin'
|
||||||
|
|
||||||
|
export let object: Task
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
function change () {
|
||||||
|
client.updateDoc(object._class, object.space, object._id, { assignee: object.assignee })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex-between header">
|
||||||
|
<UserBox _class={contact.class.Employee} title={task.string.TaskAssignee} caption='Assignee' bind:value={object.assignee} on:change={change} />
|
||||||
|
<!-- <AttributeBarEditor key={'state'} {object} showHeader={false} /> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 .5rem;
|
||||||
|
}
|
||||||
|
</style>
|
39
plugins/task-resources/src/components/TaskPresenter.svelte
Normal file
39
plugins/task-resources/src/components/TaskPresenter.svelte
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||||
|
// Copyright © 2021 Hardcore Engineering Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
|
||||||
|
import type { Task } from '@anticrm/task'
|
||||||
|
import { closeTooltip, Icon, showPopup } from '@anticrm/ui'
|
||||||
|
import EditTask from './EditTask.svelte'
|
||||||
|
import { getClient } from '@anticrm/presentation'
|
||||||
|
import task from '../plugin'
|
||||||
|
|
||||||
|
export let value: Task
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
const shortLabel = client.getHierarchy().getClass(value._class).shortLabel
|
||||||
|
|
||||||
|
function show () {
|
||||||
|
closeTooltip()
|
||||||
|
showPopup(EditTask, { _id: value._id }, 'full')
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="sm-tool-icon" on:click={show}>
|
||||||
|
<span class="icon"><Icon icon={task.icon.Task} size={'small'}/></span>{shortLabel}-{value.number}
|
||||||
|
</div>
|
28
plugins/task-resources/src/components/icons/UploadDuo.svelte
Normal file
28
plugins/task-resources/src/components/icons/UploadDuo.svelte
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||||
|
// Copyright © 2021 Hardcore Engineering Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export let size: 'small' | 'medium' | 'large'
|
||||||
|
const fill: string = 'currentColor'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg class="svg-{size}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path fill="var(--duotone-color)" d="M18,6.4c-0.1,0-0.2,0-0.3,0c-0.1,0-0.1,0-0.1,0c-0.1,0-0.1,0-0.1,0c0,0,0,0-0.1-0.1c0,0,0,0-0.1-0.1 c0-0.1-0.1-0.2-0.2-0.4c-0.9-1.9-2.8-3.3-5.1-3.3c-2.3,0-4.2,1.4-5.1,3.3C6.8,5.9,6.7,6,6.7,6.1c0,0.1-0.1,0.1-0.1,0.1 C6.6,6.3,6.6,6.3,6.5,6.3c0,0,0,0-0.1,0c0,0,0,0-0.1,0c-0.1,0-0.2,0-0.3,0C4,6.4,2.4,8,2.4,10S4,13.6,6,13.6h6h6 c2,0,3.6-1.6,3.6-3.6S20,6.4,18,6.4z"/>
|
||||||
|
<g {fill}>
|
||||||
|
<path d="M18,6.4c-0.1,0-0.2,0-0.3,0c-0.1,0-0.1,0-0.1,0c-0.1,0-0.1,0-0.1,0c0,0,0,0-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0 c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1-0.1c0-0.1-0.1-0.2-0.2-0.4c-0.9-1.9-2.8-3.3-5.1-3.3c-2.3,0-4.2,1.4-5.1,3.3 C6.8,5.9,6.7,6,6.7,6.1c0,0.1-0.1,0.1-0.1,0.1c0,0,0,0,0,0C6.6,6.3,6.6,6.3,6.5,6.3c0,0,0,0-0.1,0c0,0,0,0-0.1,0 c-0.1,0-0.2,0-0.3,0C4,6.4,2.4,8,2.4,10S4,13.6,6,13.6h0.6l1.2-1.2H6c-1.3,0-2.4-1.1-2.4-2.4c0-1.3,1.1-2.4,2.4-2.4h0.1 c0.2,0,0.4,0,0.6,0c0.2,0,0.4-0.1,0.6-0.2c0.2-0.1,0.3-0.3,0.4-0.4c0.1-0.1,0.1-0.2,0.2-0.3C7.8,6.5,7.9,6.4,8,6.2l0,0 c0.7-1.5,2.2-2.6,4-2.6s3.3,1.1,4,2.6l0,0c0.1,0.2,0.1,0.3,0.2,0.4c0,0.1,0.1,0.2,0.2,0.3c0.1,0.2,0.2,0.3,0.4,0.4 c0.2,0.1,0.4,0.2,0.6,0.2c0.2,0,0.4,0,0.6,0H18c1.3,0,2.4,1.1,2.4,2.4c0,1.3-1.1,2.4-2.4,2.4h-1.8l1.2,1.2H18c2,0,3.6-1.6,3.6-3.6 S20,6.4,18,6.4z"/>
|
||||||
|
<path d="M12,11.2l-4.4,4.4l0.8,0.8l3-3V21c0,0.3,0.3,0.6,0.6,0.6s0.6-0.3,0.6-0.6v-7.6l3,3l0.8-0.8L12,11.2z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
@ -14,10 +14,16 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import CreateTask from './components/CreateTask.svelte'
|
import { Resources } from '@anticrm/platform'
|
||||||
|
|
||||||
export default async () => ({
|
import CreateTask from './components/CreateTask.svelte'
|
||||||
|
import CreateProject from './components/CreateProject.svelte'
|
||||||
|
import TaskPresenter from './components/TaskPresenter.svelte'
|
||||||
|
|
||||||
|
export default async (): Promise<Resources> => ({
|
||||||
component: {
|
component: {
|
||||||
CreateTask
|
CreateTask,
|
||||||
},
|
CreateProject,
|
||||||
|
TaskPresenter
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
@ -13,9 +13,28 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { mergeIds } from '@anticrm/platform'
|
import { IntlString, mergeIds } from '@anticrm/platform'
|
||||||
|
|
||||||
import task, { taskId } from '@anticrm/task'
|
import task, { taskId } from '@anticrm/task'
|
||||||
|
|
||||||
export default mergeIds(taskId, task, {
|
export default mergeIds(taskId, task, {
|
||||||
|
string: {
|
||||||
|
ApplicationLabelTask: '' as IntlString,
|
||||||
|
Projects: '' as IntlString,
|
||||||
|
CreateProject: '' as IntlString,
|
||||||
|
ProjectName: '' as IntlString,
|
||||||
|
MakePrivate: '' as IntlString,
|
||||||
|
MakePrivateDescription: '' as IntlString,
|
||||||
|
CreateTask: '' as IntlString,
|
||||||
|
TaskProject: '' as IntlString,
|
||||||
|
SelectProject: '' as IntlString,
|
||||||
|
TaskName: '' as IntlString,
|
||||||
|
TaskAssignee: '' as IntlString,
|
||||||
|
TaskDescription: '' as IntlString,
|
||||||
|
NoAttachmentsForTask: '' as IntlString,
|
||||||
|
UploadDropFilesHere: '' as IntlString
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
AssigneeRequired: '' as IntlString
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
42
plugins/task-resources/src/utils.ts
Normal file
42
plugins/task-resources/src/utils.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||||
|
// Copyright © 2021 Hardcore Engineering Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import type { Doc, Ref, Space } from '@anticrm/core'
|
||||||
|
import login from '@anticrm/login'
|
||||||
|
import { getMetadata } from '@anticrm/platform'
|
||||||
|
|
||||||
|
export async function uploadFile (space: Ref<Space>, file: File, attachedTo: Ref<Doc>): Promise<string> {
|
||||||
|
console.log(file)
|
||||||
|
const uploadUrl = getMetadata(login.metadata.UploadUrl)
|
||||||
|
|
||||||
|
const data = new FormData()
|
||||||
|
data.append('file', file)
|
||||||
|
|
||||||
|
const url = `${uploadUrl as string}?space=${space}&name=${encodeURIComponent(file.name)}&attachedTo=${attachedTo}`
|
||||||
|
const resp = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + (getMetadata(login.metadata.LoginToken) as string)
|
||||||
|
},
|
||||||
|
body: data
|
||||||
|
})
|
||||||
|
if (resp.status !== 200) {
|
||||||
|
throw new Error('Can\'t upload file.')
|
||||||
|
}
|
||||||
|
const uuid = await resp.text()
|
||||||
|
console.log(uuid)
|
||||||
|
return uuid
|
||||||
|
}
|
@ -13,10 +13,10 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { plugin } from '@anticrm/platform'
|
|
||||||
import type { Plugin, Asset } from '@anticrm/platform'
|
|
||||||
import type { Space, Doc, Ref, Class } from '@anticrm/core'
|
|
||||||
import type { Employee } from '@anticrm/contact'
|
import type { Employee } from '@anticrm/contact'
|
||||||
|
import type { Class, Doc, Ref, Space } from '@anticrm/core'
|
||||||
|
import type { Asset, Plugin } from '@anticrm/platform'
|
||||||
|
import { plugin } from '@anticrm/platform'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
@ -27,9 +27,15 @@ export interface Project extends Space {}
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export interface Task extends Doc {
|
export interface Task extends Doc {
|
||||||
title: string
|
number: number // Sequence number
|
||||||
|
|
||||||
|
name: string
|
||||||
description: string
|
description: string
|
||||||
assignee: Ref<Employee>
|
assignee: Ref<Employee>
|
||||||
|
|
||||||
|
comments?: number
|
||||||
|
attachments?: number
|
||||||
|
labels?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,7 +45,8 @@ export const taskId = 'task' as Plugin
|
|||||||
|
|
||||||
export default plugin(taskId, {
|
export default plugin(taskId, {
|
||||||
class: {
|
class: {
|
||||||
Task: '' as Ref<Class<Task>>
|
Task: '' as Ref<Class<Task>>,
|
||||||
|
Project: '' as Ref<Class<Project>>
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
Task: '' as Asset
|
Task: '' as Asset
|
||||||
|
Loading…
Reference in New Issue
Block a user