Fix TSK-96 (#2052)

This commit is contained in:
Andrey Sobolev 2022-06-10 22:48:14 +07:00 committed by GitHub
parent 77ee575bbd
commit 546eac5dee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 206 additions and 120 deletions

View File

@ -35,10 +35,9 @@ import {
import attachment from '@anticrm/model-attachment' import attachment from '@anticrm/model-attachment'
import chunter from '@anticrm/model-chunter' import chunter from '@anticrm/model-chunter'
import core, { TAttachedDoc, TClass, TDoc, TSpace } from '@anticrm/model-core' import core, { TAttachedDoc, TClass, TDoc, TSpace } from '@anticrm/model-core'
import presentation from '@anticrm/model-presentation'
import view, { actionTemplates as viewTemplates, createAction, template } from '@anticrm/model-view' import view, { actionTemplates as viewTemplates, createAction, template } from '@anticrm/model-view'
import { IntlString } from '@anticrm/platform' import { IntlString } from '@anticrm/platform'
import { ViewAction } from '@anticrm/view' import tags from '@anticrm/tags'
import { import {
DOMAIN_STATE, DOMAIN_STATE,
DoneState, DoneState,
@ -60,7 +59,7 @@ import {
WonStateTemplate WonStateTemplate
} from '@anticrm/task' } from '@anticrm/task'
import { AnyComponent } from '@anticrm/ui' import { AnyComponent } from '@anticrm/ui'
import tags from '@anticrm/tags' import { ViewAction } from '@anticrm/view'
import task from './plugin' import task from './plugin'
export { createKanbanTemplate, createSequence, taskOperation } from './migration' export { createKanbanTemplate, createSequence, taskOperation } from './migration'
@ -501,17 +500,6 @@ export function createModel (builder: Builder): void {
target: task.class.TodoItem target: task.class.TodoItem
}) })
builder.createDoc(
presentation.class.ObjectSearchCategory,
core.space.Model,
{
icon: task.icon.Task,
label: task.string.SearchTask,
query: task.completion.IssueQuery
},
task.completion.IssueCategory
)
createAction( createAction(
builder, builder,
{ {

View File

@ -15,8 +15,6 @@
// //
import type { Ref, Space } from '@anticrm/core' import type { Ref, Space } from '@anticrm/core'
import { ObjectSearchCategory, ObjectSearchFactory } from '@anticrm/model-presentation'
import type { Resource } from '@anticrm/platform'
import { mergeIds } from '@anticrm/platform' import { mergeIds } from '@anticrm/platform'
import { TagCategory } from '@anticrm/tags' import { TagCategory } from '@anticrm/tags'
import { KanbanTemplate, taskId } from '@anticrm/task' import { KanbanTemplate, taskId } from '@anticrm/task'
@ -66,10 +64,6 @@ export default mergeIds(taskId, task, {
template: { template: {
DefaultProject: '' as Ref<KanbanTemplate> DefaultProject: '' as Ref<KanbanTemplate>
}, },
completion: {
IssueQuery: '' as Resource<ObjectSearchFactory>,
IssueCategory: '' as Ref<ObjectSearchCategory>
},
viewlet: { viewlet: {
TableIssue: '' as Ref<Viewlet> TableIssue: '' as Ref<Viewlet>
} }

View File

@ -51,6 +51,8 @@ import {
} from '@anticrm/tracker' } from '@anticrm/tracker'
import tracker from './plugin' import tracker from './plugin'
import presentation from '@anticrm/model-presentation'
export { trackerOperation } from './migration' export { trackerOperation } from './migration'
export { default } from './plugin' export { default } from './plugin'
@ -568,4 +570,15 @@ export function createModel (builder: Builder): void {
builder.mixin(tracker.class.Issue, core.class.Class, view.mixin.ClassFilters, { builder.mixin(tracker.class.Issue, core.class.Class, view.mixin.ClassFilters, {
filters: ['status', 'priority', 'project'] filters: ['status', 'priority', 'project']
}) })
builder.createDoc(
presentation.class.ObjectSearchCategory,
core.space.Model,
{
icon: tracker.icon.TrackerApplication,
label: tracker.string.SearchIssue,
query: tracker.completion.IssueQuery
},
tracker.completion.IssueCategory
)
} }

View File

@ -15,7 +15,8 @@
// //
import { Ref } from '@anticrm/core' import { Ref } from '@anticrm/core'
import { IntlString, mergeIds } from '@anticrm/platform' import { ObjectSearchCategory, ObjectSearchFactory } from '@anticrm/model-presentation'
import { IntlString, mergeIds, Resource } from '@anticrm/platform'
import { Team, trackerId } from '@anticrm/tracker' import { Team, trackerId } from '@anticrm/tracker'
import tracker from '@anticrm/tracker-resources/src/plugin' import tracker from '@anticrm/tracker-resources/src/plugin'
import type { AnyComponent } from '@anticrm/ui' import type { AnyComponent } from '@anticrm/ui'
@ -31,7 +32,8 @@ export default mergeIds(trackerId, tracker, {
GotoBacklog: '' as IntlString, GotoBacklog: '' as IntlString,
GotoBoard: '' as IntlString, GotoBoard: '' as IntlString,
GotoProjects: '' as IntlString, GotoProjects: '' as IntlString,
GotoTrackerApplication: '' as IntlString GotoTrackerApplication: '' as IntlString,
SearchIssue: '' as IntlString
}, },
team: { team: {
DefaultTeam: '' as Ref<Team> DefaultTeam: '' as Ref<Team>
@ -45,5 +47,9 @@ export default mergeIds(trackerId, tracker, {
}, },
viewlet: { viewlet: {
List: '' as Ref<ViewletDescriptor> List: '' as Ref<ViewletDescriptor>
},
completion: {
IssueQuery: '' as Resource<ObjectSearchFactory>,
IssueCategory: '' as Ref<ObjectSearchCategory>
} }
}) })

View File

@ -93,7 +93,9 @@ export class LiveQuery {
callback: (result: FindResult<T>) => void, callback: (result: FindResult<T>) => void,
options?: FindOptions<T> options?: FindOptions<T>
): boolean { ): boolean {
console.log(_class, query, callback, options)
if (!this.needUpdate(_class, query, callback, options)) { if (!this.needUpdate(_class, query, callback, options)) {
console.log('matched')
return false return false
} }
this.oldCallback = callback this.oldCallback = callback
@ -104,6 +106,10 @@ export class LiveQuery {
const unsub = liveQuery.query(_class, query, callback, options) const unsub = liveQuery.query(_class, query, callback, options)
this.unsubscribe = () => { this.unsubscribe = () => {
unsub() unsub()
this.oldCallback = undefined
this.oldClass = undefined
this.oldOptions = undefined
this.oldQuery = undefined
this.unsubscribe = () => {} this.unsubscribe = () => {}
} }
return true return true

View File

@ -170,7 +170,9 @@
selected = i selected = i
}} }}
> >
<svelte:component this={item.component} value={item.doc} {...item.componentProps ?? {}} /> <div class="ml-2 mt-1 mb-1">
<svelte:component this={item.component} value={item.doc} {...item.componentProps ?? {}} />
</div>
</div> </div>
{/each} {/each}
{#if !items.length} {#if !items.length}

View File

@ -29,6 +29,8 @@
personQuery.query(contact.class.Contact, { _id: object.contact }, (result) => { personQuery.query(contact.class.Contact, { _id: object.contact }, (result) => {
refContact = result[0] refContact = result[0]
}) })
} else {
personQuery.unsubscribe()
} }
let organization: Organization let organization: Organization
@ -37,6 +39,8 @@
orgQuery.query(contact.class.Organization, { _id: object.attachedTo as Ref<Organization> }, (result) => { orgQuery.query(contact.class.Organization, { _id: object.attachedTo as Ref<Organization> }, (result) => {
organization = result[0] organization = result[0]
}) })
} else {
orgQuery.unsubscribe()
} }
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()

