mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-30 04:05:40 +00:00
Update window title (#2138)
Signed-off-by: Dvinyanin Alexandr <dvinyanin.alexandr@gmail.com>
This commit is contained in:
parent
32d2b6ed69
commit
6c3070c85d
@ -409,6 +409,10 @@ export function createModel (builder: Builder): void {
|
|||||||
presenter: tracker.component.IssuePreview
|
presenter: tracker.component.IssuePreview
|
||||||
})
|
})
|
||||||
|
|
||||||
|
builder.mixin(tracker.class.Issue, core.class.Class, view.mixin.ObjectTitle, {
|
||||||
|
titleProvider: tracker.function.getIssueTitle
|
||||||
|
})
|
||||||
|
|
||||||
builder.mixin(tracker.class.TypeIssuePriority, core.class.Class, view.mixin.AttributePresenter, {
|
builder.mixin(tracker.class.TypeIssuePriority, core.class.Class, view.mixin.AttributePresenter, {
|
||||||
presenter: tracker.component.PriorityPresenter
|
presenter: tracker.component.PriorityPresenter
|
||||||
})
|
})
|
||||||
|
@ -40,6 +40,7 @@ import type {
|
|||||||
ObjectEditor,
|
ObjectEditor,
|
||||||
ObjectEditorHeader,
|
ObjectEditorHeader,
|
||||||
ObjectFactory,
|
ObjectFactory,
|
||||||
|
ObjectTitle,
|
||||||
ObjectValidator,
|
ObjectValidator,
|
||||||
PreviewPresenter,
|
PreviewPresenter,
|
||||||
SpaceHeader,
|
SpaceHeader,
|
||||||
@ -158,6 +159,11 @@ export class TObjectFactory extends TClass implements ObjectFactory {
|
|||||||
component!: AnyComponent
|
component!: AnyComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mixin(view.mixin.ObjectTitle, core.class.Class)
|
||||||
|
export class TObjectTitle extends TClass implements ObjectTitle {
|
||||||
|
titleProvider!: Resource<<T extends Doc>(client: Client, ref: Ref<T>) => Promise<string>>
|
||||||
|
}
|
||||||
|
|
||||||
@Model(view.class.ViewletPreference, preference.class.Preference)
|
@Model(view.class.ViewletPreference, preference.class.Preference)
|
||||||
export class TViewletPreference extends TPreference implements ViewletPreference {
|
export class TViewletPreference extends TPreference implements ViewletPreference {
|
||||||
attachedTo!: Ref<Viewlet>
|
attachedTo!: Ref<Viewlet>
|
||||||
@ -276,6 +282,7 @@ export function createModel (builder: Builder): void {
|
|||||||
TActionCategory,
|
TActionCategory,
|
||||||
TObjectValidator,
|
TObjectValidator,
|
||||||
TObjectFactory,
|
TObjectFactory,
|
||||||
|
TObjectTitle,
|
||||||
TObjectEditorHeader,
|
TObjectEditorHeader,
|
||||||
THTMLPresenter,
|
THTMLPresenter,
|
||||||
TSpaceHeader,
|
TSpaceHeader,
|
||||||
|
@ -56,7 +56,7 @@ import SetParentIssueActionPopup from './components/SetParentIssueActionPopup.sv
|
|||||||
import Views from './components/views/Views.svelte'
|
import Views from './components/views/Views.svelte'
|
||||||
import KanbanView from './components/issues/KanbanView.svelte'
|
import KanbanView from './components/issues/KanbanView.svelte'
|
||||||
import tracker from './plugin'
|
import tracker from './plugin'
|
||||||
import { getIssueId } from './utils'
|
import { getIssueId, getIssueTitle } from './utils'
|
||||||
|
|
||||||
export async function queryIssue<D extends Issue> (
|
export async function queryIssue<D extends Issue> (
|
||||||
_class: Ref<Class<D>>,
|
_class: Ref<Class<D>>,
|
||||||
@ -148,5 +148,8 @@ export default async (): Promise<Resources> => ({
|
|||||||
},
|
},
|
||||||
completion: {
|
completion: {
|
||||||
IssueQuery: async (client: Client, query: string) => await queryIssue(tracker.class.Issue, client, query)
|
IssueQuery: async (client: Client, query: string) => await queryIssue(tracker.class.Issue, client, query)
|
||||||
|
},
|
||||||
|
function: {
|
||||||
|
getIssueTitle
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -12,10 +12,11 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
import type { IntlString } from '@anticrm/platform'
|
import type { IntlString, Resource } from '@anticrm/platform'
|
||||||
import { mergeIds } from '@anticrm/platform'
|
import { mergeIds } from '@anticrm/platform'
|
||||||
import tracker, { trackerId } from '../../tracker/lib'
|
import tracker, { trackerId } from '../../tracker/lib'
|
||||||
import { AnyComponent } from '@anticrm/ui'
|
import { AnyComponent } from '@anticrm/ui'
|
||||||
|
import { Client, Doc, Ref } from '@anticrm/core'
|
||||||
|
|
||||||
export default mergeIds(trackerId, tracker, {
|
export default mergeIds(trackerId, tracker, {
|
||||||
string: {
|
string: {
|
||||||
@ -209,5 +210,8 @@ export default mergeIds(trackerId, tracker, {
|
|||||||
Roadmap: '' as AnyComponent,
|
Roadmap: '' as AnyComponent,
|
||||||
TeamProjects: '' as AnyComponent,
|
TeamProjects: '' as AnyComponent,
|
||||||
IssuePreview: '' as AnyComponent
|
IssuePreview: '' as AnyComponent
|
||||||
|
},
|
||||||
|
function: {
|
||||||
|
getIssueTitle: '' as Resource<(client: Client, ref: Ref<Doc>) => Promise<string>>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import contact, { Employee, formatName } from '@anticrm/contact'
|
import contact, { Employee, formatName } from '@anticrm/contact'
|
||||||
import { DocumentQuery, Ref, SortingOrder, TxOperations } from '@anticrm/core'
|
import { Doc, DocumentQuery, Ref, SortingOrder, TxOperations } from '@anticrm/core'
|
||||||
import { Asset, IntlString, translate } from '@anticrm/platform'
|
import { Asset, IntlString, translate } from '@anticrm/platform'
|
||||||
import {
|
import {
|
||||||
IssuePriority,
|
IssuePriority,
|
||||||
@ -504,3 +504,13 @@ export async function getKanbanStatuses (
|
|||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getIssueTitle (client: TxOperations, ref: Ref<Doc>): Promise<string> {
|
||||||
|
const issue = await client.findOne(
|
||||||
|
tracker.class.Issue,
|
||||||
|
{ _id: ref as Ref<Issue> },
|
||||||
|
{ lookup: { space: tracker.class.Team } }
|
||||||
|
)
|
||||||
|
if (issue?.$lookup?.space === undefined) throw new Error(`Issue Team not found, _id: ${ref}`)
|
||||||
|
return getIssueId(issue.$lookup.space, issue)
|
||||||
|
}
|
||||||
|
@ -154,6 +154,13 @@ export interface ObjectValidator extends Class<Doc> {
|
|||||||
validator: Resource<<T extends Doc>(doc: T, client: Client) => Promise<Status>>
|
validator: Resource<<T extends Doc>(doc: T, client: Client) => Promise<Status>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface ObjectTitle extends Class<Doc> {
|
||||||
|
titleProvider: Resource<<T extends Doc>(client: Client, ref: Ref<T>) => Promise<string>>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@ -384,6 +391,7 @@ const view = plugin(viewId, {
|
|||||||
ObjectEditorHeader: '' as Ref<Mixin<ObjectEditorHeader>>,
|
ObjectEditorHeader: '' as Ref<Mixin<ObjectEditorHeader>>,
|
||||||
ObjectValidator: '' as Ref<Mixin<ObjectValidator>>,
|
ObjectValidator: '' as Ref<Mixin<ObjectValidator>>,
|
||||||
ObjectFactory: '' as Ref<Mixin<ObjectFactory>>,
|
ObjectFactory: '' as Ref<Mixin<ObjectFactory>>,
|
||||||
|
ObjectTitle: '' as Ref<Mixin<ObjectTitle>>,
|
||||||
SpaceHeader: '' as Ref<Mixin<SpaceHeader>>,
|
SpaceHeader: '' as Ref<Mixin<SpaceHeader>>,
|
||||||
SpaceName: '' as Ref<Mixin<SpaceName>>,
|
SpaceName: '' as Ref<Mixin<SpaceName>>,
|
||||||
IgnoreActions: '' as Ref<Mixin<IgnoreActions>>,
|
IgnoreActions: '' as Ref<Mixin<IgnoreActions>>,
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import calendar from '@anticrm/calendar'
|
import calendar from '@anticrm/calendar'
|
||||||
import contact, { Employee, EmployeeAccount } from '@anticrm/contact'
|
import contact, { Employee, EmployeeAccount } from '@anticrm/contact'
|
||||||
import core, { Client, getCurrentAccount, Ref, Space } from '@anticrm/core'
|
import core, { Class, Client, Doc, getCurrentAccount, Ref, Space } from '@anticrm/core'
|
||||||
import notification, { NotificationStatus } from '@anticrm/notification'
|
import notification, { NotificationStatus } from '@anticrm/notification'
|
||||||
import { NotificationClientImpl } from '@anticrm/notification-resources'
|
import { NotificationClientImpl } from '@anticrm/notification-resources'
|
||||||
import { getMetadata, IntlString } from '@anticrm/platform'
|
import { getMetadata, getResource, IntlString } from '@anticrm/platform'
|
||||||
import { Avatar, createQuery, setClient } from '@anticrm/presentation'
|
import { Avatar, createQuery, setClient } from '@anticrm/presentation'
|
||||||
import {
|
import {
|
||||||
AnyComponent,
|
AnyComponent,
|
||||||
@ -26,6 +26,7 @@
|
|||||||
closeTooltip,
|
closeTooltip,
|
||||||
Component,
|
Component,
|
||||||
DatePickerPopup,
|
DatePickerPopup,
|
||||||
|
fetchMetadataLocalStorage,
|
||||||
getCurrentLocation,
|
getCurrentLocation,
|
||||||
location,
|
location,
|
||||||
Location,
|
Location,
|
||||||
@ -35,6 +36,8 @@
|
|||||||
showPopup,
|
showPopup,
|
||||||
TooltipInstance
|
TooltipInstance
|
||||||
} from '@anticrm/ui'
|
} from '@anticrm/ui'
|
||||||
|
import login from '@anticrm/login'
|
||||||
|
import view from '@anticrm/view'
|
||||||
import { ActionContext, ActionHandler } from '@anticrm/view-resources'
|
import { ActionContext, ActionHandler } from '@anticrm/view-resources'
|
||||||
import type { Application, NavigatorModel, SpecialNavModel, ViewConfiguration } from '@anticrm/workbench'
|
import type { Application, NavigatorModel, SpecialNavModel, ViewConfiguration } from '@anticrm/workbench'
|
||||||
import { onDestroy, tick } from 'svelte'
|
import { onDestroy, tick } from 'svelte'
|
||||||
@ -125,9 +128,33 @@
|
|||||||
closePopup()
|
closePopup()
|
||||||
|
|
||||||
await syncLoc(loc)
|
await syncLoc(loc)
|
||||||
|
await updateWindowTitle(loc)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async function updateWindowTitle (loc: Location) {
|
||||||
|
const title = (await getWindowTitle(loc)) ?? getMetadata(workbench.metadata.PlatformTitle) ?? 'Platform'
|
||||||
|
const ws = fetchMetadataLocalStorage(login.metadata.CurrentWorkspace)
|
||||||
|
document.title = ws == null ? title : `${ws} - ${title}`
|
||||||
|
}
|
||||||
|
async function getWindowTitle (loc: Location) {
|
||||||
|
if (loc.fragment == null) return
|
||||||
|
const hierarchy = client.getHierarchy()
|
||||||
|
const [, _id, _class] = decodeURIComponent(loc.fragment).split('|')
|
||||||
|
if (_class == null) return
|
||||||
|
|
||||||
|
const clazz = hierarchy.getClass(_class as Ref<Class<Doc>>)
|
||||||
|
if (!hierarchy.hasMixin(clazz, view.mixin.ObjectTitle)) return
|
||||||
|
|
||||||
|
const mixin = hierarchy.as(clazz, view.mixin.ObjectTitle)
|
||||||
|
const titleProvider = await getResource(mixin.titleProvider)
|
||||||
|
try {
|
||||||
|
return await titleProvider(client, _id as Ref<Doc>)
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function syncLoc (loc: Location): Promise<void> {
|
async function syncLoc (loc: Location): Promise<void> {
|
||||||
const app = loc.path.length > 1 ? (loc.path[1] as Ref<Application>) : undefined
|
const app = loc.path.length > 1 ? (loc.path[1] as Ref<Application>) : undefined
|
||||||
const space = loc.path.length > 2 ? (loc.path[2] as Ref<Space>) : undefined
|
const space = loc.path.length > 2 ? (loc.path[2] as Ref<Space>) : undefined
|
||||||
|
Loading…
Reference in New Issue
Block a user