mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-12 20:57:45 +02:00
Configurable Back reference (#848)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Generated
+31
-8
@@ -55,6 +55,7 @@ specifiers:
|
||||
'@rush-temp/model-gmail': file:./projects/model-gmail.tgz
|
||||
'@rush-temp/model-inventory': file:./projects/model-inventory.tgz
|
||||
'@rush-temp/model-lead': file:./projects/model-lead.tgz
|
||||
'@rush-temp/model-presentation': file:./projects/model-presentation.tgz
|
||||
'@rush-temp/model-recruit': file:./projects/model-recruit.tgz
|
||||
'@rush-temp/model-rig': file:./projects/model-rig.tgz
|
||||
'@rush-temp/model-server-attachment': file:./projects/model-server-attachment.tgz
|
||||
@@ -239,6 +240,7 @@ dependencies:
|
||||
'@rush-temp/model-gmail': file:projects/model-gmail.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-inventory': file:projects/model-inventory.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-lead': file:projects/model-lead.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-presentation': file:projects/model-presentation.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-recruit': file:projects/model-recruit.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-rig': file:projects/model-rig.tgz_37f79b97d0d86442e45d380c86f520c5
|
||||
'@rush-temp/model-server-attachment': file:projects/model-server-attachment.tgz_typescript@4.5.4
|
||||
@@ -11634,7 +11636,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/model-all.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-Z4F3zvl3i5iZUuhvKo1+SlVy9Urq09lVL4XsyY1zAwk14Af42uf5CVbbubPiSuLt4SevW1StJ5c08y4vztbfQA==, tarball: file:projects/model-all.tgz}
|
||||
resolution: {integrity: sha512-xDbSAT10XpV9IMIWZmkZF1DKtDmPuh++4I5oxtxRHGrrdJ1h0J37nkAmZ6AayfWgqaCXG8EBn+SplvLw07HESg==, tarball: file:projects/model-all.tgz}
|
||||
id: file:projects/model-all.tgz
|
||||
name: '@rush-temp/model-all'
|
||||
version: 0.0.0
|
||||
@@ -11701,7 +11703,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/model-contact.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-GD5NmMEaz2KD79NdbNlQTbmuc98hxeV0cwV8xgRtCZnbeNrDw4h71yUik4vGNLsgha8ezy2oefrdi5aET1wbig==, tarball: file:projects/model-contact.tgz}
|
||||
resolution: {integrity: sha512-a2k6USkc9xrm3ba78A0pOps3X4Ox8A+uHm3cdNpfrSA8ihdfU9p6imeFr+ZotWF8YCcnwagz9sVHpT5dtmH4Mg==, tarball: file:projects/model-contact.tgz}
|
||||
id: file:projects/model-contact.tgz
|
||||
name: '@rush-temp/model-contact'
|
||||
version: 0.0.0
|
||||
@@ -11826,8 +11828,29 @@ packages:
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
file:projects/model-presentation.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-cBkfqfxIgaViuDI4bj0NDuVg1NnzoSjL2mxvRRRn1Dnqkq+2K00cKyx67Pil9dHwH636h2HEYKoM4VNsT3Os1w==, tarball: file:projects/model-presentation.tgz}
|
||||
id: file:projects/model-presentation.tgz
|
||||
name: '@rush-temp/model-presentation'
|
||||
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-recruit.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-wIeXWWUD1Lwg8R43hEvmJzZ/ooN4DWdqv1+2vPFDZU/1xKwlW7Gqu1hZM5qUUVHbLLgMOmHsHDscPfn7tB11UQ==, tarball: file:projects/model-recruit.tgz}
|
||||
resolution: {integrity: sha512-M2V190p42TMpwBagu8ts2iLvDu2hFprTiMX2i/KIwANipE9lJGHmjYlvh7HEGsdSYbeFavMuWdqoUNWjnCjy1Q==, tarball: file:projects/model-recruit.tgz}
|
||||
id: file:projects/model-recruit.tgz
|
||||
name: '@rush-temp/model-recruit'
|
||||
version: 0.0.0
|
||||
@@ -11951,7 +11974,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/model-task.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-+R3a/p9KvLJRF7CCbFwZer5TPDbBAjpTW85JDRrpV4sL2bEQIgtgtoYYwtd8dMyqCld1MToYesR9WYvwHmVGFw==, tarball: file:projects/model-task.tgz}
|
||||
resolution: {integrity: sha512-yIegyos933cu1NpvP/oFomGd8Yo9wKWjyoQyxNO26ERynPFdYIZ7yRKeiIpVp/P2T2xT3M9510GfdWJx6/MkgA==, tarball: file:projects/model-task.tgz}
|
||||
id: file:projects/model-task.tgz
|
||||
name: '@rush-temp/model-task'
|
||||
version: 0.0.0
|
||||
@@ -12229,7 +12252,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/prod.tgz_sass@1.45.0+typescript@4.5.4:
|
||||
resolution: {integrity: sha512-WxsSu4KtdtPTf1EJkHs/CJFDHiU0AgfGMmyOm66DFGc0cWOiJlgoCcw9TuCNaQPCBQ/ldbNYbfpj01N4iZFYuA==, tarball: file:projects/prod.tgz}
|
||||
resolution: {integrity: sha512-FWLkhyyIA2ZiXuydQap4fYlvfq02Q18A0fjVgVmy/7Wedebed2Xj6n2uQVjDVN50a5EP+5CutRcLAuxs7bI4Vw==, tarball: file:projects/prod.tgz}
|
||||
id: file:projects/prod.tgz
|
||||
name: '@rush-temp/prod'
|
||||
version: 0.0.0
|
||||
@@ -12495,7 +12518,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/server.tgz:
|
||||
resolution: {integrity: sha512-e8Oeh7z0NrGebPnTPZDsh4H6UUwDv2F4ywRw2o6GW7r3iXd1iK4nbxqs1bG7DvHy7kpY+jWk6tMpFSYJ+RXOrg==, tarball: file:projects/server.tgz}
|
||||
resolution: {integrity: sha512-5U67EYHkOoUqolvKMKSN1++52yfIzKPOIG2pmnbra2Ffcg9O/7UCat9eBIUx8U+n1998DnVm+c9H3yHadlOdsw==, tarball: file:projects/server.tgz}
|
||||
name: '@rush-temp/server'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
@@ -12723,7 +12746,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/text-editor.tgz_096c09b0b673a57c275d9767a12070b1:
|
||||
resolution: {integrity: sha512-Fg9TwM9Q/v+2QLbOwTuBAhjI0/4Lm34ksUW2R0PjuY0WTUGk/ZbKALm2HJAr+fQgjd8B1FXjcFXlidoOIWQ9jA==, tarball: file:projects/text-editor.tgz}
|
||||
resolution: {integrity: sha512-mHTzsgBUTd2d3Y8xW1y8GOTLU0r4IyOsF7RpV1N4GVwaqnCZSxuFdC/T7PqX33XYI0hD6q+0KNegRs+MzvOeeg==, tarball: file:projects/text-editor.tgz}
|
||||
id: file:projects/text-editor.tgz
|
||||
name: '@rush-temp/text-editor'
|
||||
version: 0.0.0
|
||||
@@ -12805,7 +12828,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/tool.tgz:
|
||||
resolution: {integrity: sha512-Zwy6rf7v5DtpINp3IaWvHYoEVdkaQMi2n837scjAUyUjp21wMQshZudzu/K00Nfi4vI/Z40Ue8hG6LrcrUHQzA==, tarball: file:projects/tool.tgz}
|
||||
resolution: {integrity: sha512-dfzDNJuguQfZyQh/Z9IkPneooJEK0O5kQcEnqOyPiJIvv/HPK2dNw2U97BrWhjylNqTMxDziWY2zkMXiUdEkTg==, tarball: file:projects/tool.tgz}
|
||||
name: '@rush-temp/tool'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"@anticrm/model-attachment": "~0.6.0",
|
||||
"@anticrm/model-gmail": "~0.6.0",
|
||||
"@anticrm/model-inventory": "~0.6.0",
|
||||
"@anticrm/model-presentation": "~0.6.0",
|
||||
"@anticrm/core": "~0.6.13"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import { createModel as attachmentModel } from '@anticrm/model-attachment'
|
||||
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 serverCoreModel } from '@anticrm/model-server-core'
|
||||
import { createModel as serverAttachmentModel } from '@anticrm/model-server-attachment'
|
||||
@@ -52,6 +53,7 @@ telegramModel(builder)
|
||||
leadModel(builder)
|
||||
gmailModel(builder)
|
||||
inventoryModel(builder)
|
||||
presentationModel(builder)
|
||||
|
||||
serverCoreModel(builder)
|
||||
serverAttachmentModel(builder)
|
||||
|
||||
@@ -143,7 +143,7 @@ export function createModel (builder: Builder): void {
|
||||
component: chunter.activity.TxBacklinkCreate,
|
||||
label: chunter.string.MentionedIn,
|
||||
labelComponent: chunter.activity.TxBacklinkReference,
|
||||
display: 'content',
|
||||
display: 'emphasized',
|
||||
editable: false,
|
||||
hideOnRemove: true
|
||||
}, chunter.ids.TxCommentCreate)
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"@anticrm/model-workbench": "~0.6.0",
|
||||
"@anticrm/model-attachment": "~0.6.0",
|
||||
"@anticrm/model-view": "~0.6.0",
|
||||
"@anticrm/model-presentation": "~0.6.0",
|
||||
"@anticrm/model": "~0.6.0",
|
||||
"@anticrm/core": "~0.6.11",
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
|
||||
@@ -34,6 +34,7 @@ import workbench from '@anticrm/model-workbench'
|
||||
import view from '@anticrm/model-view'
|
||||
import attachment from '@anticrm/model-attachment'
|
||||
import { ids as contact } from './plugin'
|
||||
import presentation from '@anticrm/model-presentation'
|
||||
|
||||
export const DOMAIN_CONTACT = 'contact' as Domain
|
||||
|
||||
@@ -234,6 +235,24 @@ export function createModel (builder: Builder): void {
|
||||
builder.mixin(contact.class.Contact, core.class.Class, view.mixin.AttributePresenter, {
|
||||
presenter: contact.component.ContactPresenter
|
||||
})
|
||||
|
||||
builder.createDoc(presentation.class.ObjectSearchCategory, core.space.Model, {
|
||||
icon: contact.icon.Person,
|
||||
label: contact.string.SearchEmployee,
|
||||
query: contact.completion.EmployeeQuery
|
||||
}, contact.completion.EmployeeCategory)
|
||||
|
||||
builder.createDoc(presentation.class.ObjectSearchCategory, core.space.Model, {
|
||||
icon: contact.icon.Person,
|
||||
label: contact.string.SearchPerson,
|
||||
query: contact.completion.PersonQuery
|
||||
}, contact.completion.PersonCategory)
|
||||
|
||||
builder.createDoc(presentation.class.ObjectSearchCategory, core.space.Model, {
|
||||
icon: contact.icon.Company,
|
||||
label: contact.string.SearchOrganization,
|
||||
query: contact.completion.OrganizationQuery
|
||||
}, contact.completion.OrganizationCategory)
|
||||
}
|
||||
|
||||
export { contact as default }
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { IntlString, mergeIds } from '@anticrm/platform'
|
||||
import { IntlString, mergeIds, Resource } from '@anticrm/platform'
|
||||
import type { Ref, Class, Type } from '@anticrm/core'
|
||||
import contact, { contactId } from '@anticrm/contact'
|
||||
import type { Channel } from '@anticrm/contact'
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
import {} from '@anticrm/core'
|
||||
import { Application } from '@anticrm/workbench'
|
||||
import { ObjectSearchCategory, ObjectSearchFactory } from '@anticrm/model-presentation'
|
||||
|
||||
export const ids = mergeIds(contactId, contact, {
|
||||
app: {
|
||||
@@ -45,9 +46,20 @@ export const ids = mergeIds(contactId, contact, {
|
||||
Persons: '' as IntlString,
|
||||
Contacts: '' as IntlString,
|
||||
CreatePersons: '' as IntlString,
|
||||
CreateOrganizations: '' as IntlString
|
||||
CreateOrganizations: '' as IntlString,
|
||||
SearchEmployee: '' as IntlString,
|
||||
SearchPerson: '' as IntlString,
|
||||
SearchOrganization: '' as IntlString
|
||||
},
|
||||
class: {
|
||||
TypeChannel: '' as Ref<Class<Type<Channel>>>
|
||||
},
|
||||
completion: {
|
||||
PersonQuery: '' as Resource<ObjectSearchFactory>,
|
||||
EmployeeQuery: '' as Resource<ObjectSearchFactory>,
|
||||
OrganizationQuery: '' as Resource<ObjectSearchFactory>,
|
||||
EmployeeCategory: '' as Ref<ObjectSearchCategory>,
|
||||
PersonCategory: '' as Ref<ObjectSearchCategory>,
|
||||
OrganizationCategory: '' as Ref<ObjectSearchCategory>
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@anticrm/model-rig/profiles/default/config/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -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"
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@anticrm/model-presentation",
|
||||
"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/presentation": "~0.6.0",
|
||||
"@anticrm/model-core": "~0.6.0"
|
||||
}
|
||||
}
|
||||
@@ -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 { ObjectSearchCategory, ObjectSearchFactory } from '@anticrm/presentation/src/types'
|
||||
import presentation from './plugin'
|
||||
|
||||
export { default } from './plugin'
|
||||
export { ObjectSearchCategory, ObjectSearchFactory }
|
||||
|
||||
@Model(presentation.class.ObjectSearchCategory, core.class.Doc, DOMAIN_MODEL)
|
||||
export class TObjectSearchCategory extends TDoc implements ObjectSearchCategory {
|
||||
label!: IntlString
|
||||
icon!: Asset
|
||||
|
||||
// Query for documents with pattern
|
||||
query!: Resource<ObjectSearchFactory>
|
||||
}
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.createModel(
|
||||
TObjectSearchCategory
|
||||
)
|
||||
}
|
||||
@@ -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 presentation, { presentationId } from '@anticrm/presentation/src/plugin'
|
||||
|
||||
export default mergeIds(presentationId, presentation, {
|
||||
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./node_modules/@anticrm/model-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@
|
||||
"@anticrm/view": "~0.6.0",
|
||||
"@anticrm/task": "~0.6.0",
|
||||
"@anticrm/model-task": "~0.6.0",
|
||||
"@anticrm/workbench": "~0.6.1"
|
||||
"@anticrm/workbench": "~0.6.1",
|
||||
"@anticrm/model-presentation": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import workbench from '@anticrm/model-workbench'
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import { Applicant, Candidate, Candidates, Vacancy } from '@anticrm/recruit'
|
||||
import recruit from './plugin'
|
||||
import presentation from '@anticrm/model-presentation'
|
||||
|
||||
@Model(recruit.class.Vacancy, task.class.SpaceWithStates)
|
||||
@UX(recruit.string.Vacancy, recruit.icon.Vacancy)
|
||||
@@ -281,6 +282,12 @@ export function createModel (builder: Builder): void {
|
||||
},
|
||||
recruit.space.VacancyTemplates
|
||||
)
|
||||
|
||||
builder.createDoc(presentation.class.ObjectSearchCategory, core.space.Model, {
|
||||
icon: recruit.icon.Application,
|
||||
label: recruit.string.SearchApplication,
|
||||
query: recruit.completion.ApplicationQuery
|
||||
}, recruit.completion.ApplicationCategory)
|
||||
}
|
||||
|
||||
export { default } from './plugin'
|
||||
|
||||
@@ -22,6 +22,7 @@ import { KanbanTemplate } from '@anticrm/task'
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
import type { Action } from '@anticrm/view'
|
||||
import { Application } from '@anticrm/workbench'
|
||||
import { ObjectSearchFactory, ObjectSearchCategory } from '@anticrm/model-presentation'
|
||||
|
||||
export default mergeIds(recruitId, recruit, {
|
||||
app: {
|
||||
@@ -36,7 +37,8 @@ export default mergeIds(recruitId, recruit, {
|
||||
string: {
|
||||
RecruitApplication: '' as IntlString,
|
||||
Vacancies: '' as IntlString,
|
||||
CandidatePools: '' as IntlString
|
||||
CandidatePools: '' as IntlString,
|
||||
SearchApplication: '' as IntlString
|
||||
},
|
||||
validator: {
|
||||
ApplicantValidator: '' as Resource<<T extends Doc>(doc: T, client: Client) => Promise<Status>>
|
||||
@@ -56,5 +58,9 @@ export default mergeIds(recruitId, recruit, {
|
||||
},
|
||||
template: {
|
||||
DefaultVacancy: '' as Ref<KanbanTemplate>
|
||||
},
|
||||
completion: {
|
||||
ApplicationQuery: '' as Resource<ObjectSearchFactory>,
|
||||
ApplicationCategory: '' as Ref<ObjectSearchCategory>
|
||||
}
|
||||
})
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"@anticrm/task-resources": "~0.6.0",
|
||||
"@anticrm/model-chunter": "~0.6.0",
|
||||
"@anticrm/workbench": "~0.6.1",
|
||||
"@anticrm/view": "~0.6.0"
|
||||
"@anticrm/view": "~0.6.0",
|
||||
"@anticrm/model-presentation": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
+17
-29
@@ -14,53 +14,38 @@
|
||||
//
|
||||
|
||||
// To help typescript locate view plugin properly
|
||||
import type { ActionTarget } from '@anticrm/view'
|
||||
|
||||
import attachment from '@anticrm/model-attachment'
|
||||
import type { Employee } from '@anticrm/contact'
|
||||
import contact from '@anticrm/contact'
|
||||
import { Arr, Class, Doc, Domain, DOMAIN_MODEL, FindOptions, Ref, Space, Timestamp } from '@anticrm/core'
|
||||
import {
|
||||
Builder,
|
||||
Collection,
|
||||
Implements,
|
||||
Collection, Hidden, Implements,
|
||||
Mixin,
|
||||
Model,
|
||||
Prop,
|
||||
Hidden,
|
||||
TypeBoolean,
|
||||
Prop, TypeBoolean,
|
||||
TypeDate,
|
||||
TypeRef,
|
||||
TypeString,
|
||||
UX
|
||||
} from '@anticrm/model'
|
||||
import attachment from '@anticrm/model-attachment'
|
||||
import chunter from '@anticrm/model-chunter'
|
||||
import core, { TAttachedDoc, TClass, TDoc, TSpace } from '@anticrm/model-core'
|
||||
import presentation from '@anticrm/model-presentation'
|
||||
import view from '@anticrm/model-view'
|
||||
import workbench from '@anticrm/model-workbench'
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import type {
|
||||
Kanban,
|
||||
KanbanCard,
|
||||
Project,
|
||||
State,
|
||||
Issue,
|
||||
Sequence,
|
||||
DoneState,
|
||||
WonState,
|
||||
LostState,
|
||||
KanbanTemplateSpace,
|
||||
StateTemplate,
|
||||
DoneStateTemplate,
|
||||
WonStateTemplate,
|
||||
LostStateTemplate,
|
||||
KanbanTemplate,
|
||||
Task,
|
||||
TodoItem
|
||||
DoneState, DoneStateTemplate, Issue, Kanban,
|
||||
KanbanCard, KanbanTemplate, KanbanTemplateSpace, LostState, LostStateTemplate, Project, Sequence, State, StateTemplate, Task,
|
||||
TodoItem, WonState, WonStateTemplate
|
||||
} from '@anticrm/task'
|
||||
import task from './plugin'
|
||||
import { AnyComponent } from '@anticrm/ui'
|
||||
import type { ActionTarget } from '@anticrm/view'
|
||||
import task from './plugin'
|
||||
|
||||
export { createDeps, createKanbanTemplate } from './creation'
|
||||
export { taskOperation } from './migration'
|
||||
export { default } from './plugin'
|
||||
|
||||
export const DOMAIN_TASK = 'task' as Domain
|
||||
@@ -519,7 +504,10 @@ export function createModel (builder: Builder): void {
|
||||
done: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export { taskOperation } from './migration'
|
||||
export { createDeps, createKanbanTemplate } from './creation'
|
||||
builder.createDoc(presentation.class.ObjectSearchCategory, core.space.Model, {
|
||||
icon: task.icon.Task,
|
||||
label: task.string.SearchTask,
|
||||
query: task.completion.IssueQuery
|
||||
}, task.completion.IssueCategory)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import task from '@anticrm/task-resources/src/plugin'
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
import { Application } from '@anticrm/workbench'
|
||||
import type { Action } from '@anticrm/view'
|
||||
import { ObjectSearchCategory, ObjectSearchFactory } from '@anticrm/model-presentation'
|
||||
|
||||
export default mergeIds(taskId, task, {
|
||||
app: {
|
||||
@@ -85,12 +86,17 @@ export default mergeIds(taskId, task, {
|
||||
MarkAsUndone: '' as IntlString,
|
||||
Kanban: '' as IntlString,
|
||||
ApplicationLabelTask: '' as IntlString,
|
||||
Projects: '' as IntlString
|
||||
Projects: '' as IntlString,
|
||||
SearchTask: '' as IntlString
|
||||
},
|
||||
space: {
|
||||
TasksPublic: '' as Ref<Space>
|
||||
},
|
||||
template: {
|
||||
DefaultProject: '' as Ref<KanbanTemplate>
|
||||
},
|
||||
completion: {
|
||||
IssueQuery: '' as Resource<ObjectSearchFactory>,
|
||||
IssueCategory: '' as Ref<ObjectSearchCategory>
|
||||
}
|
||||
})
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
import { addStringsLoader } from '@anticrm/platform'
|
||||
import { presentationId } from './plugin'
|
||||
|
||||
export { presentationId }
|
||||
export * from './utils'
|
||||
export * from './attributes'
|
||||
export * from './types'
|
||||
|
||||
export { default as UserBox } from './components/UserBox.svelte'
|
||||
export { default as UserInfo } from './components/UserInfo.svelte'
|
||||
|
||||
@@ -1,21 +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 { Class, Ref } from '@anticrm/core'
|
||||
import type { IntlString, Plugin } from '@anticrm/platform'
|
||||
import { plugin } from '@anticrm/platform'
|
||||
import { ObjectSearchCategory } from '.'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -23,6 +25,9 @@ import { plugin } from '@anticrm/platform'
|
||||
export const presentationId = 'presentation' as Plugin
|
||||
|
||||
export default plugin(presentationId, {
|
||||
class: {
|
||||
ObjectSearchCategory: '' as Ref<Class<ObjectSearchCategory>>
|
||||
},
|
||||
string: {
|
||||
Create: '' as IntlString,
|
||||
Cancel: '' as IntlString,
|
||||
@@ -34,4 +39,4 @@ export default plugin(presentationId, {
|
||||
Deselect: '' as IntlString,
|
||||
AddSocialLinks: '' as IntlString
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Client, Doc } from '@anticrm/core'
|
||||
import { Asset, IntlString, Resource } from '@anticrm/platform'
|
||||
import { AnySvelteComponent } from '@anticrm/ui'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface ObjectSearchResult {
|
||||
doc: Doc
|
||||
component?: AnySvelteComponent
|
||||
componentProps?: any
|
||||
title: string
|
||||
icon?: Asset | AnySvelteComponent
|
||||
iconProps?: any
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type ObjectSearchFactory = (client: Client, query: string) => Promise<ObjectSearchResult[]>
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface ObjectSearchCategory extends Doc {
|
||||
label: IntlString
|
||||
icon: Asset
|
||||
|
||||
// Query for documents with pattern
|
||||
query: Resource<ObjectSearchFactory>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"string": {
|
||||
"Suggested": "SUGGESTED"
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@
|
||||
"svelte": "^3.37.0",
|
||||
"@anticrm/presentation": "~0.6.2",
|
||||
"@anticrm/contact": "~0.6.2",
|
||||
"@anticrm/platform": "~0.6.5",
|
||||
"@anticrm/core": "~0.6.11",
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
"@tiptap/core": "~2.0.0-beta.93",
|
||||
|
||||
@@ -14,19 +14,29 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { formatName, Person } from '@anticrm/contact'
|
||||
import { UserInfo } from '@anticrm/presentation'
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let items: Person[]
|
||||
export let query: string
|
||||
import { getResource, translate } from '@anticrm/platform'
|
||||
import { getClient, ObjectSearchCategory, ObjectSearchResult } from '@anticrm/presentation'
|
||||
import { ActionIcon, EditWithIcon, IconSearch, Label } from '@anticrm/ui'
|
||||
import plugin from '../plugin'
|
||||
|
||||
export let query: string = ''
|
||||
export let items: ObjectSearchResult[]
|
||||
export let clientRect: () => ClientRect
|
||||
export let command: (props: any) => void
|
||||
export let close: () => void
|
||||
export let categories: ObjectSearchCategory[]
|
||||
export let category: ObjectSearchCategory
|
||||
|
||||
export let onCategory: (cat: ObjectSearchCategory) => void
|
||||
|
||||
const client = getClient()
|
||||
let popup: HTMLDivElement
|
||||
let selected = 0
|
||||
|
||||
function dispatchItem (item: ObjectSearchResult): void {
|
||||
command({ id: item.doc._id, label: item.title, objectclass: item.doc._class })
|
||||
}
|
||||
|
||||
export function onKeyDown (ev: KeyboardEvent) {
|
||||
if (ev.key === 'ArrowDown') {
|
||||
if (selected < items.length - 1) selected++
|
||||
@@ -36,19 +46,24 @@ import { createEventDispatcher } from 'svelte';
|
||||
if (selected > 0) selected--
|
||||
return true
|
||||
}
|
||||
if (ev.key === 'Tab') {
|
||||
const pos = categories.indexOf(category)
|
||||
category = categories[(pos + 1) % categories.length]
|
||||
return true
|
||||
}
|
||||
if (ev.key === 'Enter') {
|
||||
const person = items[selected]
|
||||
if (person) {
|
||||
command({ id: person._id, label: formatName(person.name), objectclass: person._class })
|
||||
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 true
|
||||
// }
|
||||
if (ev.key === 'Esc') {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -56,15 +71,32 @@ import { createEventDispatcher } from 'svelte';
|
||||
console.log('done')
|
||||
}
|
||||
|
||||
function updateStyle (popup: HTMLDivElement): void {
|
||||
const x = clientRect().left
|
||||
const height = popup.getBoundingClientRect().height
|
||||
const y = clientRect().top - height - 16
|
||||
style = `left: ${x}px; top: ${y}px;`
|
||||
}
|
||||
|
||||
let style = 'visibility: hidden'
|
||||
$: {
|
||||
if (popup) {
|
||||
const x = clientRect().left
|
||||
const height = popup.getBoundingClientRect().height
|
||||
const y = clientRect().top - height - 16
|
||||
style = `left: ${x}px; top: ${y}px;`
|
||||
$: if (popup) {
|
||||
updateStyle(popup)
|
||||
}
|
||||
|
||||
async function updateItems (category: ObjectSearchCategory, query: string): Promise<void> {
|
||||
const f = await getResource(category.query)
|
||||
items = await f(client, query)
|
||||
if (selected > items.length) {
|
||||
selected = 0
|
||||
}
|
||||
}
|
||||
$: updateItems(category, query)
|
||||
|
||||
let placeholder = ''
|
||||
|
||||
$: translate(category.label, {}).then((v) => {
|
||||
placeholder = v
|
||||
})
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -74,15 +106,29 @@ import { createEventDispatcher } from 'svelte';
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
<div bind:this={popup} class="completion" {style}>
|
||||
<div class="caption">Contacts</div>
|
||||
<div class="scroll">
|
||||
<div bind:this={popup} class="completion" {style} on:keydown={onKeyDown}>
|
||||
<div class='category-container'>
|
||||
{#each categories as c}
|
||||
<div class='category-selector' class:selected={category.label === c.label}>
|
||||
<ActionIcon label={c.label} icon={c.icon} size={'medium'} action={() => {
|
||||
category = c
|
||||
onCategory(c)
|
||||
updateItems(c, query)
|
||||
} }/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div class='mt-4 mb-4'>
|
||||
<EditWithIcon icon={IconSearch} bind:value={query} on:input={() => updateItems(category, query) } placeholder={placeholder} />
|
||||
</div>
|
||||
<Label label={plugin.string.Suggested}/>
|
||||
<div class="scroll mt-2">
|
||||
{#each items as item, i}
|
||||
<div
|
||||
class="item"
|
||||
class:selected={i === selected}
|
||||
on:click={() => {
|
||||
command({ id: item._id, label: formatName(item.name), objectclass: item._class })
|
||||
dispatchItem(item)
|
||||
}}
|
||||
on:focus={() => {
|
||||
selected = i
|
||||
@@ -91,7 +137,7 @@ import { createEventDispatcher } from 'svelte';
|
||||
selected = i
|
||||
}}
|
||||
>
|
||||
<UserInfo size={'medium'} value={item} />
|
||||
<svelte:component this={item.component} value={item.doc} {...item.componentProps ?? {}} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -115,6 +161,8 @@ import { createEventDispatcher } from 'svelte';
|
||||
.completion {
|
||||
position: absolute;
|
||||
z-index: 2010;
|
||||
min-width: 300px;
|
||||
height: 332px;
|
||||
padding: 16px;
|
||||
background-color: var(--theme-button-bg-hovered);
|
||||
border: 1px solid var(--theme-bg-accent-hover);
|
||||
@@ -129,12 +177,22 @@ import { createEventDispatcher } from 'svelte';
|
||||
color: var(--theme-content-trans-color);
|
||||
}
|
||||
.scroll {
|
||||
max-height: 200px;
|
||||
max-height: calc(300px - 128px);
|
||||
display: grid;
|
||||
grid-auto-flow: row;
|
||||
gap: 12px;
|
||||
height: calc(100% - 71px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.category-container {
|
||||
display: flex;
|
||||
.category-selector {
|
||||
margin-right: 1rem;
|
||||
opacity: 0.7;
|
||||
&.selected {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,26 +12,89 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { getResource } from '@anticrm/platform'
|
||||
import presentation, { getClient, ObjectSearchCategory, ObjectSearchFactory } from '@anticrm/presentation'
|
||||
import { AnyExtension } from '@tiptap/core'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import Send from './icons/Send.svelte'
|
||||
import { Completion } from '../Completion'
|
||||
import Attach from './icons/Attach.svelte'
|
||||
import Emoji from './icons/Emoji.svelte'
|
||||
import GIF from './icons/GIF.svelte'
|
||||
import Send from './icons/Send.svelte'
|
||||
import TextStyle from './icons/TextStyle.svelte'
|
||||
|
||||
import MentionList from './MentionList.svelte'
|
||||
import { SvelteRenderer } from './SvelteRenderer'
|
||||
import TextEditor from './TextEditor.svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
export let content: string = ''
|
||||
export let showSend = true
|
||||
const client = getClient()
|
||||
|
||||
let textEditor: TextEditor
|
||||
|
||||
export let categories: ObjectSearchCategory[] = []
|
||||
|
||||
client.findAll(presentation.class.ObjectSearchCategory, {}).then((r) => {
|
||||
categories = r
|
||||
})
|
||||
|
||||
|
||||
// Current selected category
|
||||
let category: ObjectSearchCategory | undefined = categories[0]
|
||||
|
||||
$: if (categories.length > 0 && category === undefined) {
|
||||
category = categories[0]
|
||||
}
|
||||
|
||||
export function submit (): void {
|
||||
textEditor.submit()
|
||||
}
|
||||
|
||||
const editorExtensions: AnyExtension[] = [
|
||||
Completion.configure({
|
||||
HTMLAttributes: {
|
||||
class: 'reference'
|
||||
},
|
||||
suggestion: {
|
||||
items: async (query: { query: string }) => {
|
||||
if (category !== undefined) {
|
||||
const f = await getResource(category.query)
|
||||
return (await f(client, query.query))
|
||||
}
|
||||
return []
|
||||
},
|
||||
render: () => {
|
||||
let component: any
|
||||
|
||||
return {
|
||||
onStart: (props:any) => {
|
||||
component = new SvelteRenderer(MentionList, {
|
||||
...props,
|
||||
close: () => { component.destroy() },
|
||||
categories,
|
||||
category,
|
||||
onCategory: (cat: ObjectSearchCategory) => {
|
||||
category = cat
|
||||
}
|
||||
})
|
||||
},
|
||||
onUpdate (props:any) {
|
||||
component.updateProps(props)
|
||||
},
|
||||
onKeyDown (props:any) {
|
||||
return component.onKeyDown(props)
|
||||
},
|
||||
onExit () {
|
||||
component.destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
]
|
||||
</script>
|
||||
|
||||
<div class="ref-container">
|
||||
@@ -43,7 +106,7 @@
|
||||
content = ''
|
||||
textEditor.clear()
|
||||
}
|
||||
}/>
|
||||
} extensions={editorExtensions} />
|
||||
</div>
|
||||
{#if showSend}
|
||||
<button class="sendButton" on:click={submit}><div class="icon"><Send/></div></button>
|
||||
|
||||
@@ -15,122 +15,84 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { AnyExtension, Editor, Extension } from '@tiptap/core'
|
||||
import Highlight from '@tiptap/extension-highlight'
|
||||
import Link from '@tiptap/extension-link'
|
||||
// import Typography from '@tiptap/extension-typography'
|
||||
import Placeholder from '@tiptap/extension-placeholder'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
|
||||
|
||||
import { onMount, onDestroy, createEventDispatcher } from 'svelte'
|
||||
import { Editor, Extension } from '@tiptap/core'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Highlight from '@tiptap/extension-highlight'
|
||||
import Link from '@tiptap/extension-link'
|
||||
// import Typography from '@tiptap/extension-typography'
|
||||
import Placeholder from '@tiptap/extension-placeholder'
|
||||
// import Mention from '@tiptap/extension-mention'
|
||||
import { Completion } from '../Completion'
|
||||
export let content: string = ''
|
||||
export let placeholder: string = 'Type something...'
|
||||
export let extensions: AnyExtension[] = []
|
||||
|
||||
import MentionList from './MentionList.svelte'
|
||||
import { SvelteRenderer } from './SvelteRenderer'
|
||||
let element: HTMLElement
|
||||
let editor: Editor
|
||||
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
import contact from '@anticrm/contact'
|
||||
export function submit (): void {
|
||||
content = editor.getHTML()
|
||||
dispatch('content', content)
|
||||
}
|
||||
|
||||
export let content: string = ''
|
||||
export let placeholder: string = 'Type something...'
|
||||
export function clear (): void {
|
||||
content = ''
|
||||
editor.commands.clearContent(false)
|
||||
}
|
||||
|
||||
let element: HTMLElement
|
||||
let editor: Editor
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
|
||||
export function submit (): void {
|
||||
content = editor.getHTML()
|
||||
dispatch('content', content)
|
||||
}
|
||||
|
||||
export function clear (): void {
|
||||
content = ''
|
||||
editor.commands.clearContent(false)
|
||||
}
|
||||
|
||||
const Handle = Extension.create({
|
||||
addKeyboardShortcuts () {
|
||||
return {
|
||||
'Shift-Enter': () => {
|
||||
const res = this.editor.commands.splitListItem('listItem')
|
||||
if (!res) {
|
||||
this.editor.commands.first(({ commands }) => [
|
||||
() => commands.newlineInCode(),
|
||||
() => commands.createParagraphNear(),
|
||||
() => commands.liftEmptyBlock(),
|
||||
() => commands.splitBlock()
|
||||
])
|
||||
const Handle = Extension.create({
|
||||
addKeyboardShortcuts () {
|
||||
return {
|
||||
'Shift-Enter': () => {
|
||||
const res = this.editor.commands.splitListItem('listItem')
|
||||
if (!res) {
|
||||
this.editor.commands.first(({ commands }) => [
|
||||
() => commands.newlineInCode(),
|
||||
() => commands.createParagraphNear(),
|
||||
() => commands.liftEmptyBlock(),
|
||||
() => commands.splitBlock()
|
||||
])
|
||||
}
|
||||
return true
|
||||
},
|
||||
Enter: () => {
|
||||
submit()
|
||||
return true
|
||||
}
|
||||
return true
|
||||
},
|
||||
Enter: () => {
|
||||
submit()
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
editor = new Editor({
|
||||
element,
|
||||
content: content,
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Highlight,
|
||||
Link,
|
||||
Handle, // order important
|
||||
// Typography, // we need to disable 1/2 -> ½ rule (https://github.com/hcengineering/anticrm/issues/345)
|
||||
Placeholder.configure({ placeholder: placeholder }),
|
||||
Completion.configure({
|
||||
HTMLAttributes: {
|
||||
class: 'reference'
|
||||
},
|
||||
suggestion: {
|
||||
items: async (query: { query: string }) => {
|
||||
const persons = await client.findAll(contact.class.Person, { name: { $like: `%${query.query}%` } }, { limit: 200 })
|
||||
return persons.filter(person => person.name.includes(query.query))
|
||||
},
|
||||
render: () => {
|
||||
let component: any
|
||||
onMount(() => {
|
||||
editor = new Editor({
|
||||
element,
|
||||
content: content,
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Highlight,
|
||||
Link,
|
||||
Handle, // order important
|
||||
// Typography, // we need to disable 1/2 -> ½ rule (https://github.com/hcengineering/anticrm/issues/345)
|
||||
Placeholder.configure({ placeholder: placeholder }),
|
||||
...extensions
|
||||
],
|
||||
onTransaction: () => {
|
||||
// force re-render so `editor.isActive` works as expected
|
||||
editor = editor
|
||||
},
|
||||
onBlur: () => {
|
||||
dispatch('blur')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
onStart: (props:any) => {
|
||||
component = new SvelteRenderer(MentionList, { ...props, close: () => { component.destroy() } })
|
||||
},
|
||||
onUpdate (props:any) {
|
||||
component.updateProps(props)
|
||||
},
|
||||
onKeyDown (props:any) {
|
||||
return component.onKeyDown(props)
|
||||
},
|
||||
onExit () {
|
||||
component.destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
],
|
||||
onTransaction: () => {
|
||||
// force re-render so `editor.isActive` works as expected
|
||||
editor = editor
|
||||
},
|
||||
onBlur: () => {
|
||||
dispatch('blur')
|
||||
onDestroy(() => {
|
||||
if (editor) {
|
||||
editor.destroy()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
if (editor) {
|
||||
editor.destroy()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div style="width: 100%" bind:this={element}/>
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
//
|
||||
// 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 { default as TextEditor } from './components/TextEditor.svelte'
|
||||
//
|
||||
export { default as ReferenceInput } from './components/ReferenceInput.svelte'
|
||||
export { default as TextEditor } from './components/TextEditor.svelte'
|
||||
|
||||
export * from '@anticrm/presentation/src/types'
|
||||
|
||||
addStringsLoader(textEditorId, async (lang: string) => {
|
||||
return await import(`../lang/${lang}.json`)
|
||||
})
|
||||
|
||||
export { default } from './plugin'
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
// Copyright © 2021 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { IntlString, Plugin, plugin } from '@anticrm/platform'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const textEditorId = 'text-editor' as Plugin
|
||||
|
||||
export default plugin(textEditorId, {
|
||||
string: {
|
||||
Suggested: '' as IntlString
|
||||
}
|
||||
})
|
||||
@@ -18,8 +18,7 @@
|
||||
import type { TxViewlet } from '@anticrm/activity'
|
||||
import activity from '@anticrm/activity'
|
||||
import contact, { EmployeeAccount, formatName } from '@anticrm/contact'
|
||||
import { AttachedDoc, Doc, Ref, TxCreateDoc } from '@anticrm/core'
|
||||
import core from '@anticrm/core'
|
||||
import { Doc, Ref } from '@anticrm/core'
|
||||
import { Asset, getResource } from '@anticrm/platform'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import {
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
"PersonsFolder": "Persons folder",
|
||||
"MakePrivate": "Make private",
|
||||
"MakePrivateDescription": "Only members can see it",
|
||||
"Create": "Contact"
|
||||
"Create": "Contact",
|
||||
"SearchEmployee": "Search for employee...",
|
||||
"SearchPerson": "Search for person...",
|
||||
"SearchOrganization": "Search for organization..."
|
||||
}
|
||||
}
|
||||
@@ -14,22 +14,37 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import PersonPresenter from './components/PersonPresenter.svelte'
|
||||
import ContactPresenter from './components/ContactPresenter.svelte'
|
||||
import OrganizationPresenter from './components/OrganizationPresenter.svelte'
|
||||
import ChannelsPresenter from './components/ChannelsPresenter.svelte'
|
||||
import CreatePerson from './components/CreatePerson.svelte'
|
||||
import CreateOrganization from './components/CreateOrganization.svelte'
|
||||
import EditPerson from './components/EditPerson.svelte'
|
||||
import EditOrganization from './components/EditOrganization.svelte'
|
||||
import CreatePersons from './components/CreatePersons.svelte'
|
||||
import CreateOrganizations from './components/CreateOrganizations.svelte'
|
||||
import SocialEditor from './components/SocialEditor.svelte'
|
||||
import Contacts from './components/Contacts.svelte'
|
||||
import { Contact, formatName } from '@anticrm/contact'
|
||||
import { Class, Client, Ref } from '@anticrm/core'
|
||||
import { Resources } from '@anticrm/platform'
|
||||
import { Avatar, ObjectSearchResult, UserInfo } from '@anticrm/presentation'
|
||||
import ChannelsPresenter from './components/ChannelsPresenter.svelte'
|
||||
import ContactPresenter from './components/ContactPresenter.svelte'
|
||||
import Contacts from './components/Contacts.svelte'
|
||||
import CreateOrganization from './components/CreateOrganization.svelte'
|
||||
import CreateOrganizations from './components/CreateOrganizations.svelte'
|
||||
import CreatePerson from './components/CreatePerson.svelte'
|
||||
import CreatePersons from './components/CreatePersons.svelte'
|
||||
import EditOrganization from './components/EditOrganization.svelte'
|
||||
import EditPerson from './components/EditPerson.svelte'
|
||||
import OrganizationPresenter from './components/OrganizationPresenter.svelte'
|
||||
import PersonPresenter from './components/PersonPresenter.svelte'
|
||||
import SocialEditor from './components/SocialEditor.svelte'
|
||||
import contact from './plugin'
|
||||
|
||||
export { ContactPresenter }
|
||||
|
||||
async function queryContact (_class: Ref<Class<Contact>>, client: Client, search: string): Promise<ObjectSearchResult[]> {
|
||||
return (await client.findAll(_class, { name: { $like: `%${search}%` } }, { limit: 200 })).map(e => ({
|
||||
doc: e,
|
||||
title: formatName(e.name),
|
||||
icon: Avatar,
|
||||
iconProps: { size: 'x-small', avatar: e.avatar },
|
||||
component: UserInfo,
|
||||
componentProps: { size: 'x-small' }
|
||||
}))
|
||||
}
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
ContactPresenter,
|
||||
@@ -44,5 +59,10 @@ export default async (): Promise<Resources> => ({
|
||||
CreateOrganizations,
|
||||
SocialEditor,
|
||||
Contacts
|
||||
},
|
||||
completion: {
|
||||
EmployeeQuery: async (client: Client, query: string) => await queryContact(contact.class.Employee, client, query),
|
||||
PersonQuery: async (client: Client, query: string) => await queryContact(contact.class.Person, client, query),
|
||||
OrganizationQuery: async (client: Client, query: string) => await queryContact(contact.class.Organization, client, query)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -14,9 +14,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { IntlString, mergeIds } from '@anticrm/platform'
|
||||
|
||||
import contact, { contactId } from '@anticrm/contact'
|
||||
import { IntlString, mergeIds } from '@anticrm/platform'
|
||||
|
||||
export default mergeIds(contactId, contact, {
|
||||
string: {
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
"Delete": "Delete",
|
||||
"WorkLocationPreferences": "Work location preferences",
|
||||
"Onsite": "Onsite",
|
||||
"Remote": "Remote"
|
||||
"Remote": "Remote",
|
||||
"SearchApplication": "Search for application..."
|
||||
},
|
||||
"status": {
|
||||
"CandidateRequired": "Please select candidate",
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
// Copyright © 2021 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { formatName, Person } from '@anticrm/contact'
|
||||
import { Ref } from '@anticrm/core'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import type { Applicant } from '@anticrm/recruit'
|
||||
import { Icon } from '@anticrm/ui'
|
||||
import recruit from '../plugin'
|
||||
|
||||
export let value: Applicant
|
||||
|
||||
const client = getClient()
|
||||
const shortLabel = client.getHierarchy().getClass(value._class).shortLabel?.toUpperCase()
|
||||
|
||||
let person: Person| undefined
|
||||
|
||||
$: client.findOne(contact.class.Person, { _id: value.attachedTo as Ref<Person> }).then(p => {
|
||||
person = p
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class='flex item'>
|
||||
<Icon icon={recruit.icon.Application} size={'large'} />
|
||||
<div class='ml-2'>
|
||||
{shortLabel}-{value.number}
|
||||
</div>
|
||||
{#if person}
|
||||
<div class='ml-1'>{formatName(person.name)}</div>
|
||||
{/if}
|
||||
</div>
|
||||
<style lang="scss">
|
||||
.item {
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -14,7 +14,7 @@
|
||||
//
|
||||
|
||||
import type { Client, Doc } from '@anticrm/core'
|
||||
import { OK, Resources, Severity, Status } from '@anticrm/platform'
|
||||
import { IntlString, OK, Resources, Severity, Status, translate } from '@anticrm/platform'
|
||||
import { Applicant } from '@anticrm/recruit'
|
||||
import { showPopup } from '@anticrm/ui'
|
||||
import ApplicationPresenter from './components/ApplicationPresenter.svelte'
|
||||
@@ -29,6 +29,9 @@ import EditVacancy from './components/EditVacancy.svelte'
|
||||
import KanbanCard from './components/KanbanCard.svelte'
|
||||
import TemplatesIcon from './components/TemplatesIcon.svelte'
|
||||
import recruit from './plugin'
|
||||
import { ObjectSearchResult } from '@anticrm/presentation'
|
||||
import task from '@anticrm/task'
|
||||
import ApplicationItem from './components/ApplicationItem.svelte'
|
||||
|
||||
async function createApplication (object: Doc): Promise<void> {
|
||||
showPopup(CreateApplication, { candidate: object._id, preserveCandidate: true })
|
||||
@@ -51,6 +54,40 @@ export async function applicantValidator (applicant: Applicant, client: Client):
|
||||
return OK
|
||||
}
|
||||
|
||||
export async function queryApplication (client: Client, search: string): Promise<ObjectSearchResult[]> {
|
||||
const _class = recruit.class.Applicant
|
||||
const cl = client.getHierarchy().getClass(_class)
|
||||
const shortLabel = (await translate(cl.shortLabel ?? '' as IntlString, {})).toUpperCase()
|
||||
|
||||
// Check number pattern
|
||||
|
||||
const sequence = (await client.findOne(task.class.Sequence, { attachedTo: _class }))?.sequence ?? 0
|
||||
|
||||
const named = new Map((await client.findAll(_class, { $search: search }, { limit: 200 })).map(e => [e._id, e]))
|
||||
const nids: number[] = []
|
||||
if (sequence > 0) {
|
||||
for (let n = 0; n < sequence; n++) {
|
||||
const v = `${n}`
|
||||
if (v.includes(search)) {
|
||||
nids.push(n)
|
||||
}
|
||||
}
|
||||
const numbered = await client.findAll<Applicant>(_class, { number: { $in: nids } }, { limit: 200 })
|
||||
for (const d of numbered) {
|
||||
if (!named.has(d._id)) {
|
||||
named.set(d._id, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(named.values()).map(e => ({
|
||||
doc: e,
|
||||
title: `${shortLabel}-${e.number}`,
|
||||
icon: task.icon.Task,
|
||||
component: ApplicationItem
|
||||
}))
|
||||
}
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
actionImpl: {
|
||||
CreateApplication: createApplication
|
||||
@@ -70,5 +107,8 @@ export default async (): Promise<Resources> => ({
|
||||
Applications,
|
||||
Candidates,
|
||||
CreateCandidate
|
||||
},
|
||||
completion: {
|
||||
ApplicationQuery: async (client: Client, query: string) => await queryApplication(client, query)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"AllStates": "All states",
|
||||
"DoneStates": "Done states",
|
||||
"States": "States",
|
||||
"ChooseAColor": "Choose a color"
|
||||
"ChooseAColor": "Choose a color",
|
||||
"SearchTask": "Search for task..."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<!--
|
||||
// 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 { getClient } from '@anticrm/presentation'
|
||||
import type { Issue, Task } from '@anticrm/task'
|
||||
import { Icon } from '@anticrm/ui'
|
||||
import task from '../plugin'
|
||||
|
||||
export let value: Task
|
||||
|
||||
const client = getClient()
|
||||
const shortLabel = client.getHierarchy().getClass(value._class).shortLabel?.toUpperCase()
|
||||
|
||||
let name: string | undefined = undefined
|
||||
|
||||
$: if (client.getHierarchy().isDerived(value._class, task.class.Issue)) {
|
||||
name = (value as Issue).name
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class='flex item'>
|
||||
<Icon icon={task.icon.Task} size={'large'} />
|
||||
<div class='ml-2'>
|
||||
{shortLabel}-{value.number}
|
||||
</div>
|
||||
{#if name}
|
||||
<div class='ml-1'>{name}</div>
|
||||
{/if}
|
||||
</div>
|
||||
<style lang="scss">
|
||||
.item {
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -14,33 +14,31 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Resources } from '@anticrm/platform'
|
||||
|
||||
import CreateTask from './components/CreateTask.svelte'
|
||||
import CreateProject from './components/CreateProject.svelte'
|
||||
import TaskPresenter from './components/TaskPresenter.svelte'
|
||||
import KanbanCard from './components/KanbanCard.svelte'
|
||||
import TemplatesIcon from './components/TemplatesIcon.svelte'
|
||||
import EditIssue from './components/EditIssue.svelte'
|
||||
import { Doc } from '@anticrm/core'
|
||||
import { Class, Client, Doc, Ref } from '@anticrm/core'
|
||||
import { IntlString, Resources, translate } from '@anticrm/platform'
|
||||
import { getClient, MessageBox, ObjectSearchResult } from '@anticrm/presentation'
|
||||
import task, { SpaceWithStates, Task, TodoItem } from '@anticrm/task'
|
||||
import { showPopup } from '@anticrm/ui'
|
||||
import { getClient, MessageBox } from '@anticrm/presentation'
|
||||
|
||||
import TaskItem from './components/TaskItem.svelte'
|
||||
import CreateProject from './components/CreateProject.svelte'
|
||||
import CreateTask from './components/CreateTask.svelte'
|
||||
import EditIssue from './components/EditIssue.svelte'
|
||||
import KanbanView from './components/kanban/KanbanView.svelte'
|
||||
import StateEditor from './components/state/StateEditor.svelte'
|
||||
import StatePresenter from './components/state/StatePresenter.svelte'
|
||||
import KanbanCard from './components/KanbanCard.svelte'
|
||||
import DoneStatePresenter from './components/state/DoneStatePresenter.svelte'
|
||||
import EditStatuses from './components/state/EditStatuses.svelte'
|
||||
import { SpaceWithStates, TodoItem } from '@anticrm/task'
|
||||
import Todos from './components/todos/Todos.svelte'
|
||||
import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte'
|
||||
import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte'
|
||||
import StateEditor from './components/state/StateEditor.svelte'
|
||||
import StatePresenter from './components/state/StatePresenter.svelte'
|
||||
import StatusTableView from './components/StatusTableView.svelte'
|
||||
import TaskHeader from './components/TaskHeader.svelte'
|
||||
import TaskPresenter from './components/TaskPresenter.svelte'
|
||||
import TemplatesIcon from './components/TemplatesIcon.svelte'
|
||||
import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte'
|
||||
import Todos from './components/todos/Todos.svelte'
|
||||
import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte'
|
||||
|
||||
export { default as KanbanTemplateEditor } from './components/kanban/KanbanTemplateEditor.svelte'
|
||||
export { default as KanbanTemplateSelector } from './components/kanban/KanbanTemplateSelector.svelte'
|
||||
|
||||
export { default as Tasks } from './components/Tasks.svelte'
|
||||
|
||||
async function createTask (object: Doc): Promise<void> {
|
||||
@@ -93,6 +91,39 @@ async function UnarchiveSpace (object: SpaceWithStates): Promise<void> {
|
||||
)
|
||||
}
|
||||
|
||||
export async function queryTask<D extends Task> (_class: Ref<Class<D>>, client: Client, search: string): Promise<ObjectSearchResult[]> {
|
||||
const cl = client.getHierarchy().getClass(_class)
|
||||
const shortLabel = (await translate(cl.shortLabel ?? '' as IntlString, {})).toUpperCase()
|
||||
|
||||
// Check number pattern
|
||||
|
||||
const sequence = (await client.findOne(task.class.Sequence, { attachedTo: _class }))?.sequence ?? 0
|
||||
|
||||
const named = new Map((await client.findAll(_class, { name: { $like: `%${search}%` } }, { limit: 200 })).map(e => [e._id, e]))
|
||||
const nids: number[] = []
|
||||
if (sequence > 0) {
|
||||
for (let n = 0; n < sequence; n++) {
|
||||
const v = `${n}`
|
||||
if (v.includes(search)) {
|
||||
nids.push(n)
|
||||
}
|
||||
}
|
||||
const numbered = await client.findAll<Task>(_class, { number: { $in: nids } }, { limit: 200 }) as D[]
|
||||
for (const d of numbered) {
|
||||
if (!named.has(d._id)) {
|
||||
named.set(d._id, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(named.values()).map(e => ({
|
||||
doc: e,
|
||||
title: `${shortLabel}-${e.number}`,
|
||||
icon: task.icon.Task,
|
||||
component: TaskItem
|
||||
}))
|
||||
}
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
CreateTask,
|
||||
@@ -118,5 +149,8 @@ export default async (): Promise<Resources> => ({
|
||||
TodoItemMarkUnDone: async (obj: TodoItem) => await toggleDone(false, obj),
|
||||
ArchiveSpace,
|
||||
UnarchiveSpace
|
||||
},
|
||||
completion: {
|
||||
IssueQuery: async (client: Client, query: string) => await queryTask(task.class.Issue, client, query)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -101,8 +101,6 @@ export interface Project extends SpaceWithStates {}
|
||||
* @public
|
||||
*/
|
||||
export interface Issue extends Task {
|
||||
number: number // Sequence number
|
||||
|
||||
name: string
|
||||
description: string
|
||||
|
||||
|
||||
@@ -536,6 +536,11 @@
|
||||
"projectFolder": "packages/presentation",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/model-presentation",
|
||||
"projectFolder": "models/presentation",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/client",
|
||||
"projectFolder": "plugins/client",
|
||||
|
||||
@@ -185,7 +185,7 @@ class TServerStorage implements ServerStorage {
|
||||
): Promise<FindResult<T>> {
|
||||
return await ctx.with('find-all', {}, (ctx) => {
|
||||
const domain = this.hierarchy.getDomain(clazz)
|
||||
if (query.$search !== undefined && query.$search.length > 0) {
|
||||
if (query.$search !== undefined) {
|
||||
return ctx.with('full-text-find-all', {}, (ctx) => this.fulltext.findAll(ctx, clazz, query, options))
|
||||
}
|
||||
return ctx.with('db-find-all', { _class: clazz, domain }, () =>
|
||||
|
||||
Reference in New Issue
Block a user