View File

@ -34,7 +34,7 @@
</script> </script>
<div class="flex item"> <div class="flex item">
<Icon icon={recruit.icon.Application} size={'large'} /> <Icon icon={recruit.icon.Application} size={'medium'} />
<div class="ml-2"> <div class="ml-2">
{#if shortLabel}<Label label={shortLabel} />-{/if}{value.number} {#if shortLabel}<Label label={shortLabel} />-{/if}{value.number}
</div> </div>

View File

@ -31,6 +31,8 @@
templatesQ.query(task.class.KanbanTemplate, { space: folder._id as Ref<Doc> as Ref<Space> }, (result) => { templatesQ.query(task.class.KanbanTemplate, { space: folder._id as Ref<Doc> as Ref<Space> }, (result) => {
templates = result templates = result
}) })
} else {
templatesQ.unsubscribe()
} }
let selectedId: Ref<KanbanTemplate> | undefined let selectedId: Ref<KanbanTemplate> | undefined

View File

@ -54,6 +54,8 @@
} }
} }
) )
} else {
elementsQuery.unsubscribe()
} }
type TagElementInfo = { count: number; modifiedOn: number } type TagElementInfo = { count: number; modifiedOn: number }

View File

@ -62,8 +62,7 @@
"DoneStatesLost": "Done status / Lost", "DoneStatesLost": "Done status / Lost",
"AllStates": "All states", "AllStates": "All states",
"DoneStates": "Done states", "DoneStates": "Done states",
"States": "States", "States": "States",
"SearchTask": "Search for task...",
"NoDoneState": "Not done", "NoDoneState": "Not done",
"ManageStatusesWithin": "Manage application statuses within", "ManageStatusesWithin": "Manage application statuses within",
"ManageProjectStatues": "Manage project statues", "ManageProjectStatues": "Manage project statues",

