Improved URL-to-reference conversion (#8916)

Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com>
This commit is contained in:
Victor Ilyushchenko 2025-05-14 06:08:51 +03:00 committed by GitHub
parent d1a338d313
commit c7847a035c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 71 additions and 52 deletions

View File

@ -13,6 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import { Analytics } from '@hcengineering/analytics'
import attachment, { Attachment, AttachmentsEvents } from '@hcengineering/attachment'
import contact from '@hcengineering/contact'
import core, { BlobMetadata, Doc, PersonId, Ref, generateId, type Blob, type Space } from '@hcengineering/core'
@ -34,11 +35,9 @@
defaultRefActions,
getModelRefActions
} from '@hcengineering/text-editor-resources'
import { AnySvelteComponent, getEventPositionElement, getPopupPositionElement, navigate } from '@hcengineering/ui'
import { type FileUploadCallbackParams, uploadFiles } from '@hcengineering/uploader'
import view from '@hcengineering/view'
import { getCollaborationUser, getObjectId, getObjectLinkFragment } from '@hcengineering/view-resources'
import { Analytics } from '@hcengineering/analytics'
import { AnySvelteComponent, getEventPositionElement, getPopupPositionElement } from '@hcengineering/ui'
import { uploadFiles, type FileUploadCallbackParams } from '@hcengineering/uploader'
import { getCollaborationUser, getObjectId, openDoc } from '@hcengineering/view-resources'
import AttachmentsGrid from './AttachmentsGrid.svelte'
@ -324,8 +323,7 @@
on:open-document={async (event) => {
const doc = await client.findOne(event.detail._class, { _id: event.detail._id })
if (doc != null) {
const location = await getObjectLinkFragment(client.getHierarchy(), doc, {}, view.component.EditDoc)
navigate(location)
await openDoc(client.getHierarchy(), doc)
}
}}
on:focus

View File

@ -13,13 +13,11 @@
// limitations under the License.
-->
<script lang="ts">
import { Doc, Class, Ref, updateAttribute } from '@hcengineering/core'
import { Class, Doc, Ref, updateAttribute } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import { createQuery, getAttribute, getClient, KeyedAttribute } from '@hcengineering/presentation'
import { navigate } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { getObjectLinkFragment } from '@hcengineering/view-resources'
import { openDoc } from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte'
import AttachmentStyledBox from './AttachmentStyledBox.svelte'
@ -137,8 +135,7 @@
save(object, description)
const doc = await client.findOne(event.detail._class, { _id: event.detail._id })
if (doc != null) {
const location = await getObjectLinkFragment(client.getHierarchy(), doc, {}, view.component.EditDoc)
navigate(location)
await openDoc(client.getHierarchy(), doc)
}
}}
/>

View File

@ -20,9 +20,7 @@
import { getClient } from '@hcengineering/presentation'
import { Heading } from '@hcengineering/text-editor'
import { TableOfContents } from '@hcengineering/text-editor-resources'
import { navigate } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { getObjectLinkFragment } from '@hcengineering/view-resources'
import { openDoc } from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte'
import ContentEditor from './ContentEditor.svelte'
@ -107,8 +105,7 @@
on:open-document={async (event) => {
const doc = await client.findOne(event.detail._class, { _id: event.detail._id })
if (doc != null) {
const location = await getObjectLinkFragment(client.getHierarchy(), doc, {}, view.component.EditDoc)
navigate(location)
await openDoc(client.getHierarchy(), doc)
}
}}
bind:this={editor}

View File

