mirror of
https://github.com/hcengineering/platform.git
synced 2025-06-12 13:42:38 +00:00
Email tempaltes (#853)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
390a4b28d1
commit
52baf5444d
5
.vscode/launch.json
vendored
5
.vscode/launch.json
vendored
@ -13,7 +13,10 @@
|
||||
"ELASTIC_URL": "http://localhost:9200",
|
||||
"MONGO_URL": "mongodb://localhost:27017",
|
||||
"APM_SERVER_URL2": "http://localhost:8200",
|
||||
"METRICS_CONSOLE": "true" // Show metrics in console evert 30 seconds.
|
||||
"METRICS_CONSOLE": "true", // Show metrics in console evert 30 seconds.,
|
||||
"MINIO_ENDPOINT": "localhost",
|
||||
"MINIO_ACCESS_KEY":"minioadmin",
|
||||
"MINIO_SECRET_KEY":"minioadmin"
|
||||
},
|
||||
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
|
||||
"sourceMaps": true,
|
||||
|
@ -64,6 +64,8 @@ specifiers:
|
||||
'@rush-temp/model-setting': file:./projects/model-setting.tgz
|
||||
'@rush-temp/model-task': file:./projects/model-task.tgz
|
||||
'@rush-temp/model-telegram': file:./projects/model-telegram.tgz
|
||||
'@rush-temp/model-templates': file:./projects/model-templates.tgz
|
||||
'@rush-temp/model-text-editor': file:./projects/model-text-editor.tgz
|
||||
'@rush-temp/model-view': file:./projects/model-view.tgz
|
||||
'@rush-temp/model-workbench': file:./projects/model-workbench.tgz
|
||||
'@rush-temp/mongo': file:./projects/mongo.tgz
|
||||
@ -93,6 +95,9 @@ specifiers:
|
||||
'@rush-temp/telegram': file:./projects/telegram.tgz
|
||||
'@rush-temp/telegram-assets': file:./projects/telegram-assets.tgz
|
||||
'@rush-temp/telegram-resources': file:./projects/telegram-resources.tgz
|
||||
'@rush-temp/templates': file:./projects/templates.tgz
|
||||
'@rush-temp/templates-assets': file:./projects/templates-assets.tgz
|
||||
'@rush-temp/templates-resources': file:./projects/templates-resources.tgz
|
||||
'@rush-temp/text-editor': file:./projects/text-editor.tgz
|
||||
'@rush-temp/theme': file:./projects/theme.tgz
|
||||
'@rush-temp/tool': file:./projects/tool.tgz
|
||||
@ -249,6 +254,8 @@ dependencies:
|
||||
'@rush-temp/model-setting': file:projects/model-setting.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-task': file:projects/model-task.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-telegram': file:projects/model-telegram.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-templates': file:projects/model-templates.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-text-editor': file:projects/model-text-editor.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-view': file:projects/model-view.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-workbench': file:projects/model-workbench.tgz_typescript@4.5.4
|
||||
'@rush-temp/mongo': file:projects/mongo.tgz
|
||||
@ -278,6 +285,9 @@ dependencies:
|
||||
'@rush-temp/telegram': file:projects/telegram.tgz
|
||||
'@rush-temp/telegram-assets': file:projects/telegram-assets.tgz
|
||||
'@rush-temp/telegram-resources': file:projects/telegram-resources.tgz_096c09b0b673a57c275d9767a12070b1
|
||||
'@rush-temp/templates': file:projects/templates.tgz
|
||||
'@rush-temp/templates-assets': file:projects/templates-assets.tgz
|
||||
'@rush-temp/templates-resources': file:projects/templates-resources.tgz_096c09b0b673a57c275d9767a12070b1
|
||||
'@rush-temp/text-editor': file:projects/text-editor.tgz_096c09b0b673a57c275d9767a12070b1
|
||||
'@rush-temp/theme': file:projects/theme.tgz_096c09b0b673a57c275d9767a12070b1
|
||||
'@rush-temp/tool': file:projects/tool.tgz
|
||||
@ -11636,7 +11646,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/model-all.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-xDbSAT10XpV9IMIWZmkZF1DKtDmPuh++4I5oxtxRHGrrdJ1h0J37nkAmZ6AayfWgqaCXG8EBn+SplvLw07HESg==, tarball: file:projects/model-all.tgz}
|
||||
resolution: {integrity: sha512-5WhGhRWED9z51QVhlJWZJ321v4zkTY33gwVOdMVHidlhnmKJ2LPWfIN8Gs1K2I0Z2Gea3GfcgDbSrTYSGQd7bw==, tarball: file:projects/model-all.tgz}
|
||||
id: file:projects/model-all.tgz
|
||||
name: '@rush-temp/model-all'
|
||||
version: 0.0.0
|
||||
@ -12015,6 +12025,48 @@ packages:
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
file:projects/model-templates.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-yX+lWtzx5DiEX8LI6I8/XaAw+RkthYZgqVcAEvpL7vraVJHwSukdKHyHXRu6XdGAyXeMdlgPcwD9xF6CQts5gA==, tarball: file:projects/model-templates.tgz}
|
||||
id: file:projects/model-templates.tgz
|
||||
name: '@rush-temp/model-templates'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@rushstack/heft': 0.41.8
|
||||
'@types/heft-jest': 1.0.2
|
||||
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
|
||||
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
|
||||
eslint: 7.32.0
|
||||
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
|
||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
prettier: 2.5.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
file:projects/model-text-editor.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-2B69wwO38YusKx2s2f+p0sf+2ExNVFMTqO41+2SJKIQCfVF6vshEOn9HS3m93V5xIlZ3wJmVW5vl5b5x0beF1g==, tarball: file:projects/model-text-editor.tgz}
|
||||
id: file:projects/model-text-editor.tgz
|
||||
name: '@rush-temp/model-text-editor'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@rushstack/heft': 0.41.8
|
||||
'@types/heft-jest': 1.0.2
|
||||
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
|
||||
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
|
||||
eslint: 7.32.0
|
||||
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
|
||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
prettier: 2.5.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
file:projects/model-view.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-Nw3Id7t/uufJKYSapqk8INj5vMWLppU+gjcKnDD4tNoTtbbr/Zfe9NNwpcieZBJphJ0BpMTs1vYBmlZUTEQinw==, tarball: file:projects/model-view.tgz}
|
||||
id: file:projects/model-view.tgz
|
||||
@ -12252,7 +12304,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/prod.tgz_sass@1.45.0+typescript@4.5.4:
|
||||
resolution: {integrity: sha512-FWLkhyyIA2ZiXuydQap4fYlvfq02Q18A0fjVgVmy/7Wedebed2Xj6n2uQVjDVN50a5EP+5CutRcLAuxs7bI4Vw==, tarball: file:projects/prod.tgz}
|
||||
resolution: {integrity: sha512-TRuJuHrFjTf/GKVoEbO9fUjFNW/dRPVDdYd8HyhpTr26o8RpI8yCYWasAX/V7nJiMRXL06FbEp0vwjMh1odogQ==, tarball: file:projects/prod.tgz}
|
||||
id: file:projects/prod.tgz
|
||||
name: '@rush-temp/prod'
|
||||
version: 0.0.0
|
||||
@ -12553,7 +12605,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/setting-resources.tgz_096c09b0b673a57c275d9767a12070b1:
|
||||
resolution: {integrity: sha512-KNZjL1XCVMDaeEnRfQBi4JAMjdg5aUyf6jrCrLGMZfG8Keq4JjHKqCNGVQ+xaYFZcQrEifs7M5OD9D6oimC4ag==, tarball: file:projects/setting-resources.tgz}
|
||||
resolution: {integrity: sha512-64E4dI7SY+8qkmtk5dn8wbbxOSOqM+AD4Xh+i0BTv09Fhafe/TAcYLdByY5jzVkLmBohrYgBioZJcPbmulsvXg==, tarball: file:projects/setting-resources.tgz}
|
||||
id: file:projects/setting-resources.tgz
|
||||
name: '@rush-temp/setting-resources'
|
||||
version: 0.0.0
|
||||
@ -12745,6 +12797,82 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/templates-assets.tgz:
|
||||
resolution: {integrity: sha512-ZmNp9/xT3bhobdqstxRpaa+ddU1K3WLzF1ErI6L+cARerFsrgeG0g7+DaaMpd4QIv4Ip3+3MhDIbvjq8JCKE4g==, tarball: file:projects/templates-assets.tgz}
|
||||
name: '@rush-temp/templates-assets'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@rushstack/heft': 0.41.8
|
||||
'@types/heft-jest': 1.0.2
|
||||
'@types/node': 16.11.14
|
||||
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
|
||||
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
|
||||
eslint: 7.32.0
|
||||
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
|
||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
prettier: 2.5.1
|
||||
typescript: 4.5.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/templates-resources.tgz_096c09b0b673a57c275d9767a12070b1:
|
||||
resolution: {integrity: sha512-dsQP6LQ9+rxBOtUE2GXjmu7lhsQUAtP3ZWdzfo58ncdXao64Dn8w2nYrrUZ9dz7rcxwOPP3oHsrK7N2Egs1CMw==, tarball: file:projects/templates-resources.tgz}
|
||||
id: file:projects/templates-resources.tgz
|
||||
name: '@rush-temp/templates-resources'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
|
||||
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
|
||||
eslint: 7.32.0
|
||||
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
|
||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
eslint-plugin-svelte3: 3.2.1_eslint@7.32.0+svelte@3.44.3
|
||||
prettier: 2.5.1
|
||||
prettier-plugin-svelte: 2.5.1_prettier@2.5.1+svelte@3.44.3
|
||||
sass: 1.45.0
|
||||
svelte: 3.44.3
|
||||
svelte-check: 2.2.11_4374c622c67ed7479ff0e44c29d09bce
|
||||
svelte-loader: 3.1.2_svelte@3.44.3
|
||||
svelte-preprocess: 4.10.1_14d64cad431e31f100de7363af24a44f
|
||||
typescript: 4.5.4
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- coffeescript
|
||||
- less
|
||||
- node-sass
|
||||
- postcss
|
||||
- postcss-load-config
|
||||
- pug
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/templates.tgz:
|
||||
resolution: {integrity: sha512-GRoSidgyl5TL1m7EI6J/XuUCM7aQ8zp5jH8yl8oDXPHG2rS2v+7pSz9ccBE/ynC0pUkxKL1oSgDRMq9eAXC4Ag==, tarball: file:projects/templates.tgz}
|
||||
name: '@rush-temp/templates'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@rushstack/heft': 0.41.8
|
||||
'@types/heft-jest': 1.0.2
|
||||
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
|
||||
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
|
||||
eslint: 7.32.0
|
||||
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
|
||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
prettier: 2.5.1
|
||||
typescript: 4.5.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/text-editor.tgz_096c09b0b673a57c275d9767a12070b1:
|
||||
resolution: {integrity: sha512-mHTzsgBUTd2d3Y8xW1y8GOTLU0r4IyOsF7RpV1N4GVwaqnCZSxuFdC/T7PqX33XYI0hD6q+0KNegRs+MzvOeeg==, tarball: file:projects/text-editor.tgz}
|
||||
id: file:projects/text-editor.tgz
|
||||
|
@ -93,6 +93,9 @@
|
||||
"@anticrm/server-attachment": "~0.6.1",
|
||||
"@anticrm/server-attachment-resources": "~0.6.0",
|
||||
"@anticrm/server-contact": "~0.6.1",
|
||||
"@anticrm/server-contact-resources": "~0.6.0"
|
||||
"@anticrm/server-contact-resources": "~0.6.0",
|
||||
"@anticrm/templates": "~0.6.0",
|
||||
"@anticrm/templates-assets": "~0.6.0",
|
||||
"@anticrm/templates-resources": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import { clientId } from '@anticrm/client'
|
||||
import { gmailId } from '@anticrm/gmail'
|
||||
import { imageCropperId } from '@anticrm/image-cropper'
|
||||
import { inventoryId } from '@anticrm/inventory'
|
||||
import { templatesId } from '@anticrm/templates'
|
||||
|
||||
import '@anticrm/login-assets'
|
||||
import '@anticrm/task-assets'
|
||||
@ -46,6 +47,7 @@ import '@anticrm/lead-assets'
|
||||
import '@anticrm/gmail-assets'
|
||||
import '@anticrm/workbench-assets'
|
||||
import '@anticrm/inventory-assets'
|
||||
import '@anticrm/templates-assets'
|
||||
|
||||
import { setMetadata } from '@anticrm/platform'
|
||||
export async function configurePlatform() {
|
||||
@ -76,4 +78,5 @@ export async function configurePlatform() {
|
||||
addLocation(gmailId, () => import(/* webpackChunkName: "gmail" */ '@anticrm/gmail-resources'))
|
||||
addLocation(imageCropperId, () => import(/* webpackChunkName: "image-cropper" */ '@anticrm/image-cropper-resources'))
|
||||
addLocation(inventoryId, () => import(/* webpackChunkName: "inventory" */ '@anticrm/inventory-resources'))
|
||||
addLocation(templatesId, () => import(/* webpackChunkName: "templates" */ '@anticrm/templates-resources'))
|
||||
}
|
||||
|
@ -48,6 +48,8 @@
|
||||
"@anticrm/model-gmail": "~0.6.0",
|
||||
"@anticrm/model-inventory": "~0.6.0",
|
||||
"@anticrm/model-presentation": "~0.6.0",
|
||||
"@anticrm/model-templates": "~0.6.0",
|
||||
"@anticrm/model-text-editor": "~0.6.0",
|
||||
"@anticrm/core": "~0.6.13"
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ import { createModel as leadModel } from '@anticrm/model-lead'
|
||||
import { createModel as gmailModel } from '@anticrm/model-gmail'
|
||||
import { createModel as inventoryModel } from '@anticrm/model-inventory'
|
||||
import { createModel as presentationModel } from '@anticrm/model-presentation'
|
||||
import { createModel as templatesModel } from '@anticrm/model-templates'
|
||||
import { createModel as textEditorModel } from '@anticrm/model-text-editor'
|
||||
|
||||
import { createModel as serverCoreModel } from '@anticrm/model-server-core'
|
||||
import { createModel as serverAttachmentModel } from '@anticrm/model-server-attachment'
|
||||
@ -54,6 +56,8 @@ leadModel(builder)
|
||||
gmailModel(builder)
|
||||
inventoryModel(builder)
|
||||
presentationModel(builder)
|
||||
templatesModel(builder)
|
||||
textEditorModel(builder)
|
||||
|
||||
serverCoreModel(builder)
|
||||
serverAttachmentModel(builder)
|
||||
|
@ -17,8 +17,8 @@ import { Builder, Model } from '@anticrm/model'
|
||||
import { Ref, Domain, DOMAIN_MODEL } from '@anticrm/core'
|
||||
import core, { TDoc } from '@anticrm/model-core'
|
||||
import setting from '@anticrm/setting'
|
||||
import type { Integration, IntegrationType, Handler } from '@anticrm/setting'
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import type { Integration, IntegrationType, Handler, SettingsCategory } from '@anticrm/setting'
|
||||
import type { Asset, IntlString } from '@anticrm/platform'
|
||||
import task from '@anticrm/task'
|
||||
|
||||
import workbench from '@anticrm/model-workbench'
|
||||
@ -31,6 +31,13 @@ export class TIntegration extends TDoc implements Integration {
|
||||
type!: Ref<IntegrationType>
|
||||
value!: string
|
||||
}
|
||||
@Model(setting.class.SettingsCategory, core.class.Doc, DOMAIN_MODEL)
|
||||
export class TSettingsCategory extends TDoc implements SettingsCategory {
|
||||
name!: string
|
||||
label!: IntlString
|
||||
icon!: Asset
|
||||
component!: AnyComponent
|
||||
}
|
||||
|
||||
@Model(setting.class.IntegrationType, core.class.Doc, DOMAIN_MODEL)
|
||||
export class TIntegrationType extends TDoc implements IntegrationType {
|
||||
@ -42,7 +49,65 @@ export class TIntegrationType extends TDoc implements IntegrationType {
|
||||
}
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.createModel(TIntegration, TIntegrationType)
|
||||
builder.createModel(TIntegration, TIntegrationType, TSettingsCategory)
|
||||
|
||||
builder.createDoc(setting.class.SettingsCategory, core.space.Model, {
|
||||
name: 'profile',
|
||||
label: setting.string.EditProfile,
|
||||
icon: setting.icon.EditProfile,
|
||||
component: setting.component.Profile,
|
||||
order: 0
|
||||
}, setting.ids.Profile)
|
||||
|
||||
builder.createDoc(setting.class.SettingsCategory, core.space.Model, {
|
||||
name: 'password',
|
||||
label: setting.string.ChangePassword,
|
||||
icon: setting.icon.Password,
|
||||
component: setting.component.Password,
|
||||
order: 1000
|
||||
}, setting.ids.Password)
|
||||
builder.createDoc(setting.class.SettingsCategory, core.space.Model, {
|
||||
name: 'setting',
|
||||
label: setting.string.Setting,
|
||||
icon: setting.icon.Setting,
|
||||
component: setting.component.Setting,
|
||||
order: 2000
|
||||
}, setting.ids.Setting)
|
||||
builder.createDoc(setting.class.SettingsCategory, core.space.Model, {
|
||||
name: 'integrations',
|
||||
label: setting.string.Integrations,
|
||||
icon: setting.icon.Integrations,
|
||||
component: setting.component.Integrations,
|
||||
order: 3000
|
||||
}, setting.ids.Integrations)
|
||||
builder.createDoc(setting.class.SettingsCategory, core.space.Model, {
|
||||
name: 'statuses',
|
||||
label: setting.string.ManageStatuses,
|
||||
icon: task.icon.ManageStatuses,
|
||||
component: setting.component.ManageStatuses,
|
||||
order: 4000
|
||||
}, setting.ids.ManageStatuses)
|
||||
builder.createDoc(setting.class.SettingsCategory, core.space.Model, {
|
||||
name: 'support',
|
||||
label: setting.string.Support,
|
||||
icon: setting.icon.Support,
|
||||
component: setting.component.Support,
|
||||
order: 5000
|
||||
}, setting.ids.Support)
|
||||
builder.createDoc(setting.class.SettingsCategory, core.space.Model, {
|
||||
name: 'privacy',
|
||||
label: setting.string.Privacy,
|
||||
icon: setting.icon.Privacy,
|
||||
component: setting.component.Privacy,
|
||||
order: 6000
|
||||
}, setting.ids.Privacy)
|
||||
builder.createDoc(setting.class.SettingsCategory, core.space.Model, {
|
||||
name: 'terms',
|
||||
label: setting.string.Terms,
|
||||
icon: setting.icon.Terms,
|
||||
component: setting.component.Terms,
|
||||
order: 10000
|
||||
}, setting.ids.Terms)
|
||||
|
||||
builder.createDoc(
|
||||
workbench.class.Application,
|
||||
@ -51,59 +116,7 @@ export function createModel (builder: Builder): void {
|
||||
label: setting.string.Setting,
|
||||
icon: setting.icon.Setting,
|
||||
hidden: true,
|
||||
navigatorModel: {
|
||||
specials: [
|
||||
{
|
||||
id: 'profile',
|
||||
label: setting.string.EditProfile,
|
||||
icon: setting.icon.EditProfile,
|
||||
component: setting.component.Profile
|
||||
},
|
||||
{
|
||||
id: 'password',
|
||||
label: setting.string.ChangePassword,
|
||||
icon: setting.icon.Password,
|
||||
component: setting.component.Password
|
||||
},
|
||||
{
|
||||
id: 'setting',
|
||||
label: setting.string.Setting,
|
||||
icon: setting.icon.Setting,
|
||||
component: setting.component.Setting
|
||||
},
|
||||
{
|
||||
id: 'integrations',
|
||||
label: setting.string.Integrations,
|
||||
icon: setting.icon.Integrations,
|
||||
component: setting.component.Integrations
|
||||
},
|
||||
{
|
||||
id: 'statuses',
|
||||
label: setting.string.ManageStatuses,
|
||||
icon: task.icon.ManageStatuses,
|
||||
component: setting.component.ManageStatuses
|
||||
},
|
||||
{
|
||||
id: 'support',
|
||||
label: setting.string.Support,
|
||||
icon: setting.icon.Support,
|
||||
component: setting.component.Support
|
||||
},
|
||||
{
|
||||
id: 'privacy',
|
||||
label: setting.string.Privacy,
|
||||
icon: setting.icon.Privacy,
|
||||
component: setting.component.Privacy
|
||||
},
|
||||
{
|
||||
id: 'terms',
|
||||
label: setting.string.Terms,
|
||||
icon: setting.icon.Terms,
|
||||
component: setting.component.Terms
|
||||
}
|
||||
],
|
||||
spaces: []
|
||||
}
|
||||
component: setting.component.Settings
|
||||
},
|
||||
setting.ids.SettingApp
|
||||
)
|
||||
|
7
models/templates/.eslintrc.js
Normal file
7
models/templates/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@anticrm/model-rig/profiles/default/config/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
4
models/templates/.npmignore
Normal file
4
models/templates/.npmignore
Normal file
@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
18
models/templates/config/rig.json
Normal file
18
models/templates/config/rig.json
Normal file
@ -0,0 +1,18 @@
|
||||
// The "rig.json" file directs tools to look for their config files in an external package.
|
||||
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
|
||||
/**
|
||||
* (Required) The name of the rig package to inherit from.
|
||||
* It should be an NPM package name with the "-rig" suffix.
|
||||
*/
|
||||
"rigPackageName": "@anticrm/model-rig"
|
||||
|
||||
/**
|
||||
* (Optional) Selects a config profile from the rig package. The name must consist of
|
||||
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
|
||||
* If omitted, then the "default" profile will be used."
|
||||
*/
|
||||
// "rigProfile": "your-profile-name"
|
||||
}
|
40
models/templates/package.json
Normal file
40
models/templates/package.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "@anticrm/model-templates",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"author": "Anticrm Platform Contributors",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "heft build",
|
||||
"build:watch": "tsc",
|
||||
"lint:fix": "eslint --fix src",
|
||||
"lint": "eslint src",
|
||||
"format": "prettier --write src && eslint --fix src"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anticrm/model-rig": "~0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-promise": "^5.1.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint": "^7.32.0",
|
||||
"@types/heft-jest": "^1.0.2",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
||||
"prettier": "^2.4.1",
|
||||
"@rushstack/heft": "^0.41.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anticrm/activity": "~0.6.0",
|
||||
"@anticrm/model": "~0.6.0",
|
||||
"@anticrm/core": "~0.6.0",
|
||||
"@anticrm/platform": "~0.6.5",
|
||||
"@anticrm/model-core": "~0.6.0",
|
||||
"@anticrm/model-contact": "~0.6.1",
|
||||
"@anticrm/templates": "~0.6.0",
|
||||
"@anticrm/templates-resources": "~0.6.0",
|
||||
"@anticrm/setting": "~0.6.0",
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
"@anticrm/model-text-editor": "~0.6.0"
|
||||
}
|
||||
}
|
67
models/templates/src/index.ts
Normal file
67
models/templates/src/index.ts
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// 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 { Domain } from '@anticrm/core'
|
||||
import { Builder, Model, Prop, TypeString } from '@anticrm/model'
|
||||
import core, { TDoc } from '@anticrm/model-core'
|
||||
import textEditor from '@anticrm/model-text-editor'
|
||||
import { IntlString } from '@anticrm/platform'
|
||||
import setting from '@anticrm/setting'
|
||||
import type { MessageTemplate } from '@anticrm/templates'
|
||||
import templates from './plugin'
|
||||
|
||||
export const DOMAIN_TEMPLATES = 'templates' as Domain
|
||||
|
||||
@Model(templates.class.MessageTemplate, core.class.Doc, DOMAIN_TEMPLATES)
|
||||
export class TMessageTemplate extends TDoc implements MessageTemplate {
|
||||
@Prop(TypeString(), 'Title' as IntlString)
|
||||
title!: string;
|
||||
|
||||
@Prop(TypeString(), 'Message' as IntlString)
|
||||
message!: string;
|
||||
}
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.createModel(TMessageTemplate)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.Space,
|
||||
core.space.Model,
|
||||
{
|
||||
name: 'Templates',
|
||||
description: 'Space for all templates',
|
||||
private: true,
|
||||
archived: false,
|
||||
members: []
|
||||
},
|
||||
templates.space.Templates
|
||||
)
|
||||
|
||||
builder.createDoc(setting.class.SettingsCategory, core.space.Model, {
|
||||
name: 'message-templates',
|
||||
label: templates.string.Templates,
|
||||
icon: templates.icon.Templates,
|
||||
component: templates.component.Templates,
|
||||
order: 3500
|
||||
}, templates.ids.Templates)
|
||||
|
||||
builder.createDoc(textEditor.class.RefInputActionItem, core.space.Model, {
|
||||
label: templates.string.Templates,
|
||||
icon: templates.icon.Templates,
|
||||
action: templates.action.ShowTemplates,
|
||||
order: 1500
|
||||
}, templates.ids.TemplatePopupAction)
|
||||
}
|
39
models/templates/src/plugin.ts
Normal file
39
models/templates/src/plugin.ts
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.
|
||||
//
|
||||
|
||||
import { Ref } from '@anticrm/core'
|
||||
import { mergeIds, Resource } from '@anticrm/platform'
|
||||
import { SettingsCategory } from '@anticrm/setting'
|
||||
import { templatesId } from '@anticrm/templates'
|
||||
import templates from '@anticrm/templates-resources/src/plugin'
|
||||
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
import { RefInputAction, RefInputActionItem } from '@anticrm/model-text-editor'
|
||||
|
||||
export default mergeIds(templatesId, templates, {
|
||||
ids: {
|
||||
Templates: '' as Ref<SettingsCategory>,
|
||||
TemplatePopupAction: '' as Ref<RefInputActionItem>
|
||||
},
|
||||
|
||||
// Without it, CLI version is failed with some svelte dependency exception.
|
||||
componnets: {
|
||||
Dummy: '' as AnyComponent
|
||||
},
|
||||
action: {
|
||||
ShowTemplates: '' as Resource<RefInputAction>
|
||||
}
|
||||
})
|
8
models/templates/tsconfig.json
Normal file
8
models/templates/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./node_modules/@anticrm/model-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
}
|
||||
}
|
7
models/text-editor/.eslintrc.js
Normal file
7
models/text-editor/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@anticrm/model-rig/profiles/default/config/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
4
models/text-editor/.npmignore
Normal file
4
models/text-editor/.npmignore
Normal file
@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
18
models/text-editor/config/rig.json
Normal file
18
models/text-editor/config/rig.json
Normal file
@ -0,0 +1,18 @@
|
||||
// The "rig.json" file directs tools to look for their config files in an external package.
|
||||
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
|
||||
/**
|
||||
* (Required) The name of the rig package to inherit from.
|
||||
* It should be an NPM package name with the "-rig" suffix.
|
||||
*/
|
||||
"rigPackageName": "@anticrm/model-rig"
|
||||
|
||||
/**
|
||||
* (Optional) Selects a config profile from the rig package. The name must consist of
|
||||
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
|
||||
* If omitted, then the "default" profile will be used."
|
||||
*/
|
||||
// "rigProfile": "your-profile-name"
|
||||
}
|
35
models/text-editor/package.json
Normal file
35
models/text-editor/package.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@anticrm/model-text-editor",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"author": "Anticrm Platform Contributors",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "heft build",
|
||||
"build:watch": "tsc",
|
||||
"lint:fix": "eslint --fix src",
|
||||
"lint": "eslint src",
|
||||
"format": "prettier --write src && eslint --fix src"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anticrm/model-rig": "~0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-promise": "^5.1.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint": "^7.32.0",
|
||||
"@types/heft-jest": "^1.0.2",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
||||
"prettier": "^2.4.1",
|
||||
"@rushstack/heft": "^0.41.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anticrm/core": "~0.6.11",
|
||||
"@anticrm/model": "~0.6.0",
|
||||
"@anticrm/platform": "~0.6.5",
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
"@anticrm/text-editor": "~0.6.0",
|
||||
"@anticrm/model-core": "~0.6.0"
|
||||
}
|
||||
}
|
40
models/text-editor/src/index.ts
Normal file
40
models/text-editor/src/index.ts
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import { DOMAIN_MODEL } from '@anticrm/core'
|
||||
import { Builder, Model } from '@anticrm/model'
|
||||
import core, { TDoc } from '@anticrm/model-core'
|
||||
import type { Asset, IntlString, Resource } from '@anticrm/platform'
|
||||
// Import types to prevent .svelte components to being exposed to type typescript.
|
||||
import { RefInputAction, RefInputActionItem } from '@anticrm/text-editor/src/types'
|
||||
import textEditor from './plugin'
|
||||
|
||||
export { default } from './plugin'
|
||||
export { RefInputAction, RefInputActionItem }
|
||||
|
||||
@Model(textEditor.class.RefInputActionItem, core.class.Doc, DOMAIN_MODEL)
|
||||
export class TRefInputActionItem extends TDoc implements RefInputActionItem {
|
||||
label!: IntlString
|
||||
icon!: Asset
|
||||
|
||||
// Query for documents with pattern
|
||||
action!: Resource<RefInputAction>
|
||||
}
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.createModel(
|
||||
TRefInputActionItem
|
||||
)
|
||||
}
|
23
models/text-editor/src/plugin.ts
Normal file
23
models/text-editor/src/plugin.ts
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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 { mergeIds } from '@anticrm/platform'
|
||||
// Import plugin directly to prevent .svelte components to being exposed to type typescript.
|
||||
import textEditor, { textEditorId } from '@anticrm/text-editor/src/plugin'
|
||||
|
||||
export default mergeIds(textEditorId, textEditor, {
|
||||
|
||||
})
|
8
models/text-editor/tsconfig.json
Normal file
8
models/text-editor/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./node_modules/@anticrm/model-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getResource, translate } from '@anticrm/platform'
|
||||
import { getResource } from '@anticrm/platform'
|
||||
import { getClient, ObjectSearchCategory, ObjectSearchResult } from '@anticrm/presentation'
|
||||
import { ActionIcon, EditWithIcon, IconSearch, Label } from '@anticrm/ui'
|
||||
import plugin from '../plugin'
|
||||
@ -91,12 +91,6 @@
|
||||
}
|
||||
}
|
||||
$: updateItems(category, query)
|
||||
|
||||
let placeholder = ''
|
||||
|
||||
$: translate(category.label, {}).then((v) => {
|
||||
placeholder = v
|
||||
})
|
||||
</script>
|
||||
|
||||
<div
|
||||
@ -119,7 +113,7 @@
|
||||
{/each}
|
||||
</div>
|
||||
<div class='mt-4 mb-4'>
|
||||
<EditWithIcon icon={IconSearch} bind:value={query} on:input={() => updateItems(category, query) } placeholder={placeholder} />
|
||||
<EditWithIcon icon={IconSearch} bind:value={query} on:input={() => updateItems(category, query) } placeholder={category.label} />
|
||||
</div>
|
||||
<Label label={plugin.string.Suggested}/>
|
||||
<div class="scroll mt-2">
|
||||
|
@ -14,11 +14,14 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { getResource } from '@anticrm/platform'
|
||||
import presentation, { getClient, ObjectSearchCategory, ObjectSearchFactory } from '@anticrm/presentation'
|
||||
import { Asset, getResource, IntlString } from '@anticrm/platform'
|
||||
import presentation, { getClient, ObjectSearchCategory } from '@anticrm/presentation'
|
||||
import { AnySvelteComponent, Icon } from '@anticrm/ui'
|
||||
import { AnyExtension } from '@tiptap/core'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { Completion } from '../Completion'
|
||||
import textEditorPlugin from '../plugin'
|
||||
import { RefInputAction, RefInputActionItem, TextEditorHandler } from '../types'
|
||||
import Attach from './icons/Attach.svelte'
|
||||
import Emoji from './icons/Emoji.svelte'
|
||||
import GIF from './icons/GIF.svelte'
|
||||
@ -40,7 +43,52 @@
|
||||
client.findAll(presentation.class.ObjectSearchCategory, {}).then((r) => {
|
||||
categories = r
|
||||
})
|
||||
interface RefAction {
|
||||
label: IntlString
|
||||
icon: Asset | AnySvelteComponent
|
||||
action: RefInputAction
|
||||
order: number
|
||||
}
|
||||
const defActions: RefAction[] = [
|
||||
{
|
||||
label: textEditorPlugin.string.Attach,
|
||||
icon: Attach,
|
||||
action: () => {},
|
||||
order: 1000
|
||||
},
|
||||
{
|
||||
label: textEditorPlugin.string.TextStyle,
|
||||
icon: TextStyle,
|
||||
action: () => {},
|
||||
order: 2000
|
||||
},
|
||||
{
|
||||
label: textEditorPlugin.string.Emoji,
|
||||
icon: Emoji,
|
||||
action: () => {},
|
||||
order: 3000
|
||||
},
|
||||
{
|
||||
label: textEditorPlugin.string.GIF,
|
||||
icon: GIF,
|
||||
action: () => {},
|
||||
order: 4000
|
||||
}
|
||||
]
|
||||
|
||||
let actions: RefAction[] = []
|
||||
client.findAll<RefInputActionItem>(textEditorPlugin.class.RefInputActionItem, {}).then(async (res) => {
|
||||
const cont: RefAction[] = []
|
||||
for (const r of res) {
|
||||
cont.push({
|
||||
label: r.label,
|
||||
icon: r.icon,
|
||||
order: r.order ?? 10000,
|
||||
action: await getResource(r.action)
|
||||
})
|
||||
}
|
||||
actions = defActions.concat(...cont).sort((a, b) => a.order - b.order)
|
||||
})
|
||||
|
||||
// Current selected category
|
||||
let category: ObjectSearchCategory | undefined = categories[0]
|
||||
@ -95,6 +143,16 @@
|
||||
}
|
||||
})
|
||||
]
|
||||
|
||||
const editorHandler: TextEditorHandler = {
|
||||
insertText: (text) => {
|
||||
textEditor.insertText(text)
|
||||
}
|
||||
}
|
||||
function handleAction (a: RefAction, evt?: Event): void {
|
||||
console.log('handle event', a.label)
|
||||
a.action(evt?.target as HTMLElement, editorHandler)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="ref-container">
|
||||
@ -113,10 +171,11 @@
|
||||
{/if}
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div class="tool"><Attach /></div>
|
||||
<div class="tool"><TextStyle /></div>
|
||||
<div class="tool"><Emoji /></div>
|
||||
<div class="tool"><GIF /></div>
|
||||
{#each actions as a}
|
||||
<div class="tool" on:click={(evt) => handleAction(a, evt)}>
|
||||
<Icon icon={a.icon} size={'large'}/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
112
packages/text-editor/src/components/StyledTextEditor.svelte
Normal file
112
packages/text-editor/src/components/StyledTextEditor.svelte
Normal file
@ -0,0 +1,112 @@
|
||||
<!--
|
||||
// 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 { ScrollBox } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import Emoji from './icons/Emoji.svelte'
|
||||
import GIF from './icons/GIF.svelte'
|
||||
import TextStyle from './icons/TextStyle.svelte'
|
||||
import TextEditor from './TextEditor.svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
export let content: string = ''
|
||||
|
||||
let textEditor: TextEditor
|
||||
|
||||
export function submit (): void {
|
||||
textEditor.submit()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="ref-container">
|
||||
<div class="textInput">
|
||||
<div class="inputMsg">
|
||||
<ScrollBox bothScroll stretch>
|
||||
<TextEditor
|
||||
bind:content
|
||||
bind:this={textEditor}
|
||||
on:value
|
||||
on:content={(ev) => {
|
||||
dispatch('message', ev.detail)
|
||||
content = ''
|
||||
textEditor.clear()
|
||||
}}
|
||||
supportSubmit={false}
|
||||
/>
|
||||
</ScrollBox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div class="tool"><TextStyle size={'large'} /></div>
|
||||
<div class="tool"><Emoji size={'large'}/></div>
|
||||
<div class="tool"><GIF size={'large'}/></div>
|
||||
<div class="flex-grow">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.ref-container {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 4.5rem;
|
||||
|
||||
.textInput {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
min-height: 2.75rem;
|
||||
background-color: transparent;
|
||||
|
||||
.inputMsg {
|
||||
align-self: stretch;
|
||||
width: 100%;
|
||||
color: var(--theme-content-color);
|
||||
background-color: transparent;
|
||||
|
||||
:global(.ProseMirror) {
|
||||
min-height: 0;
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.buttons {
|
||||
margin: 10px 0 0 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.tool {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
opacity: 0.3;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.tool + .tool {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -15,7 +15,7 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { AnyExtension, Editor, Extension } from '@tiptap/core'
|
||||
import { AnyExtension, Editor, Extension, HTMLContent } from '@tiptap/core'
|
||||
import Highlight from '@tiptap/extension-highlight'
|
||||
import Link from '@tiptap/extension-link'
|
||||
// import Typography from '@tiptap/extension-typography'
|
||||
@ -26,6 +26,7 @@
|
||||
export let content: string = ''
|
||||
export let placeholder: string = 'Type something...'
|
||||
export let extensions: AnyExtension[] = []
|
||||
export let supportSubmit = true
|
||||
|
||||
let element: HTMLElement
|
||||
let editor: Editor
|
||||
@ -41,6 +42,9 @@
|
||||
content = ''
|
||||
editor.commands.clearContent(false)
|
||||
}
|
||||
export function insertText (text: string): void {
|
||||
editor.commands.insertContent(text as HTMLContent)
|
||||
}
|
||||
|
||||
const Handle = Extension.create({
|
||||
addKeyboardShortcuts () {
|
||||
@ -73,7 +77,7 @@
|
||||
StarterKit,
|
||||
Highlight,
|
||||
Link,
|
||||
Handle, // order important
|
||||
...(supportSubmit ? [Handle] : []), // order important
|
||||
// Typography, // we need to disable 1/2 -> ½ rule (https://github.com/hcengineering/anticrm/issues/345)
|
||||
Placeholder.configure({ placeholder: placeholder }),
|
||||
...extensions
|
||||
@ -84,6 +88,10 @@
|
||||
},
|
||||
onBlur: () => {
|
||||
dispatch('blur')
|
||||
},
|
||||
onUpdate: () => {
|
||||
content = editor.getHTML()
|
||||
dispatch('value', content)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -95,7 +103,7 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<div style="width: 100%" bind:this={element}/>
|
||||
<div style="width: 100%;" bind:this={element}/>
|
||||
|
||||
<style lang="scss" global>
|
||||
|
||||
@ -103,9 +111,9 @@
|
||||
overflow-y: auto;
|
||||
max-height: 5.5rem;
|
||||
outline: none;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
line-height: 150%;
|
||||
p:not(:last-child) {
|
||||
margin-block-end: 1em;
|
||||
}
|
||||
|
||||
> * + * {
|
||||
|
@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
export let size: number = 20
|
||||
export let size: string
|
||||
const fill: string = 'var(--theme-caption-color)'
|
||||
</script>
|
||||
|
||||
<svg width={size} height={size} {fill} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class={`class-${size}`} {fill} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.82816 10.4853L10.485 4.82845C11.6566 3.65688 13.5561 3.65688 14.7277 4.82845C15.8992 6.00002 15.8992 7.89952 14.7277 9.07109L8.01014 15.7886C7.42436 16.3744 6.47461 16.3744 5.88882 15.7886C5.30304 15.2028 5.30304 14.2531 5.88882 13.6673L11.8992 7.65687C12.0945 7.46161 12.0945 7.14503 11.8992 6.94977C11.704 6.75451 11.3874 6.75451 11.1921 6.94977L5.18172 12.9602C4.20541 13.9365 4.20541 15.5194 5.18172 16.4957C6.15803 17.472 7.74094 17.472 8.71725 16.4957L15.4348 9.77819C16.9969 8.2161 16.9969 5.68344 15.4348 4.12134C13.8727 2.55924 11.34 2.55924 9.77791 4.12134L4.12106 9.77819C3.92579 9.97346 3.92579 10.29 4.12106 10.4853C4.31632 10.6806 4.6329 10.6806 4.82816 10.4853Z"/>
|
||||
</svg>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
export let size: number = 20
|
||||
export let size: string
|
||||
const fill: string = 'var(--theme-caption-color)'
|
||||
</script>
|
||||
|
||||
<svg width={size} height={size} {fill} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class={`class-${size}`} {fill} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 2C14.4183 2 18 5.58172 18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2ZM10 3C6.13401 3 3 6.13401 3 10C3 13.866 6.13401 17 10 17C13.866 17 17 13.866 17 10C17 6.13401 13.866 3 10 3ZM7.15467 12.4273C8.66416 13.9463 11.0877 14.0045 12.6671 12.5961L12.8453 12.4273C13.04 12.2314 13.3566 12.2304 13.5524 12.4251C13.7265 12.5981 13.7467 12.8674 13.6123 13.0627L13.5547 13.1322L13.5323 13.1545C11.5691 15.1054 8.39616 15.0953 6.44533 13.1322C6.25069 12.9363 6.25169 12.6197 6.44757 12.4251C6.64344 12.2304 6.96002 12.2314 7.15467 12.4273ZM12.5 7.5C13.0523 7.5 13.5 7.94772 13.5 8.5C13.5 9.05228 13.0523 9.5 12.5 9.5C11.9477 9.5 11.5 9.05228 11.5 8.5C11.5 7.94772 11.9477 7.5 12.5 7.5ZM7.5 7.5C8.05228 7.5 8.5 7.94772 8.5 8.5C8.5 9.05228 8.05228 9.5 7.5 9.5C6.94772 9.5 6.5 9.05228 6.5 8.5C6.5 7.94772 6.94772 7.5 7.5 7.5Z"/>
|
||||
</svg>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
export let size: number = 20
|
||||
export let size: string
|
||||
const fill: string = 'var(--theme-caption-color)'
|
||||
</script>
|
||||
|
||||
<svg width={size} height={size} {fill} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class={`class-${size}`} {fill} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.4 3C16.7864 3 17.9194 4.1869 17.9959 5.68238L18 5.84375V14.1562C18 15.6727 16.9148 16.9118 15.5475 16.9955L15.4 17H4.6C3.21357 17 2.0806 15.8131 2.00412 14.3176L2 14.1562V5.84375C2 4.32735 3.08516 3.08816 4.45246 3.0045L4.6 3H15.4ZM15.25 4H4.75C3.82377 4 3.06561 4.793 3.00404 5.79653L3 5.92857V14.0714C3 15.0922 3.71957 15.9277 4.63018 15.9956L4.75 16H15.25C16.1762 16 16.9344 15.207 16.996 14.2035L17 14.0714V5.92857C17 4.90783 16.2804 4.0723 15.3698 4.00445L15.25 4ZM6.85135 7.00214C7.4713 7.00214 7.99907 7.0988 8.43229 7.30058C8.69893 7.42477 8.80624 7.72539 8.67198 7.97203C8.53772 8.21867 8.21272 8.31793 7.94609 8.19374C7.6779 8.06883 7.31378 8.00214 6.85135 8.00214C5.82473 8.00214 5.08108 8.8345 5.08108 10.0011C5.08108 11.1209 5.89403 12 6.85135 12C7.44761 12 7.85273 11.6487 7.91152 11.3268L7.91892 11.2472V10.5011L7.54054 10.5C7.24201 10.5 7 10.2761 7 10C7 9.75454 7.19122 9.55039 7.44338 9.50806L7.54054 9.5L8.45946 9.50107C8.72482 9.50107 8.94552 9.67794 8.99129 9.91119L9 10.0011V11.2472C9 12.1244 8.11351 13 6.85135 13C5.25622 13 4 11.6415 4 10.0011C4 8.31985 5.17727 7.00214 6.85135 7.00214ZM11 7C11.2455 7 11.4496 7.17688 11.4919 7.41012L11.5 7.5V12.5C11.5 12.7761 11.2761 13 11 13C10.7545 13 10.5504 12.8231 10.5081 12.5899L10.5 12.5V7.5C10.5 7.22386 10.7239 7 11 7ZM15.5 7C15.7761 7 16 7.22386 16 7.5C16 7.74546 15.8231 7.94961 15.5899 7.99194L15.5 8H14V10H15.5C15.7761 10 16 10.2239 16 10.5C16 10.7455 15.8231 10.9496 15.5899 10.9919L15.5 11H14V12.5C14 12.7761 13.7761 13 13.5 13C13.2545 13 13.0504 12.8231 13.0081 12.5899L13 12.5V7.5C13 7.22386 13.2239 7 13.5 7H15.5Z"/>
|
||||
</svg>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
export let size: number = 20
|
||||
export let size: string
|
||||
const fill: string = 'var(--theme-caption-color)'
|
||||
</script>
|
||||
|
||||
<svg width={size} height={size} {fill} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class={`class-${size}`} {fill} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.0872 6.70308C14.9271 5.85998 16.2664 5.81735 17.1568 6.57701L17.2869 6.69697L17.4134 6.83357C18.1376 7.68212 18.1376 8.93671 17.4134 9.78526L17.293 9.91574L10.4167 16.8183C10.2617 16.9739 10.0749 17.0931 9.86988 17.1682L9.71291 17.2161L6.62737 17.9764C6.28827 18.0599 5.98023 17.7813 6.00917 17.4498L6.0236 17.366L6.81558 14.2953C6.86895 14.0883 6.96574 13.8958 7.09885 13.7302L7.20537 13.6112L14.0872 6.70308ZM16.5811 7.40543C16.1201 6.94613 15.393 6.91684 14.898 7.31661L14.7957 7.40884L7.91383 14.317C7.87193 14.359 7.83804 14.408 7.8135 14.4616L7.7839 14.545L7.20061 16.805L9.47368 16.2452C9.51317 16.2354 9.55114 16.221 9.58682 16.2022L9.6385 16.1709L9.70829 16.1126L16.5845 9.20999C17.0806 8.71206 17.0806 7.90677 16.5811 7.40543ZM6.42419 2.22879L6.46607 2.31323L9.448 9.94224L8.676 10.7172L8.004 8.99824H4.007L2.96614 11.678C2.87719 11.9068 2.63835 12.0329 2.40561 11.9879L2.31893 11.9628C2.09015 11.8738 1.96399 11.635 2.00906 11.4023L2.03413 11.3156L5.53436 2.31403C5.6877 1.9197 6.21661 1.89109 6.42419 2.22879ZM6.00061 3.871L4.396 7.99824H7.614L6.00061 3.871Z"/>
|
||||
</svg>
|
||||
|
@ -1,14 +1,31 @@
|
||||
//
|
||||
// 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 { addStringsLoader } from '@anticrm/platform'
|
||||
import { textEditorId } from './plugin'
|
||||
|
||||
//
|
||||
export * from '@anticrm/presentation/src/types'
|
||||
export * from './types'
|
||||
|
||||
export { default as ReferenceInput } from './components/ReferenceInput.svelte'
|
||||
export { default as TextEditor } from './components/TextEditor.svelte'
|
||||
|
||||
export * from '@anticrm/presentation/src/types'
|
||||
export { default as StyledTextEditor } from './components/StyledTextEditor.svelte'
|
||||
|
||||
addStringsLoader(textEditorId, async (lang: string) => {
|
||||
return await import(`../lang/${lang}.json`)
|
||||
})
|
||||
|
||||
export { default } from './plugin'
|
||||
export { default } from './plugin'
|
@ -14,7 +14,9 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Class, Ref } from '@anticrm/core'
|
||||
import { IntlString, Plugin, plugin } from '@anticrm/platform'
|
||||
import { RefInputActionItem } from './types'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@ -22,7 +24,14 @@ import { IntlString, Plugin, plugin } from '@anticrm/platform'
|
||||
export const textEditorId = 'text-editor' as Plugin
|
||||
|
||||
export default plugin(textEditorId, {
|
||||
class: {
|
||||
RefInputActionItem: '' as Ref<Class<RefInputActionItem>>
|
||||
},
|
||||
string: {
|
||||
Suggested: '' as IntlString
|
||||
Suggested: '' as IntlString,
|
||||
Attach: '' as IntlString,
|
||||
TextStyle: '' as IntlString,
|
||||
Emoji: '' as IntlString,
|
||||
GIF: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
26
packages/text-editor/src/types.ts
Normal file
26
packages/text-editor/src/types.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Asset, IntlString, Resource } from '@anticrm/platform'
|
||||
import { Doc } from '@anticrm/core'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface TextEditorHandler {
|
||||
insertText: (html: string) => void
|
||||
}
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type RefInputAction = (element: HTMLElement, editor: TextEditorHandler) => void
|
||||
/**
|
||||
* A contribution to reference input control, to allow to add more actions to it.
|
||||
* @public
|
||||
*/
|
||||
export interface RefInputActionItem extends Doc {
|
||||
label: IntlString
|
||||
icon: Asset
|
||||
|
||||
// Query for documents with pattern
|
||||
action: Resource<RefInputAction>
|
||||
|
||||
order?: number
|
||||
}
|
@ -28,4 +28,8 @@
|
||||
<path d="M4.7,7.8h0.7c0.3,0,0.5-0.2,0.5-0.5S5.6,6.8,5.3,6.8H4.7c-0.3,0-0.5,0.2-0.5,0.5S4.4,7.8,4.7,7.8z"/>
|
||||
<path d="M6.7,9.5h-2c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5h2c0.3,0,0.5-0.2,0.5-0.5S6.9,9.5,6.7,9.5z"/>
|
||||
</symbol>
|
||||
<symbol id="signout" viewBox="0 0 16 16" fill="none">
|
||||
<path d="M12.24 4.42664C13.0789 5.26583 13.6502 6.33493 13.8815 7.49876C14.1129 8.66259 13.994 9.86889 13.5398 10.9651C13.0856 12.0614 12.3165 12.9983 11.3299 13.6575C10.3432 14.3167 9.18328 14.6686 7.99668 14.6686C6.81007 14.6686 5.65011 14.3167 4.66346 13.6575C3.67681 12.9983 2.90777 12.0614 2.45359 10.9651C1.9994 9.86889 1.88047 8.66259 2.11182 7.49876C2.34317 6.33493 2.91442 5.26583 3.75334 4.42664" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8 1.33331V7.99998" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 4.5 KiB |
@ -21,6 +21,8 @@
|
||||
"LearnMore": "Learn more",
|
||||
"EnterCurrentPassword": "Enter current password",
|
||||
"EnterNewPassword": "Enter new password",
|
||||
"RepeatNewPassword": "Repeat new password"
|
||||
"RepeatNewPassword": "Repeat new password",
|
||||
"Signout": "Sign out",
|
||||
"Settings": "Settings"
|
||||
}
|
||||
}
|
@ -24,7 +24,8 @@ loadMetadata(setting.icon, {
|
||||
Integrations: `${icons}#integration`,
|
||||
Support: `${icons}#support`,
|
||||
Privacy: `${icons}#privacy`,
|
||||
Terms: `${icons}#terms`
|
||||
Terms: `${icons}#terms`,
|
||||
Signout: `${icons}#signout`
|
||||
})
|
||||
|
||||
addStringsLoader(settingId, async (lang: string) => await import(`../lang/${lang}.json`))
|
||||
|
@ -45,6 +45,7 @@
|
||||
"@anticrm/task": "~0.6.0",
|
||||
"@anticrm/task-resources": "~0.6.0",
|
||||
"@anticrm/workbench": "~0.6.1",
|
||||
"@anticrm/contact-resources": "~0.6.0"
|
||||
"@anticrm/contact-resources": "~0.6.0",
|
||||
"@anticrm/login": "~0.6.1"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
<!--
|
||||
// Copyright © 2021 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 { Asset, IntlString } from '@anticrm/platform'
|
||||
import { Icon, Label } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let icon: Asset | undefined = undefined
|
||||
export let label: IntlString | undefined = undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<div
|
||||
class="flex-row-center container"
|
||||
on:click|stopPropagation={() => {
|
||||
dispatch('click')
|
||||
}}
|
||||
>
|
||||
<div class="icon">
|
||||
{#if icon}
|
||||
<Icon {icon} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
<span>
|
||||
{#if label}<Label {label} />{:else}{label}{/if}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
margin: 0 16px;
|
||||
padding-left: 10px;
|
||||
padding-right: 12px;
|
||||
min-height: 36px;
|
||||
font-weight: 500;
|
||||
color: var(--theme-caption-color);
|
||||
border-radius: 8px;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
|
||||
.icon {
|
||||
margin-right: 18px;
|
||||
width: 16px;
|
||||
min-width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
span {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--theme-button-bg-enabled);
|
||||
.tool {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
106
plugins/setting-resources/src/components/Settings.svelte
Normal file
106
plugins/setting-resources/src/components/Settings.svelte
Normal file
@ -0,0 +1,106 @@
|
||||
<script lang="ts">
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import setting, { SettingsCategory } from '@anticrm/setting'
|
||||
import { Component, getCurrentLocation, Label, location, navigate, setMetadataLocalStorage } from '@anticrm/ui'
|
||||
import { onDestroy } from 'svelte'
|
||||
import CategoryElement from './CategoryElement.svelte'
|
||||
import login from '@anticrm/login'
|
||||
|
||||
const client = getClient()
|
||||
|
||||
let category: SettingsCategory | undefined
|
||||
let categoryId: string = ''
|
||||
|
||||
let categories: SettingsCategory[] = []
|
||||
client.findAll(setting.class.SettingsCategory, {}, { sort: { order: 1 } }).then(s => {
|
||||
categories = s
|
||||
category = findCategory(categoryId)
|
||||
})
|
||||
|
||||
onDestroy(
|
||||
location.subscribe(async (loc) => {
|
||||
categoryId = loc.path[2]
|
||||
category = findCategory(categoryId)
|
||||
})
|
||||
)
|
||||
|
||||
function findCategory (name: string): SettingsCategory | undefined {
|
||||
return categories.find((x) => x.name === name)
|
||||
}
|
||||
function selectCategory (id: string): void {
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = id
|
||||
loc.path.length = 3
|
||||
navigate(loc)
|
||||
}
|
||||
function signOut (): void {
|
||||
setMetadataLocalStorage(login.metadata.LoginToken, null)
|
||||
setMetadataLocalStorage(login.metadata.LoginEndpoint, null)
|
||||
setMetadataLocalStorage(login.metadata.LoginEmail, null)
|
||||
navigate({ path: [login.component.LoginApp] })
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class='container'>
|
||||
<div class="panel-navigator">
|
||||
<div class="flex-between navheader-container">
|
||||
<span class="fs-title overflow-label">
|
||||
<Label label={setting.string.Settings}/>
|
||||
</span>
|
||||
</div>
|
||||
{#each categories as category}
|
||||
<CategoryElement icon={category.icon} label={category.label} on:click={() => { selectCategory(category.name) }}/>
|
||||
{/each}
|
||||
<div class='signout'>
|
||||
<CategoryElement icon={setting.icon.Signout} label={setting.string.Signout} on:click={signOut}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-component">
|
||||
{#if category}
|
||||
<Component is={category.component} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding-bottom: 1.25rem;
|
||||
background: var(--theme-menu-color);
|
||||
|
||||
.panel-navigator {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 1rem;
|
||||
min-width: 18rem;
|
||||
width: 18rem;
|
||||
height: 100%;
|
||||
border-radius: 1.25rem;
|
||||
background-color: var(--theme-bg-color);
|
||||
|
||||
.signout {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
flex-grow: 1;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
.panel-component {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 1rem;
|
||||
height: 100%;
|
||||
border-radius: 1.25rem;
|
||||
background-color: var(--theme-bg-color);
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
.navheader-container {
|
||||
padding: 0 1.75rem;
|
||||
height: 4rem;
|
||||
}
|
||||
</style>
|
||||
|
@ -22,9 +22,11 @@ import ManageStatuses from './components/statuses/ManageStatuses.svelte'
|
||||
import Support from './components/Support.svelte'
|
||||
import Privacy from './components/Privacy.svelte'
|
||||
import Terms from './components/Terms.svelte'
|
||||
import Settings from './components/Settings.svelte'
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
Settings,
|
||||
Profile,
|
||||
Password,
|
||||
Setting,
|
||||
|
@ -42,6 +42,19 @@ export interface Integration extends Doc {
|
||||
value: string
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface SettingsCategory extends Doc {
|
||||
name: string
|
||||
label: IntlString
|
||||
icon: Asset
|
||||
component: AnyComponent
|
||||
|
||||
// If defined, will sort using order.
|
||||
order?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@ -49,13 +62,23 @@ export const settingId = 'setting' as Plugin
|
||||
|
||||
export default plugin(settingId, {
|
||||
ids: {
|
||||
SettingApp: '' as Ref<Doc>
|
||||
SettingApp: '' as Ref<Doc>,
|
||||
Profile: '' as Ref<Doc>,
|
||||
Password: '' as Ref<Doc>,
|
||||
Setting: '' as Ref<Doc>,
|
||||
Integrations: '' as Ref<Doc>,
|
||||
ManageStatuses: '' as Ref<Doc>,
|
||||
Support: '' as Ref<Doc>,
|
||||
Privacy: '' as Ref<Doc>,
|
||||
Terms: '' as Ref<Doc>
|
||||
},
|
||||
class: {
|
||||
SettingsCategory: '' as Ref<Class<SettingsCategory>>,
|
||||
Integration: '' as Ref<Class<Integration>>,
|
||||
IntegrationType: '' as Ref<Class<IntegrationType>>
|
||||
},
|
||||
component: {
|
||||
Settings: '' as AnyComponent,
|
||||
Profile: '' as AnyComponent,
|
||||
Password: '' as AnyComponent,
|
||||
Setting: '' as AnyComponent,
|
||||
@ -66,6 +89,7 @@ export default plugin(settingId, {
|
||||
Terms: '' as AnyComponent
|
||||
},
|
||||
string: {
|
||||
Settings: '' as IntlString,
|
||||
Setting: '' as IntlString,
|
||||
Integrations: '' as IntlString,
|
||||
ManageStatuses: '' as IntlString,
|
||||
@ -87,7 +111,8 @@ export default plugin(settingId, {
|
||||
Saved: '' as IntlString,
|
||||
EnterCurrentPassword: '' as IntlString,
|
||||
EnterNewPassword: '' as IntlString,
|
||||
RepeatNewPassword: '' as IntlString
|
||||
RepeatNewPassword: '' as IntlString,
|
||||
Signout: '' as IntlString
|
||||
},
|
||||
icon: {
|
||||
EditProfile: '' as Asset,
|
||||
@ -96,6 +121,7 @@ export default plugin(settingId, {
|
||||
Integrations: '' as Asset,
|
||||
Support: '' as Asset,
|
||||
Privacy: '' as Asset,
|
||||
Terms: '' as Asset
|
||||
Terms: '' as Asset,
|
||||
Signout: '' as Asset
|
||||
}
|
||||
})
|
||||
|
8
plugins/templates-assets/assets/icons.svg
Normal file
8
plugins/templates-assets/assets/icons.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||||
<symbol id="templates" fill="none" viewBox="0 0 16 16">
|
||||
<path d="M8.58334 3.33337V3.33337C7.42111 3.33337 6.83999 3.33337 6.36142 3.45325C4.92972 3.81187 3.81184 4.92975 3.45322 6.36145C3.33334 6.84002 3.33334 7.42114 3.33334 8.58337V10.8C3.33334 11.6139 3.33334 12.0208 3.5562 12.296C3.60017 12.3503 3.64972 12.3999 3.70402 12.4439C3.97922 12.6667 4.38615 12.6667 5.20001 12.6667H7.41668C8.57891 12.6667 9.16003 12.6667 9.6386 12.5468C11.0703 12.1882 12.1882 11.0703 12.5468 9.63863C12.6667 9.16006 12.6667 8.57894 12.6667 7.41671V7.41671" stroke="white"/>
|
||||
<path d="M6 6.66663L10 6.66663" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6 9.33337H8" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12.6667 5.33337L12.6667 1.33337M10.6667 3.33337H14.6667" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</symbol>
|
||||
</svg>
|
After Width: | Height: | Size: 975 B |
14
plugins/templates-assets/lang/en.json
Normal file
14
plugins/templates-assets/lang/en.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"string": {
|
||||
"Cancel": "Cancel",
|
||||
"Templates": "Templates",
|
||||
"TemplatesHeader": "TEMPLATES",
|
||||
"CreateTemplate": "CREATE TEMPLATE",
|
||||
"SaveTemplate": "Save template",
|
||||
"EditTemplate": "Edit template",
|
||||
"ViewTemplate": "View template",
|
||||
"Suggested": "SUGGESTED",
|
||||
"SearchTemplate": "search for template",
|
||||
"TemplatePlaceholder": "New template"
|
||||
}
|
||||
}
|
33
plugins/templates-assets/package.json
Normal file
33
plugins/templates-assets/package.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@anticrm/templates-assets",
|
||||
"version": "0.6.0",
|
||||
"main": "src/index.ts",
|
||||
"author": "Anticrm Platform Contributors",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "heft build",
|
||||
"lint": "eslint src",
|
||||
"lint:fix": "eslint --fix src",
|
||||
"format": "prettier --write src && eslint --fix src",
|
||||
"build:watch": "tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@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": "^7.32.0",
|
||||
"prettier": "^2.4.1",
|
||||
"@types/heft-jest": "^1.0.2",
|
||||
"@rushstack/heft": "^0.41.1",
|
||||
"typescript": "^4.3.5",
|
||||
"@types/node": "^16.4.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anticrm/platform": "~0.6.5",
|
||||
"@anticrm/templates": "~0.6.0"
|
||||
}
|
||||
}
|
25
plugins/templates-assets/src/index.ts
Normal file
25
plugins/templates-assets/src/index.ts
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// 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 { addStringsLoader, loadMetadata } from '@anticrm/platform'
|
||||
import templates, { templatesId } from '@anticrm/templates'
|
||||
|
||||
const icons = require('../assets/icons.svg')
|
||||
loadMetadata(templates.icon, {
|
||||
Templates: `${icons}#templates`
|
||||
})
|
||||
|
||||
addStringsLoader(templatesId, async (lang: string) => await import(`../lang/${lang}.json`))
|
15
plugins/templates-assets/tsconfig.json
Normal file
15
plugins/templates-assets/tsconfig.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"declaration": true,
|
||||
"outDir": "./lib",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom"
|
||||
]
|
||||
}
|
||||
}
|
7
plugins/templates-resources/.eslintrc.js
Normal file
7
plugins/templates-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
|
||||
}
|
||||
}
|
46
plugins/templates-resources/package.json
Normal file
46
plugins/templates-resources/package.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "@anticrm/templates-resources",
|
||||
"version": "0.6.0",
|
||||
"main": "src/index.ts",
|
||||
"author": "Anticrm Platform Contributors",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "echo 'no build for ui'",
|
||||
"build:docs": "api-extractor run --local",
|
||||
"lint": "svelte-check && eslint",
|
||||
"lint:fix": "eslint --fix src",
|
||||
"format": "prettier --write --plugin-search-dir=. src && eslint --fix src",
|
||||
"svelte-check": "svelte-check"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anticrm/platform-rig": "~0.6.0",
|
||||
"svelte-loader": "^3.1.2",
|
||||
"sass": "^1.37.5",
|
||||
"svelte-preprocess": "^4.7.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-promise": "^5.1.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint": "^7.32.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
||||
"eslint-plugin-svelte3": "~3.2.1",
|
||||
"prettier-plugin-svelte": "^2.2.0",
|
||||
"prettier": "^2.4.1",
|
||||
"svelte-check": "^2.2.10",
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anticrm/platform": "~0.6.5",
|
||||
"svelte": "^3.37.0",
|
||||
"@anticrm/templates": "~0.6.0",
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
"@anticrm/presentation": "~0.6.2",
|
||||
"@anticrm/text-editor": "~0.6.0",
|
||||
"@anticrm/setting": "~0.6.0",
|
||||
"@anticrm/chunter": "~0.6.0",
|
||||
"@anticrm/chunter-resources": "~0.6.0",
|
||||
"@anticrm/core": "~0.6.11",
|
||||
"@anticrm/view-resources": "~0.6.0"
|
||||
}
|
||||
}
|
5
plugins/templates-resources/postcss.config.js
Normal file
5
plugins/templates-resources/postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer')
|
||||
]
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
<!--
|
||||
// Copyright © 2021 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 { Doc } from '@anticrm/core'
|
||||
import { IconMoreV, showPopup } from '@anticrm/ui'
|
||||
import { ContextMenu } from '@anticrm/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let label: string = ''
|
||||
export let active: boolean = false
|
||||
export let object: Doc | undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const showMenu = async (ev: MouseEvent, object?: Doc): Promise<void> => {
|
||||
if (object !== undefined) {
|
||||
showPopup(ContextMenu, { object }, ev.target as HTMLElement)
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<div
|
||||
class="flex-row-center container" class:active={active}
|
||||
on:click|stopPropagation={() => {
|
||||
dispatch('click')
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
{label}
|
||||
</span>
|
||||
{#if object}
|
||||
<div class="menuRow" on:click={(ev) => showMenu(ev, object)}><IconMoreV size={'small'} /></div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
min-height: 36px;
|
||||
font-weight: 500;
|
||||
color: var(--theme-caption-color);
|
||||
border-radius: 8px;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
|
||||
span {
|
||||
flex-grow: 1;
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: var(--theme-button-bg-enabled);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--theme-button-bg-enabled);
|
||||
.menuRow {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
.menuRow {
|
||||
visibility: hidden;
|
||||
margin-left: 0.5rem;
|
||||
opacity: 0.6;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
116
plugins/templates-resources/src/components/TemplatePopup.svelte
Normal file
116
plugins/templates-resources/src/components/TemplatePopup.svelte
Normal file
@ -0,0 +1,116 @@
|
||||
<!--
|
||||
// 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 { createQuery } from '@anticrm/presentation'
|
||||
import { MessageTemplate } from '@anticrm/templates'
|
||||
import { TextEditorHandler } from '@anticrm/text-editor'
|
||||
import { closePopup, EditWithIcon, IconSearch, Label, ScrollBox } from '@anticrm/ui'
|
||||
import templates from '../plugin'
|
||||
import TemplateElement from './TemplateElement.svelte'
|
||||
|
||||
export let editor: TextEditorHandler
|
||||
let items: MessageTemplate[] = []
|
||||
|
||||
let query: string = ''
|
||||
|
||||
const liveQuery = createQuery()
|
||||
|
||||
$: liveQuery.query(templates.class.MessageTemplate, query.trim().length === 0 ? {} : { $search: query }, (res) => {
|
||||
items = res
|
||||
})
|
||||
|
||||
let selected = 0
|
||||
|
||||
function dispatchItem (item: MessageTemplate): void {
|
||||
editor.insertText(item.message)
|
||||
closePopup()
|
||||
}
|
||||
|
||||
export function onKeyDown (ev: KeyboardEvent) {
|
||||
if (ev.key === 'ArrowDown') {
|
||||
if (selected < items.length - 1) selected++
|
||||
return true
|
||||
}
|
||||
if (ev.key === 'ArrowUp') {
|
||||
if (selected > 0) selected--
|
||||
return true
|
||||
}
|
||||
if (ev.key === 'Enter') {
|
||||
const item = items[selected]
|
||||
if (item) {
|
||||
dispatchItem(item)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// TODO: How to prevent Esc, it should hide popup instead of closing editor.
|
||||
if (ev.key === 'Esc') {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown}/>
|
||||
<div class="antiPopup template-popup">
|
||||
<div class="mt-4 mb-4">
|
||||
<EditWithIcon icon={IconSearch} bind:value={query} placeholder={templates.string.SearchTemplate} />
|
||||
</div>
|
||||
<Label label={templates.string.Suggested} />
|
||||
<div class='scroll mt-2'>
|
||||
{#each items as item, i}
|
||||
<div
|
||||
class="item"
|
||||
class:selected={i === selected}
|
||||
on:click={() => {
|
||||
dispatchItem(item)
|
||||
}}
|
||||
on:focus={() => {
|
||||
selected = i
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
selected = i
|
||||
}}>
|
||||
{item.title}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<style lang="scss">
|
||||
.template-popup {
|
||||
width: 19.75rem;
|
||||
height: 18.5rem;
|
||||
padding: 16px;
|
||||
background-color: var(--theme-button-bg-hovered);
|
||||
|
||||
.selected {
|
||||
background-color: var(--theme-button-bg-focused);
|
||||
}
|
||||
|
||||
.scroll {
|
||||
max-height: calc(300px - 128px);
|
||||
display: grid;
|
||||
grid-auto-flow: row;
|
||||
gap: 12px;
|
||||
overflow-y: auto;
|
||||
|
||||
.item {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
182
plugins/templates-resources/src/components/Templates.svelte
Normal file
182
plugins/templates-resources/src/components/Templates.svelte
Normal file
@ -0,0 +1,182 @@
|
||||
<script lang="ts">
|
||||
import { Data, Ref } from '@anticrm/core'
|
||||
import { getClient, LiveQuery, MessageViewer } from '@anticrm/presentation'
|
||||
import { MessageTemplate } from '@anticrm/templates'
|
||||
import { StyledTextEditor } from '@anticrm/text-editor'
|
||||
import { Button, CircleButton, EditBox, Icon, IconAdd, Label, ScrollBox } from '@anticrm/ui'
|
||||
import templatesPlugin from '../plugin'
|
||||
import TemplateElement from './TemplateElement.svelte'
|
||||
|
||||
const client = getClient()
|
||||
const query = new LiveQuery()
|
||||
let templates: MessageTemplate[] = []
|
||||
let selected: Ref<MessageTemplate> | undefined
|
||||
let newTemplate: Data<MessageTemplate> | undefined = undefined
|
||||
|
||||
query.query(templatesPlugin.class.MessageTemplate, {}, (t) => {
|
||||
templates = t
|
||||
if (templates.findIndex(t => t._id === selected) === -1) {
|
||||
selected = undefined
|
||||
newTemplate = undefined
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const Mode = {
|
||||
View: 1,
|
||||
Edit: 2,
|
||||
Create: 3
|
||||
}
|
||||
let mode = Mode.View
|
||||
|
||||
async function addTemplate (): Promise<void> {
|
||||
newTemplate = {
|
||||
title: '',
|
||||
message: ''
|
||||
}
|
||||
mode = Mode.Create
|
||||
}
|
||||
async function saveNewTemplate (): Promise<void> {
|
||||
if (newTemplate === undefined) {
|
||||
return
|
||||
}
|
||||
if (mode === Mode.Create) {
|
||||
if (newTemplate.title.trim().length > 0) {
|
||||
const ref = await client.createDoc(templatesPlugin.class.MessageTemplate, templatesPlugin.space.Templates, newTemplate)
|
||||
selected = ref
|
||||
}
|
||||
} else if (selected !== undefined) {
|
||||
await client.updateDoc(templatesPlugin.class.MessageTemplate, templatesPlugin.space.Templates, selected, newTemplate)
|
||||
}
|
||||
mode = Mode.View
|
||||
}
|
||||
|
||||
let textEditor: StyledTextEditor
|
||||
|
||||
export function submit (): void {
|
||||
textEditor.submit()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex-between navheader-container">
|
||||
<span class="fs-title overflow-label flex-row-center">
|
||||
<div class="mr-2">
|
||||
<Icon icon={templatesPlugin.icon.Templates} size={'medium'} />
|
||||
</div>
|
||||
<Label label={templatesPlugin.string.Templates} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-grow">
|
||||
<div class="tempaltes-nav flex-row">
|
||||
<div class="flex-between flex-reverse">
|
||||
<CircleButton icon={IconAdd} on:click={addTemplate} />
|
||||
<Label label={templatesPlugin.string.TemplatesHeader} />
|
||||
</div>
|
||||
<div class="templates flex-row">
|
||||
<ScrollBox vertical stretch>
|
||||
{#each templates as t}
|
||||
<TemplateElement
|
||||
label={t.title}
|
||||
active={newTemplate === undefined && t._id === selected}
|
||||
on:click={() => {
|
||||
selected = t._id
|
||||
newTemplate = { title: t.title, message: t.message }
|
||||
mode = Mode.View
|
||||
}}
|
||||
object={t}
|
||||
/>
|
||||
{/each}
|
||||
</ScrollBox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="templates-edit">
|
||||
{#if newTemplate}
|
||||
<span class="fs-title overflow-label">
|
||||
{#if mode === Mode.Create}
|
||||
<Label label={templatesPlugin.string.CreateTemplate} />
|
||||
{:else if mode === Mode.Edit}
|
||||
<Label label={templatesPlugin.string.EditTemplate} />
|
||||
{:else}
|
||||
<Label label={templatesPlugin.string.ViewTemplate} />
|
||||
{/if}
|
||||
</span>
|
||||
<div class="titleedit mt-4 mb-4">
|
||||
{#if mode !== Mode.View}
|
||||
<EditBox bind:value={newTemplate.title} maxWidth={'12rem'} placeholder={templatesPlugin.string.TemplatePlaceholder} />
|
||||
{:else}
|
||||
{newTemplate.title}
|
||||
{/if}
|
||||
</div>
|
||||
{#if mode !== Mode.View}
|
||||
<StyledTextEditor
|
||||
bind:content={newTemplate.message}
|
||||
bind:this={textEditor}
|
||||
on:value={(evt) => {
|
||||
newTemplate = { title: newTemplate?.title ?? '', message: evt.detail }
|
||||
}}>
|
||||
<div class="flex flex-reverse flex-reverse flex-grow">
|
||||
<div class="ml-2">
|
||||
<Button disabled={newTemplate.title.trim().length == 0 } primary label={templatesPlugin.string.SaveTemplate} on:click={saveNewTemplate} />
|
||||
</div>
|
||||
<Button
|
||||
label={templatesPlugin.string.Cancel}
|
||||
on:click={() => {
|
||||
if (mode === Mode.Create) {
|
||||
newTemplate = undefined
|
||||
}
|
||||
mode = Mode.View
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</StyledTextEditor>
|
||||
{:else}
|
||||
<div class='text'>
|
||||
<MessageViewer message={newTemplate.message}/>
|
||||
</div>
|
||||
<div class='flex flex-reverse'>
|
||||
<Button primary label={templatesPlugin.string.EditTemplate} on:click={() => { mode = Mode.Edit }} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.navheader-container {
|
||||
padding: 0 1.75rem;
|
||||
height: 4rem;
|
||||
border-bottom: 1px solid var(--theme-menu-divider);
|
||||
}
|
||||
.tempaltes-nav {
|
||||
width: 425px;
|
||||
border-right: 1px solid var(--theme-menu-divider);
|
||||
padding: 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.templates-edit {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 2rem;
|
||||
background-color: var(--theme-button-bg-enabled);
|
||||
|
||||
.titleedit {
|
||||
font-size: 18px;
|
||||
border-bottom: 1px solid var(--theme-menu-divider);
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
.templates {
|
||||
margin-top: 2rem;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
.text {
|
||||
flex-grow: 1;
|
||||
line-height: 150%;
|
||||
}
|
||||
</style>
|
34
plugins/templates-resources/src/index.ts
Normal file
34
plugins/templates-resources/src/index.ts
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// 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 { Resources } from '@anticrm/platform'
|
||||
import Templates from './components/Templates.svelte'
|
||||
import { TextEditorHandler } from '@anticrm/text-editor'
|
||||
import { showPopup } from '@anticrm/ui'
|
||||
import TemplatePopup from './components/TemplatePopup.svelte'
|
||||
|
||||
function ShowTemplates (element: HTMLElement, editor: TextEditorHandler): void {
|
||||
showPopup(TemplatePopup, { editor }, element)
|
||||
}
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
Templates
|
||||
},
|
||||
action: {
|
||||
ShowTemplates
|
||||
}
|
||||
})
|
37
plugins/templates-resources/src/plugin.ts
Normal file
37
plugins/templates-resources/src/plugin.ts
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// 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 { IntlString, mergeIds } from '@anticrm/platform'
|
||||
import { AnyComponent } from '@anticrm/ui'
|
||||
import templates, { templatesId } from '@anticrm/templates'
|
||||
|
||||
export default mergeIds(templatesId, templates, {
|
||||
string: {
|
||||
Cancel: '' as IntlString,
|
||||
Templates: '' as IntlString,
|
||||
TemplatesHeader: '' as IntlString,
|
||||
CreateTemplate: '' as IntlString,
|
||||
ViewTemplate: '' as IntlString,
|
||||
EditTemplate: '' as IntlString,
|
||||
SaveTemplate: '' as IntlString,
|
||||
Suggested: '' as IntlString,
|
||||
SearchTemplate: '' as IntlString,
|
||||
TemplatePlaceholder: '' as IntlString
|
||||
},
|
||||
component: {
|
||||
Templates: '' as AnyComponent
|
||||
}
|
||||
})
|
5
plugins/templates-resources/svelte.config.js
Normal file
5
plugins/templates-resources/svelte.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
const sveltePreprocess = require('svelte-preprocess')
|
||||
|
||||
module.exports = {
|
||||
preprocess: sveltePreprocess()
|
||||
};
|
15
plugins/templates-resources/tsconfig.json
Normal file
15
plugins/templates-resources/tsconfig.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"declaration": true,
|
||||
"outDir": "./lib",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom"
|
||||
]
|
||||
}
|
||||
}
|
7
plugins/templates/.eslintrc.js
Normal file
7
plugins/templates/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
4
plugins/templates/.npmignore
Normal file
4
plugins/templates/.npmignore
Normal file
@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
18
plugins/templates/config/rig.json
Normal file
18
plugins/templates/config/rig.json
Normal file
@ -0,0 +1,18 @@
|
||||
// The "rig.json" file directs tools to look for their config files in an external package.
|
||||
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
|
||||
/**
|
||||
* (Required) The name of the rig package to inherit from.
|
||||
* It should be an NPM package name with the "-rig" suffix.
|
||||
*/
|
||||
"rigPackageName": "@anticrm/platform-rig"
|
||||
|
||||
/**
|
||||
* (Optional) Selects a config profile from the rig package. The name must consist of
|
||||
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
|
||||
* If omitted, then the "default" profile will be used."
|
||||
*/
|
||||
// "rigProfile": "your-profile-name"
|
||||
}
|
34
plugins/templates/package.json
Normal file
34
plugins/templates/package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "@anticrm/templates",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"author": "Anticrm Platform Contributors",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "heft build",
|
||||
"build:watch": "tsc",
|
||||
"lint:fix": "eslint --fix src",
|
||||
"lint": "eslint src",
|
||||
"format": "prettier --write src && eslint --fix src"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anticrm/platform-rig": "~0.6.0",
|
||||
"@types/heft-jest": "^1.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-promise": "^5.1.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint": "^7.32.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
||||
"prettier": "^2.4.1",
|
||||
"@rushstack/heft": "^0.41.1",
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anticrm/platform": "~0.6.5",
|
||||
"@anticrm/core": "~0.6.11",
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
"@anticrm/setting": "~0.6.0"
|
||||
}
|
||||
}
|
43
plugins/templates/src/index.ts
Normal file
43
plugins/templates/src/index.ts
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// Copyright © 2020, 2021 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.
|
||||
//
|
||||
|
||||
import type { Class, Doc, Ref, Space } from '@anticrm/core'
|
||||
import type { Plugin } from '@anticrm/platform'
|
||||
import { Asset, plugin } from '@anticrm/platform'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface MessageTemplate extends Doc {
|
||||
title: string
|
||||
message: string
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const templatesId = 'templates' as Plugin
|
||||
|
||||
export default plugin(templatesId, {
|
||||
class: {
|
||||
MessageTemplate: '' as Ref<Class<MessageTemplate>>
|
||||
},
|
||||
space: {
|
||||
Templates: '' as Ref<Space>
|
||||
},
|
||||
icon: {
|
||||
Templates: '' as Asset
|
||||
}
|
||||
})
|
9
plugins/templates/tsconfig.json
Normal file
9
plugins/templates/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"lib": ["esnext", "dom"]
|
||||
}
|
||||
}
|
@ -14,18 +14,16 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { getCurrentLocation, Label, navigate, setMetadataLocalStorage } from '@anticrm/ui'
|
||||
import { Avatar, createQuery, getClient } from '@anticrm/presentation'
|
||||
import workbench, { Application, SpecialNavModel } from '@anticrm/workbench'
|
||||
import setting from '@anticrm/setting'
|
||||
import login from '@anticrm/login'
|
||||
import { getCurrentAccount, Ref } from '@anticrm/core'
|
||||
import contact, { Employee, EmployeeAccount, formatName } from '@anticrm/contact'
|
||||
import { getCurrentAccount, Ref } from '@anticrm/core'
|
||||
import login from '@anticrm/login'
|
||||
import { Avatar, createQuery, getClient } from '@anticrm/presentation'
|
||||
import setting, { SettingsCategory } from '@anticrm/setting'
|
||||
import { closePopup, getCurrentLocation, Icon, Label, navigate, setMetadataLocalStorage } from '@anticrm/ui'
|
||||
|
||||
const client = getClient()
|
||||
async function getItems(): Promise<SpecialNavModel[] | undefined> {
|
||||
const app = await client.findOne(workbench.class.Application, { _id: setting.ids.SettingApp as Ref<Application> })
|
||||
return app?.navigatorModel?.specials
|
||||
async function getItems (): Promise<SettingsCategory[]> {
|
||||
return await client.findAll(setting.class.SettingsCategory, {}, { sort: { order: 1 } })
|
||||
}
|
||||
|
||||
let account: EmployeeAccount | undefined
|
||||
@ -45,10 +43,11 @@
|
||||
}, { limit: 1 })
|
||||
|
||||
|
||||
function selectSpecial (sp: SpecialNavModel): void {
|
||||
function selectCategory (sp: SettingsCategory): void {
|
||||
closePopup()
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[1] = setting.ids.SettingApp
|
||||
loc.path[2] = sp.id
|
||||
loc.path[2] = sp.name
|
||||
loc.path.length = 3
|
||||
navigate(loc)
|
||||
}
|
||||
@ -60,14 +59,14 @@
|
||||
navigate({ path: [login.component.LoginApp] })
|
||||
}
|
||||
|
||||
function filterItems (items: SpecialNavModel[]): SpecialNavModel[] {
|
||||
return items?.filter((p) => p.id !== 'profile' && p.id !== 'password')
|
||||
function filterItems (items: SettingsCategory[]): SettingsCategory[] {
|
||||
return items?.filter((p) => p.name !== 'profile' && p.name !== 'password')
|
||||
}
|
||||
|
||||
function editProfile (items: SpecialNavModel[] | undefined): void {
|
||||
const profile = items?.find((p) => p.id === 'profile')
|
||||
function editProfile (items: SettingsCategory[] | undefined): void {
|
||||
const profile = items?.find((p) => p.name === 'profile')
|
||||
if (profile === undefined) return
|
||||
selectSpecial(profile)
|
||||
selectCategory(profile)
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -88,10 +87,15 @@
|
||||
<div class="content">
|
||||
{#if items}
|
||||
{#each filterItems(items) as item }
|
||||
<div class="item" on:click={() => selectSpecial(item)}><Label label={item.label} /></div>
|
||||
<div class="item flex-row-center" on:click={() => selectCategory(item)}>
|
||||
<div class='mr-2'>
|
||||
<Icon icon={item.icon} size={'x-small'}/>
|
||||
</div>
|
||||
<Label label={item.label} />
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
<div class="item" on:click={signOut}><Label label={'Sign out'} /></div>
|
||||
<div class="item" on:click={signOut}><Label label={setting.string.Signout} /></div>
|
||||
</div>
|
||||
{/await}
|
||||
</div>
|
||||
|
@ -172,14 +172,14 @@
|
||||
<div class="panel-component">
|
||||
{#if currentApplication && currentApplication.component}
|
||||
<Component is={currentApplication.component} />
|
||||
{/if}
|
||||
|
||||
{#if ownSpecialComponent}
|
||||
<svelte:component this={ownSpecialComponent} model={navigatorModel} />
|
||||
{:else if specialComponent}
|
||||
<Component is={specialComponent} />
|
||||
{:else}
|
||||
<SpaceView {currentSpace} {currentView} {createItemDialog} />
|
||||
{#if ownSpecialComponent}
|
||||
<svelte:component this={ownSpecialComponent} model={navigatorModel} />
|
||||
{:else if specialComponent}
|
||||
<Component is={specialComponent} />
|
||||
{:else}
|
||||
<SpaceView {currentSpace} {currentView} {createItemDialog} />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<!-- <div class="aside"><Chat thread/></div> -->
|
||||
|
25
rush.json
25
rush.json
@ -940,6 +940,31 @@
|
||||
"packageName": "@anticrm/inventory-resources",
|
||||
"projectFolder": "plugins/inventory-resources",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/templates",
|
||||
"projectFolder": "plugins/templates",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/templates-assets",
|
||||
"projectFolder": "plugins/templates-assets",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/templates-resources",
|
||||
"projectFolder": "plugins/templates-resources",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/model-templates",
|
||||
"projectFolder": "models/templates",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/model-text-editor",
|
||||
"projectFolder": "models/text-editor",
|
||||
"shouldPublish": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user