View File

@ -63,7 +63,6 @@
"AllStates": "Все статусы", "AllStates": "Все статусы",
"DoneStates": "Завершенные статусы", "DoneStates": "Завершенные статусы",
"States": "Статусы", "States": "Статусы",
"SearchTask": "Поиск задачи...",
"NoDoneState": "Не завершено", "NoDoneState": "Не завершено",
"ManageStatusesWithin": "Управление статусами для", "ManageStatusesWithin": "Управление статусами для",
"ManageProjectStatues": "Управление статусами задачи", "ManageProjectStatues": "Управление статусами задачи",

View File

@ -30,6 +30,8 @@
wonStates = result.filter((x) => x._class === task.class.WonState) wonStates = result.filter((x) => x._class === task.class.WonState)
lostStates = result.filter((x) => x._class === task.class.LostState) lostStates = result.filter((x) => x._class === task.class.LostState)
}) })
} else {
doneStatesQ.unsubscribe()
} }
let hoveredDoneState: Ref<DoneState> | undefined let hoveredDoneState: Ref<DoneState> | undefined

View File

@ -45,6 +45,8 @@
}, },
{ limit: 1 } { limit: 1 }
) )
} else {
query.unsubscribe()
} }
</script> </script>

View File

@ -14,11 +14,10 @@
// limitations under the License. // limitations under the License.
// //
import { Class, Client, Ref } from '@anticrm/core' import { Resources } from '@anticrm/platform'
import { IntlString, Resources, translate } from '@anticrm/platform' import { SpaceWithStates } from '@anticrm/task'
import { ObjectSearchResult } from '@anticrm/presentation'
import { SpaceWithStates, Task } from '@anticrm/task'
import { showPopup } from '@anticrm/ui' import { showPopup } from '@anticrm/ui'
import AssignedTasks from './components/AssignedTasks.svelte'
import CreateProject from './components/CreateProject.svelte' import CreateProject from './components/CreateProject.svelte'
import EditIssue from './components/EditIssue.svelte' import EditIssue from './components/EditIssue.svelte'
import KanbanTemplateEditor from './components/kanban/KanbanTemplateEditor.svelte' import KanbanTemplateEditor from './components/kanban/KanbanTemplateEditor.svelte'
@ -32,59 +31,17 @@ import StateEditor from './components/state/StateEditor.svelte'
import StatePresenter from './components/state/StatePresenter.svelte' import StatePresenter from './components/state/StatePresenter.svelte'
import StatusTableView from './components/StatusTableView.svelte' import StatusTableView from './components/StatusTableView.svelte'
import TaskHeader from './components/TaskHeader.svelte' import TaskHeader from './components/TaskHeader.svelte'
import TaskItem from './components/TaskItem.svelte'
import TaskPresenter from './components/TaskPresenter.svelte' import TaskPresenter from './components/TaskPresenter.svelte'
import TemplatesIcon from './components/TemplatesIcon.svelte' import TemplatesIcon from './components/TemplatesIcon.svelte'
import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte' import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte'
import TodoItemsPopup from './components/todos/TodoItemsPopup.svelte' import TodoItemsPopup from './components/todos/TodoItemsPopup.svelte'
import Todos from './components/todos/Todos.svelte' import Todos from './components/todos/Todos.svelte'
import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte' import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte'
import AssignedTasks from './components/AssignedTasks.svelte'
import task from './plugin'
async function editStatuses (object: SpaceWithStates): Promise<void> { async function editStatuses (object: SpaceWithStates): Promise<void> {
showPopup(EditStatuses, { _id: object._id, spaceClass: object._class }, 'float') showPopup(EditStatuses, { _id: object._id, spaceClass: object._class }, 'float')
} }
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<Task>(_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 })
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 type StatesBarPosition = 'start' | 'middle' | 'end' | undefined export type StatesBarPosition = 'start' | 'middle' | 'end' | undefined
export default async (): Promise<Resources> => ({ export default async (): Promise<Resources> => ({
@ -111,8 +68,5 @@ export default async (): Promise<Resources> => ({
}, },
actionImpl: { actionImpl: {
EditStatuses: editStatuses EditStatuses: editStatuses
},
completion: {
IssueQuery: async (client: Client, query: string) => await queryTask(task.class.Issue, client, query)
} }
}) })