@ -13,48 +13,47 @@
// limitations under the License.
-->
<script lang="ts">
import { createEventDispatcher, onDestroy, tick } from 'svelte'
import { merge } from 'effector'
import { type Ref, type Blob, generateId } from '@hcengineering/core'
import { getResource, setPlatformStatus, unknownError } from '@hcengineering/platform'
import { getClient } from '@hcengineering/presentation'
import view from '@hcengineering/view'
import attachment, { Attachment } from '@hcengineering/attachment'
import documents, { DocumentState } from '@hcengineering/controlled-documents'
import { type Blob, type Ref, generateId } from '@hcengineering/core'
import { getResource, setPlatformStatus, unknownError } from '@hcengineering/platform'
import { getClient } from '@hcengineering/presentation'
import { Editor, Heading } from '@hcengineering/text-editor'
import {
CollaboratorEditor,
TableOfContents,
TableOfContentsContent,
FocusExtension,
HeadingsExtension,
IsEmptyContentExtension,
NodeHighlightExtension,
NodeHighlightType,
highlightUpdateCommand,
getNodeElement
TableOfContents,
TableOfContentsContent,
getNodeElement,
highlightUpdateCommand
} from '@hcengineering/text-editor-resources'
import { navigate, EditBox, Scroller, Label } from '@hcengineering/ui'
import { getCollaborationUser, getObjectLinkFragment } from '@hcengineering/view-resources'
import { EditBox, Label, Scroller } from '@hcengineering/ui'
import { getCollaborationUser, openDoc } from '@hcengineering/view-resources'
import { merge } from 'effector'
import { createEventDispatcher, onDestroy, tick } from 'svelte'
import plugin from '../../plugin'
import {
$areDocumentCommentPopupsOpened as areDocumentCommentPopupsOpened,
$controlledDocument as controlledDocument,
$isEditable as isEditable,
$documentCommentHighlightedLocation as documentCommentHighlightedLocation,
$areDocumentCommentPopupsOpened as arePopupsOpened,
$canAddDocumentComments as canAddDocumentComments,
$canViewDocumentComments as canViewDocumentComments,
$controlledDocument as controlledDocument,
$documentCommentHighlightedLocation as documentCommentHighlightedLocation,
$documentComments as documentComments,
documentCommentsDisplayRequested,
documentCommentsHighlightUpdated,
documentCommentsLocationNavigateRequested,
$documentReleasedVersions as documentReleasedVersions
$documentReleasedVersions as documentReleasedVersions,
$isEditable as isEditable
} from '../../stores/editors/document'
import DocumentTitle from './DocumentTitle.svelte'
import DocumentPrintTitlePage from '../print/DocumentPrintTitlePage.svelte'
import { syncDocumentMetaTitle } from '../../utils'
import DocumentPrintTitlePage from '../print/DocumentPrintTitlePage.svelte'
import DocumentTitle from './DocumentTitle.svelte'
const client = getClient()
const hierarchy = client.getHierarchy()
@ -295,8 +294,7 @@
on:open-document={async (event) => {
const doc = await client.findOne(event.detail._class, { _id: event.detail._id })
if (doc != null) {
const location = await getObjectLinkFragment(client.getHierarchy(), doc, {}, view.component.EditDoc)
navigate(location)
await openDoc(client.getHierarchy(), doc)
}
}}
attachFile={async (file) => {

View File

@ -15,6 +15,7 @@
//
-->
<script lang="ts">
import { Analytics } from '@hcengineering/analytics'
import attachment, { Attachment } from '@hcengineering/attachment'
import core, { Doc, Ref, WithLookup, generateId, type Blob } from '@hcengineering/core'
import { Document, DocumentEvents } from '@hcengineering/document'
@ -35,7 +36,6 @@
TimeSince,
createFocusManager,
getPlatformColorDef,
navigate,
showPopup,
themeStore
} from '@hcengineering/ui'
@ -45,14 +45,13 @@
IconPicker,
ParentsNavigator,
RelationsEditor,
getObjectLinkFragment,
openDoc,
restrictionStore,
showMenu
} from '@hcengineering/view-resources'
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
import { Analytics } from '@hcengineering/analytics'
import { starDocument, unstarDocument, unlockContent } from '..'
import { starDocument, unlockContent, unstarDocument } from '..'
import document from '../plugin'
import { getDocumentUrl } from '../utils'
import DocumentEditor from './DocumentEditor.svelte'
@ -389,8 +388,7 @@
on:open-document={async (event) => {
const doc = await client.findOne(event.detail._class, { _id: event.detail._id })
if (doc != null) {
const location = await getObjectLinkFragment(client.getHierarchy(), doc, {}, view.component.EditDoc)
navigate(location)
await openDoc(client.getHierarchy(), doc)
}
}}
on:loaded={() => {

View File

@ -408,7 +408,12 @@ export async function getReferenceLabel<T extends Doc> (
const identifier = (await labelProviderFn?.(client, id, doc)) ?? ''
const title = (await titleProviderFn?.(client, id, doc)) ?? ''
const label = identifier !== '' && title !== '' && identifier !== title ? `${identifier} ${title}` : title ?? ''
const label =
identifier !== '' && title !== '' && identifier !== title
? `${identifier} ${title}`
: title !== ''
? title
: identifier
return label
}
@ -451,7 +456,6 @@ export async function getTargetObjectFromUrl (
urlOrLocation: string | Location
): Promise<{ _id: Ref<Doc>, _class: Ref<Class<Doc>> } | undefined> {
const client = getClient()
const hierarchy = client.getHierarchy()
let location: Location
if (typeof urlOrLocation === 'string') {
@ -469,19 +473,43 @@ export async function getTargetObjectFromUrl (
const appAlias = (location.path[2] ?? '').trim()
if (!(appAlias.length > 0)) return
const excludedApps = getMetadata(workbench.metadata.ExcludedApplications) ?? []
const apps: Application[] = client
.getModel()
.findAllSync<Application>(workbench.class.Application, { hidden: false, _id: { $nin: excludedApps } })
const app = apps.find((p) => p.alias === appAlias)
const locationResolver = app?.locationResolver
const locationDataResolver = app?.locationDataResolver
if (app?.locationResolver === undefined) return
const locationResolverFn = await getResource(app.locationResolver)
const resolvedLocation = await locationResolverFn(location)
if ((location.fragment ?? '') !== '') {
const obj = await getObjectFromFragment(location.fragment ?? '')
if (obj !== undefined) return obj
}
const locationParts = decodeURIComponent(resolvedLocation?.loc?.fragment ?? '').split('|')
if (locationResolver !== undefined) {
const locationResolverFn = await getResource(locationResolver)
const resolvedLocation = await locationResolverFn(location)
const obj = await getObjectFromFragment(resolvedLocation?.loc?.fragment ?? '')
if (obj !== undefined) return obj
}
if (locationDataResolver !== undefined) {
const locationDataResolverFn = await getResource(locationDataResolver)
const locationData = await locationDataResolverFn(location)
if (locationData.objectId !== undefined && locationData.objectClass !== undefined) {
return { _id: locationData.objectId, _class: locationData.objectClass }
}
}
}
async function getObjectFromFragment (
fragment: string
): Promise<{ _id: Ref<Doc>, _class: Ref<Class<Doc>> } | undefined> {
const client = getClient()
const hierarchy = client.getHierarchy()
const locationParts = decodeURIComponent(fragment).split('|')
const id = locationParts[1] as Ref<Doc>
const objectclass = locationParts[2] as Ref<Class<Doc>>
if (id === undefined || objectclass === undefined) return

View File

@ -399,7 +399,10 @@
}
}
loc.query = resolved.loc.query ?? loc.query ?? currentQuery ?? resolved.defaultLocation.query
loc.fragment = resolved.loc.fragment ?? loc.fragment ?? resolved.defaultLocation.fragment
loc.fragment =
(loc.fragment ?? '') !== '' && resolved.loc.fragment === resolved.defaultLocation.fragment
? loc.fragment
: resolved.loc.fragment ?? resolved.defaultLocation.fragment
return loc
}