View File

@ -221,7 +221,6 @@ const task = plugin(taskId, {
Kanban: '' as IntlString, Kanban: '' as IntlString,
ApplicationLabelTask: '' as IntlString, ApplicationLabelTask: '' as IntlString,
Projects: '' as IntlString, Projects: '' as IntlString,
SearchTask: '' as IntlString,
ManageProjectStatues: '' as IntlString, ManageProjectStatues: '' as IntlString,
TodoItems: '' as IntlString TodoItems: '' as IntlString
}, },

View File

@ -139,7 +139,8 @@
"IncludeItemsThatMatch": "Include items that match", "IncludeItemsThatMatch": "Include items that match",
"AnyFilter": "any filter", "AnyFilter": "any filter",
"AllFilters": "all filters", "AllFilters": "all filters",
"NoDescription": "No description" "NoDescription": "No description",
"SearchIssue": "Search for task..."
}, },
"status": {} "status": {}
} }

View File

@ -89,7 +89,8 @@
"IncludeItemsThatMatch": "Включить элементы, которые соответствуют", "IncludeItemsThatMatch": "Включить элементы, которые соответствуют",
"AnyFilter": "любому фильтру", "AnyFilter": "любому фильтру",
"AllFilters": "всем фильтрам", "AllFilters": "всем фильтрам",
"NoDescription": "Нет описания" "NoDescription": "Нет описания",
"SearchIssue": "Поиск задачи..."
}, },
"status": {} "status": {}
} }

View File

@ -0,0 +1,38 @@
<!--
// 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 { WithLookup } from '@anticrm/core'
import type { Issue, Team } from '@anticrm/tracker'
import { Icon } from '@anticrm/ui'
import tracker from '../../plugin'
import { getIssueId } from '../../utils'
export let value: WithLookup<Issue>
$: title = getIssueId(value.$lookup?.space as Team, value)
</script>
<div class="flex item">
<Icon icon={tracker.icon.TrackerApplication} size={'medium'} />
<div class="ml-2">
{title} - {value.title}
</div>
</div>
<style lang="scss">
.item {
align-items: center;
}
</style>

View File

@ -33,6 +33,8 @@
$: if (!currentTeam) { $: if (!currentTeam) {
spaceQuery.query(tracker.class.Team, { _id: value.space }, (res) => ([currentTeam] = res)) spaceQuery.query(tracker.class.Team, { _id: value.space }, (res) => ([currentTeam] = res))
} else {
spaceQuery.unsubscribe()
} }
$: issueName = currentTeam && getIssueId(currentTeam, value) $: issueName = currentTeam && getIssueId(currentTeam, value)
</script> </script>

View File

@ -86,13 +86,16 @@
$: areSubIssuesLoading = !subIssues $: areSubIssuesLoading = !subIssues
$: parentIssue = issue.$lookup?.attachedTo ? (issue.$lookup?.attachedTo as Issue) : null $: parentIssue = issue.$lookup?.attachedTo ? (issue.$lookup?.attachedTo as Issue) : null
$: parentIssue && $: if (parentIssue) {
subIssuesQeury.query( subIssuesQeury.query(
tracker.class.Issue, tracker.class.Issue,
{ space: issue.space, attachedTo: parentIssue._id }, { space: issue.space, attachedTo: parentIssue._id },
(res) => (subIssues = res), (res) => (subIssues = res),
{ sort: { modifiedOn: SortingOrder.Descending } } { sort: { modifiedOn: SortingOrder.Descending } }
) )
} else {
subIssuesQeury.unsubscribe()
}
</script> </script>
{#if parentIssue} {#if parentIssue}

View File

@ -37,19 +37,25 @@
closePopup() closePopup()
projectId = loc.path[4] as Ref<Project> projectId = loc.path[4] as Ref<Project>
console.log('PROJECT SELECTED', projectId)
}) })
) )
const projectQuery = createQuery() const projectQuery = createQuery()
$: if (projectId !== undefined) { $: if (projectId !== undefined) {
console.log('call query for', projectId)
projectQuery.query(tracker.class.Project, { _id: projectId }, (result) => { projectQuery.query(tracker.class.Project, { _id: projectId }, (result) => {
;[project] = result project = result.shift()
console.log('recieve result for', projectId, project)
}) })
} else { } else {
projectQuery.unsubscribe()
project = undefined project = undefined
} }
</script> </script>
{projectId}
{JSON.stringify(project)}
{#if project} {#if project}
<EditProject {project} /> <EditProject {project} />
{:else} {:else}

View File

@ -13,47 +13,99 @@
// limitations under the License. // limitations under the License.
// //
import { Class, Client, Ref } from '@anticrm/core'
import { Resources } from '@anticrm/platform' import { Resources } from '@anticrm/platform'
import { ObjectSearchResult } from '@anticrm/presentation'
import NopeComponent from './components/NopeComponent.svelte' import { Issue, Team } from '@anticrm/tracker'
import Inbox from './components/inbox/Inbox.svelte'
import Active from './components/issues/Active.svelte' import Active from './components/issues/Active.svelte'
import AssigneePresenter from './components/issues/AssigneePresenter.svelte'
import Backlog from './components/issues/Backlog.svelte' import Backlog from './components/issues/Backlog.svelte'
import Board from './components/issues/Board.svelte' import Board from './components/issues/Board.svelte'
import Inbox from './components/inbox/Inbox.svelte'
import Issues from './components/issues/Issues.svelte'
import MyIssues from './components/myissues/MyIssues.svelte'
import Projects from './components/projects/Projects.svelte'
import ProjectPresenter from './components/projects/ProjectPresenter.svelte'
import ProjectTitlePresenter from './components/projects/ProjectTitlePresenter.svelte'
import Views from './components/views/Views.svelte'
import IssuePresenter from './components/issues/IssuePresenter.svelte'
import TitlePresenter from './components/issues/TitlePresenter.svelte'
import PriorityPresenter from './components/issues/PriorityPresenter.svelte'
import PriorityEditor from './components/issues/PriorityEditor.svelte'
import ProjectEditor from './components/projects/ProjectEditor.svelte'
import StatusPresenter from './components/issues/StatusPresenter.svelte'
import StatusEditor from './components/issues/StatusEditor.svelte'
import SetDueDateActionPopup from './components/SetDueDateActionPopup.svelte'
import SetParentIssueActionPopup from './components/SetParentIssueActionPopup.svelte'
import DueDatePresenter from './components/issues/DueDatePresenter.svelte' import DueDatePresenter from './components/issues/DueDatePresenter.svelte'
import AssigneePresenter from './components/issues/AssigneePresenter.svelte' import EditIssue from './components/issues/edit/EditIssue.svelte'
import IssueItem from './components/issues/IssueItem.svelte'
import IssuePresenter from './components/issues/IssuePresenter.svelte'
import IssuePreview from './components/issues/IssuePreview.svelte'
import Issues from './components/issues/Issues.svelte'
import IssuesView from './components/issues/IssuesView.svelte'
import ListView from './components/issues/ListView.svelte'
import ModificationDatePresenter from './components/issues/ModificationDatePresenter.svelte'
import PriorityEditor from './components/issues/PriorityEditor.svelte'
import PriorityPresenter from './components/issues/PriorityPresenter.svelte'
import StatusEditor from './components/issues/StatusEditor.svelte'
import StatusPresenter from './components/issues/StatusPresenter.svelte'
import TitlePresenter from './components/issues/TitlePresenter.svelte'
import ViewOptionsPopup from './components/issues/ViewOptionsPopup.svelte' import ViewOptionsPopup from './components/issues/ViewOptionsPopup.svelte'
import MyIssues from './components/myissues/MyIssues.svelte'
import NewIssueHeader from './components/NewIssueHeader.svelte'
import NopeComponent from './components/NopeComponent.svelte'
import EditProject from './components/projects/EditProject.svelte'
import IconPresenter from './components/projects/IconPresenter.svelte' import IconPresenter from './components/projects/IconPresenter.svelte'
import LeadPresenter from './components/projects/LeadPresenter.svelte' import LeadPresenter from './components/projects/LeadPresenter.svelte'
import TargetDatePresenter from './components/projects/TargetDatePresenter.svelte' import ProjectEditor from './components/projects/ProjectEditor.svelte'
import ProjectMembersPresenter from './components/projects/ProjectMembersPresenter.svelte' import ProjectMembersPresenter from './components/projects/ProjectMembersPresenter.svelte'
import ProjectStatusPresenter from './components/projects/ProjectStatusPresenter.svelte' import ProjectPresenter from './components/projects/ProjectPresenter.svelte'
import EditProject from './components/projects/EditProject.svelte' import Projects from './components/projects/Projects.svelte'
import ProjectStatusEditor from './components/projects/ProjectStatusEditor.svelte' import ProjectStatusEditor from './components/projects/ProjectStatusEditor.svelte'
import ProjectStatusPresenter from './components/projects/ProjectStatusPresenter.svelte'
import ProjectTitlePresenter from './components/projects/ProjectTitlePresenter.svelte'
import TargetDatePresenter from './components/projects/TargetDatePresenter.svelte'
import SetDueDateActionPopup from './components/SetDueDateActionPopup.svelte'
import SetParentIssueActionPopup from './components/SetParentIssueActionPopup.svelte'
import Views from './components/views/Views.svelte'
import tracker from './plugin'
import { getIssueId } from './utils'
import ModificationDatePresenter from './components/issues/ModificationDatePresenter.svelte' export async function queryIssue<D extends Issue> (
import EditIssue from './components/issues/edit/EditIssue.svelte' _class: Ref<Class<D>>,
import NewIssueHeader from './components/NewIssueHeader.svelte' client: Client,
import ListView from './components/issues/ListView.svelte' search: string
import IssuesView from './components/issues/IssuesView.svelte' ): Promise<ObjectSearchResult[]> {
import IssuePreview from './components/issues/IssuePreview.svelte' const teams = await client.findAll<Team>(tracker.class.Team, {})
const named = new Map(
(
await client.findAll<Issue>(
_class,
{ title: { $like: `%${search}%` } },
{
limit: 200,
lookup: { space: tracker.class.Team }
}
)
).map((e) => [e._id, e])
)
for (const currentTeam of teams) {
const nids: number[] = []
for (let n = 0; n < currentTeam.sequence; n++) {
const v = `${currentTeam.identifier}-${n}`
if (v.includes(search)) {
nids.push(n)
}
}
if (nids.length > 0) {
const numbered = await client.findAll<Issue>(
_class,
{ number: { $in: nids } },
{ limit: 200, lookup: { space: tracker.class.Team } }
)
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: getIssueId(e.$lookup?.space as Team, e),
icon: tracker.icon.TrackerApplication,
component: IssueItem
}))
}
export default async (): Promise<Resources> => ({ export default async (): Promise<Resources> => ({
component: { component: {
NopeComponent, NopeComponent,
@ -95,5 +147,8 @@ export default async (): Promise<Resources> => ({
}, },
function: { function: {
ProjectVisible: () => false ProjectVisible: () => false
},
completion: {
IssueQuery: async (client: Client, query: string) => await queryIssue(tracker.class.Issue, client, query)
} }
}) })

View File

@ -63,12 +63,14 @@
}) })
const query = createQuery() const query = createQuery()
$: _id && $: if (_id && _class) {
_class &&
query.query(_class, { _id }, (result) => { query.query(_class, { _id }, (result) => {
object = result[0] object = result[0]
realObjectClass = object._class realObjectClass = object._class
}) })
} else {
query.unsubscribe()
}
let keys: KeyedAttribute[] = [] let keys: KeyedAttribute[] = []
let collectionEditors: { key: KeyedAttribute; editor: AnyComponent }[] = [] let collectionEditors: { key: KeyedAttribute; editor: AnyComponent }[] = []

View File

@ -34,6 +34,7 @@
doc = r.shift() doc = r.shift()
}) })
} else { } else {
docQuery.unsubscribe()
doc = value doc = value
} }

View File

@ -29,7 +29,7 @@
let preference: ViewletPreference | undefined let preference: ViewletPreference | undefined
const preferenceQuery = createQuery() const preferenceQuery = createQuery()
$: viewlet && $: if (viewlet) {
preferenceQuery.query( preferenceQuery.query(
view.class.ViewletPreference, view.class.ViewletPreference,
{ {
@ -41,6 +41,9 @@
}, },
{ limit: 1 } { limit: 1 }
) )
} else {
preferenceQuery.unsubscribe()
}
const client = getClient() const client = getClient()
const hierarchy = client.getHierarchy() const hierarchy = client.getHierarchy()

View File

@ -3,11 +3,13 @@
"version": "1.0.0", "version": "1.0.0",
"license": "EPL-2.0", "license": "EPL-2.0",
"scripts": { "scripts": {
"build": "rm -rf ./dist && cross-env NODE_ENV=production webpack --stats-error-details && echo 'done'", "build": "echo 'disabled'",
"bundle": "cp -r ../../server/front/bundle.js .", "*build": "rm -rf ./dist && cross-env NODE_ENV=production webpack --stats-error-details && echo 'done'",
"docker:build": "docker build -t hardcoreeng/tracker-front .", "*bundle": "cp -r ../../server/front/bundle.js .",
"docker:staging": "../../common/scripts/docker_tag.sh hardcoreeng/tracker-front staging", "bundle": "echo 'disabled'",
"docker:push": "../../common/scripts/docker_tag.sh hardcoreeng/tracker-front", "*docker:build": "docker build -t hardcoreeng/tracker-front .",
"*docker:staging": "../../common/scripts/docker_tag.sh hardcoreeng/tracker-front staging",
"*docker:push": "../../common/scripts/docker_tag.sh hardcoreeng/tracker-front",
"analyze": "cross-env NODE_ENV=production webpack --json > stats.json", "analyze": "cross-env NODE_ENV=production webpack --json > stats.json",
"show": "webpack-bundle-analyzer stats.json dist", "show": "webpack-bundle-analyzer stats.json dist",
"dev": "cross-env CLIENT_TYPE=dev webpack serve", "dev": "cross-env CLIENT_TYPE=dev webpack serve",
@ -15,8 +17,8 @@
"start": "cross-env NODE_ENV=production webpack serve", "start": "cross-env NODE_ENV=production webpack serve",
"preformat-svelte": "prettier -w src/**/*.svelte", "preformat-svelte": "prettier -w src/**/*.svelte",
"lint": "", "lint": "",
"lint:fix": "yarn preformat-svelte && eslint --fix src", "lint:fix": "",
"deploy": "cp -p public/* dist && aws s3 sync dist s3://anticrm-platform --delete --acl public-read" "*deploy": "cp -p public/* dist && aws s3 sync dist s3://anticrm-platform --delete --acl public-read"
}, },
"devDependencies": { "devDependencies": {
"cross-env": "~7.0.3", "cross-env": "~7.0.3",