mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-30 05:25:00 +02:00
Allow to perform markdown copy (#10090)
This commit is contained in:
@@ -247,6 +247,14 @@
|
||||
"safeForSimultaneousRushProcesses": true,
|
||||
"shellCommand": "./common/scripts/docker.sh"
|
||||
},
|
||||
{
|
||||
"commandKind": "global",
|
||||
"name": "docker-server",
|
||||
"summary": "Build docker with platform",
|
||||
"description": "use to build all docker containers required for platform",
|
||||
"safeForSimultaneousRushProcesses": true,
|
||||
"shellCommand": "./common/scripts/docker-server.sh && rush docker:up"
|
||||
},
|
||||
{
|
||||
"commandKind": "global",
|
||||
"name": "docker:up",
|
||||
|
||||
Generated
+2
-1
@@ -6277,7 +6277,7 @@ packages:
|
||||
version: 0.0.0
|
||||
|
||||
'@rush-temp/view-resources@file:projects/view-resources.tgz':
|
||||
resolution: {integrity: sha512-L3IzKi6Lo78o7lDzz+V2Ap+7lStsOm0mhIuaOtFk/UQQjSHp8CVcN0RwubG+KEHV/zv2li/pXTjNes3Ayg+Xsw==, tarball: file:projects/view-resources.tgz}
|
||||
resolution: {integrity: sha512-iBRhD5GGptL67zFov48Awf3MSVsnV6uctkmKFRv7EzGXUXpbS5E5uv3mS0TUlwEV2GCGIxejsbnQ8tJrHYqMNw==, tarball: file:projects/view-resources.tgz}
|
||||
version: 0.0.0
|
||||
|
||||
'@rush-temp/view@file:projects/view.tgz':
|
||||
@@ -34768,6 +34768,7 @@ snapshots:
|
||||
'@hcengineering/platform-rig': 0.7.19(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.5.3)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.9.3)))(postcss@8.5.3)(sass@1.93.2)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.9.3))
|
||||
'@hcengineering/query': 0.7.6
|
||||
'@hcengineering/text': 0.7.5(prosemirror-inputrules@1.4.0)(prosemirror-model@1.24.1)(prosemirror-state@1.4.3)(prosemirror-view@1.37.2)
|
||||
'@hcengineering/text-markdown': 0.7.5
|
||||
'@types/jest': 29.5.12
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.9.3))(eslint@8.56.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.9.3)
|
||||
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
rush docker:build -p 20 \
|
||||
--to @hcengineering/pod-server \
|
||||
--to @hcengineering/tool
|
||||
@@ -101,6 +101,24 @@ export function createActions (builder: Builder): void {
|
||||
card.action.UnsetParent
|
||||
)
|
||||
|
||||
createAction(builder, {
|
||||
action: view.actionImpl.CopyDocumentMarkdown,
|
||||
actionProps: {
|
||||
contentClass: card.class.Card,
|
||||
contentField: 'content'
|
||||
},
|
||||
label: view.string.CopyDocumentMarkdown,
|
||||
icon: view.icon.Print,
|
||||
input: 'any',
|
||||
category: card.category.Card,
|
||||
target: card.class.Card,
|
||||
query: {},
|
||||
context: {
|
||||
mode: ['context', 'browser'],
|
||||
group: 'tools'
|
||||
}
|
||||
})
|
||||
|
||||
createAction(builder, {
|
||||
action: view.actionImpl.ShowPopup,
|
||||
actionProps: {
|
||||
|
||||
@@ -458,6 +458,7 @@
|
||||
onContentError: ({ error, disableCollaboration }) => {
|
||||
disableCollaboration()
|
||||
contentError = true
|
||||
console.error(error)
|
||||
Analytics.handleError(error)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -275,4 +275,7 @@
|
||||
<path d="M13 21.0005C13 20.4482 12.5523 20.0005 12 20.0005H7C6.44772 20.0005 6 20.4482 6 21.0005C6 21.5528 6.44772 22.0005 7 22.0005H12C12.5523 22.0005 13 21.5528 13 21.0005Z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M26 4.00012C28.2091 4.00012 30 5.79098 30 8.00012V24.0001C30 26.2093 28.2091 28.0001 26 28.0001H6C3.79086 28.0001 2 26.2093 2 24.0001V8.00012C2 5.79098 3.79086 4.00012 6 4.00012H26ZM17 6.00012H26C27.1046 6.00012 28 6.89555 28 8.00012V24.0001C28 25.1047 27.1046 26.0001 26 26.0001H17V6.00012ZM15 6.00012V26.0001H6C4.89543 26.0001 4 25.1047 4 24.0001V8.00012C4 6.89555 4.89543 6.00012 6 6.00012H15Z"/>
|
||||
</symbol>
|
||||
<symbol id="print" viewBox="0 0 32 32">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 4C7.89543 4 7 4.89543 7 6V26C7 27.1046 7.89543 28 9 28H23C24.1046 28 25 27.1046 25 26V12H21C18.7909 12 17 10.2091 17 8V4H9ZM19 4.41421V8C19 9.10457 19.8954 10 21 10H24.5858L19 4.41421ZM5 6C5 3.79086 6.79086 2 9 2H18.5858C19.1162 2 19.6249 2.21071 20 2.58579L26.4142 9C26.7893 9.37507 27 9.88378 27 10.4142V26C27 28.2091 25.2091 30 23 30H9C6.79086 30 5 28.2091 5 26V6ZM10 17C10 16.4477 10.4477 16 11 16H21C21.5523 16 22 16.4477 22 17C22 17.5523 21.5523 18 21 18H11C10.4477 18 10 17.5523 10 17ZM10 23C10 22.4477 10.4477 22 11 22H21C21.5523 22 22 22.4477 22 23C22 23.5523 21.5523 24 21 24H11C10.4477 24 10 23.5523 10 23Z" />
|
||||
</symbol>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 62 KiB |
@@ -112,6 +112,7 @@
|
||||
"Or": "Nebo",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "Kopírovat do schránky",
|
||||
"CopyDocumentMarkdown": "Kopírovat jako Markdown",
|
||||
"PublicView": "Veřejné",
|
||||
|
||||
"ChooseIcon": "Vybrat ikonu",
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
"Or": "Oder",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "In die Zwischenablage kopieren",
|
||||
"CopyDocumentMarkdown": "Als Markdown kopieren",
|
||||
"PublicView": "Öffentlich",
|
||||
|
||||
"ChooseIcon": "Symbol wählen",
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
"Or": "Or",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "Copy to clipboard",
|
||||
"CopyDocumentMarkdown": "Copy as Markdown",
|
||||
"PublicView": "Public",
|
||||
|
||||
"ChooseIcon": "Choose icon",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"Or": "O",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "Copiar al portapapeles",
|
||||
"CopyDocumentMarkdown": "Copiar como Markdown",
|
||||
"PublicView": "Público",
|
||||
"ChooseIcon": "Elegir icono",
|
||||
"IconColor": "Elegir color del icono",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"Or": "Ou",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "Copier dans le presse-papiers",
|
||||
"CopyDocumentMarkdown": "Copier en Markdown",
|
||||
"PublicView": "Vue publique",
|
||||
"ChooseIcon": "Choisir une icône",
|
||||
"IconColor": "Choisir la couleur de l'icône",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"Or": "O",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "Copia negli appunti",
|
||||
"CopyDocumentMarkdown": "Copia come Markdown",
|
||||
"PublicView": "Vista pubblica",
|
||||
"ChooseIcon": "Scegli icona",
|
||||
"IconColor": "Scegli colore icona",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"Or": "または",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "クリップボードにコピー",
|
||||
"CopyDocumentMarkdown": "Markdownとしてコピー",
|
||||
"PublicView": "公開",
|
||||
"ChooseIcon": "アイコンを選択",
|
||||
"IconColor": "アイコンの色を選択",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"Or": "Ou",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "Copiar para área de transferência",
|
||||
"CopyDocumentMarkdown": "Copiar como Markdown",
|
||||
"PublicView": "Público",
|
||||
"ChooseIcon": "Escolher ícone",
|
||||
"IconColor": "Escolher cor do ícone",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"Or": "Или",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "Скопировать в буфер обмена",
|
||||
"CopyDocumentMarkdown": "Скопировать как Markdown",
|
||||
"PublicView": "Публичный",
|
||||
|
||||
"ChooseIcon": "Выбрать иконку",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"Or": "Veya",
|
||||
"HyperlinkPlaceholder": "https://ornek.com",
|
||||
"CopyToClipboard": "Panoya kopyala",
|
||||
"CopyDocumentMarkdown": "Markdown olarak kopyala",
|
||||
"PublicView": "Genel",
|
||||
"ChooseIcon": "İkon seç",
|
||||
"IconColor": "İkon rengi seç",
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
"Or": "或",
|
||||
"HyperlinkPlaceholder": "https://jappleseed.com",
|
||||
"CopyToClipboard": "复制到剪贴板",
|
||||
"CopyDocumentMarkdown": "复制为 Markdown",
|
||||
"PublicView": "公开视图",
|
||||
|
||||
"ChooseIcon": "选择图标",
|
||||
|
||||
@@ -67,7 +67,8 @@ loadMetadata(view.icon, {
|
||||
Feather: `${icons}#feather`,
|
||||
MasterDetail: `${icons}#master-detail`,
|
||||
Tree: `${icons}#tree`,
|
||||
Document: `${icons}#document`
|
||||
Document: `${icons}#document`,
|
||||
Print: `${icons}#print`
|
||||
})
|
||||
loadMetadata(core.icon, {
|
||||
TypeString: `${icons}#string`,
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
"@hcengineering/ui": "^0.7.0",
|
||||
"@hcengineering/task": "^0.7.0",
|
||||
"@hcengineering/text": "^0.7.5",
|
||||
"@hcengineering/text-markdown": "^0.7.5",
|
||||
"@hcengineering/preference": "^0.7.0",
|
||||
"@hcengineering/notification": "^0.7.0",
|
||||
"@hcengineering/presentation": "^0.7.0",
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import {
|
||||
import contact from '@hcengineering/contact'
|
||||
import core, {
|
||||
type Blob,
|
||||
type Class,
|
||||
type Doc,
|
||||
type DocumentQuery,
|
||||
@@ -6,17 +8,21 @@ import {
|
||||
type Ref,
|
||||
type Space,
|
||||
type TxResult,
|
||||
getCurrentAccount
|
||||
getCurrentAccount,
|
||||
makeDocCollabId
|
||||
} from '@hcengineering/core'
|
||||
import { type Asset, type IntlString, type Resource, getResource } from '@hcengineering/platform'
|
||||
import {
|
||||
MessageBox,
|
||||
getClient,
|
||||
updateAttribute,
|
||||
type ContextStore,
|
||||
MessageBox,
|
||||
contextStore,
|
||||
copyTextToClipboardOldBrowser
|
||||
copyTextToClipboardOldBrowser,
|
||||
getClient,
|
||||
getMarkup,
|
||||
updateAttribute
|
||||
} from '@hcengineering/presentation'
|
||||
import { markupToJSON } from '@hcengineering/text'
|
||||
import { markupToMarkdown } from '@hcengineering/text-markdown'
|
||||
import {
|
||||
type AnyComponent,
|
||||
type AnySvelteComponent,
|
||||
@@ -24,10 +30,12 @@ import {
|
||||
type PopupPosAlignment,
|
||||
closeTooltip,
|
||||
isPopupPosAlignment,
|
||||
locationToUrl,
|
||||
navigate,
|
||||
showPanel,
|
||||
showPopup
|
||||
} from '@hcengineering/ui'
|
||||
import { get } from 'svelte/store'
|
||||
import MoveView from './components/Move.svelte'
|
||||
import view from './plugin'
|
||||
import {
|
||||
@@ -36,13 +44,10 @@ import {
|
||||
type SelectionStore,
|
||||
focusStore,
|
||||
previewDocument,
|
||||
selectionStore,
|
||||
selectionLimit
|
||||
selectionLimit,
|
||||
selectionStore
|
||||
} from './selection'
|
||||
import { deleteObjects, getObjectId, getObjectLinkFragment, restrictionStore } from './utils'
|
||||
import contact from '@hcengineering/contact'
|
||||
import { locationToUrl } from '@hcengineering/ui'
|
||||
import { get } from 'svelte/store'
|
||||
|
||||
/**
|
||||
* Action to be used for copying text to clipboard.
|
||||
@@ -65,21 +70,20 @@ async function CopyTextToClipboard (
|
||||
}
|
||||
): Promise<void> {
|
||||
const getText = await getResource(props.textProvider)
|
||||
const text = Array.isArray(doc)
|
||||
? (await Promise.all(doc.map(async (d) => await getText(d, props.props)))).join(',')
|
||||
: await getText(doc, props.props)
|
||||
await copyText(text, 'text/plain')
|
||||
}
|
||||
|
||||
async function copyText (text: any, contentType: string = 'text/plain'): Promise<void> {
|
||||
try {
|
||||
// Safari specific behavior
|
||||
// see https://bugs.webkit.org/show_bug.cgi?id=222262
|
||||
const text = Array.isArray(doc)
|
||||
? (await Promise.all(doc.map(async (d) => await getText(d, props.props)))).join(',')
|
||||
: await getText(doc, props.props)
|
||||
const clipboardItem = new ClipboardItem({
|
||||
'text/plain': text
|
||||
})
|
||||
await navigator.clipboard.write([clipboardItem])
|
||||
} catch {
|
||||
// Fallback to default clipboard API implementation
|
||||
const text = Array.isArray(doc)
|
||||
? (await Promise.all(doc.map(async (d) => await getText(d, props.props)))).join(',')
|
||||
: await getText(doc, props.props)
|
||||
if (navigator.clipboard != null && typeof navigator.clipboard.writeText === 'function') {
|
||||
await navigator.clipboard.writeText(text)
|
||||
} else copyTextToClipboardOldBrowser(text)
|
||||
@@ -589,6 +593,41 @@ async function getPopupAlignment (
|
||||
}
|
||||
}
|
||||
|
||||
async function CopyDocumentMarkdown (
|
||||
doc: Doc | Doc[],
|
||||
evt: Event,
|
||||
props: {
|
||||
contentClass: Ref<Class<Doc>>
|
||||
contentField: string
|
||||
}
|
||||
): Promise<void> {
|
||||
const docs = Array.isArray(doc) ? doc : doc !== undefined ? [doc] : []
|
||||
if (docs.length !== 1) {
|
||||
return
|
||||
}
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const contentClass = hierarchy.getClass(props.contentClass)
|
||||
if (contentClass == null) {
|
||||
return
|
||||
}
|
||||
const contentField = hierarchy.findAttribute(props.contentClass, props.contentField)
|
||||
if (contentField == null) {
|
||||
return
|
||||
}
|
||||
if (contentField.type._class === core.class.TypeCollaborativeDoc) {
|
||||
const content = await getMarkup(
|
||||
makeDocCollabId(docs[0], props.contentField),
|
||||
(docs[0] as any)[props.contentField] as Ref<Blob>
|
||||
)
|
||||
if (content !== null) {
|
||||
const jsonMarkup = markupToJSON(content)
|
||||
const contentJson = markupToMarkdown(jsonMarkup)
|
||||
await copyText(contentJson, 'text/markdown')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@@ -616,5 +655,6 @@ export const actionImpl = {
|
||||
ShowPopup,
|
||||
ShowEditor,
|
||||
ValueSelector,
|
||||
AttributeSelector
|
||||
AttributeSelector,
|
||||
CopyDocumentMarkdown
|
||||
}
|
||||
|
||||
@@ -156,7 +156,8 @@ const view = plugin(viewId, {
|
||||
OpenInNewTab: '' as Ref<Action>,
|
||||
RemoveRelation: '' as Ref<Action>,
|
||||
|
||||
CopyLink: '' as Ref<Action<Doc, any>>
|
||||
CopyLink: '' as Ref<Action<Doc, any>>,
|
||||
CopyDocumentMarkdown: '' as Ref<Action<Doc, any>>
|
||||
},
|
||||
viewlet: {
|
||||
Table: '' as Ref<ViewletDescriptor>,
|
||||
@@ -250,7 +251,8 @@ const view = plugin(viewId, {
|
||||
Icon: '' as IntlString,
|
||||
Select: '' as IntlString,
|
||||
Color: '' as IntlString,
|
||||
AutomationOnly: '' as IntlString
|
||||
AutomationOnly: '' as IntlString,
|
||||
CopyDocumentMarkdown: '' as IntlString
|
||||
},
|
||||
icon: {
|
||||
Table: '' as Asset,
|
||||
@@ -301,7 +303,8 @@ const view = plugin(viewId, {
|
||||
Feather: '' as Asset,
|
||||
MasterDetail: '' as Asset,
|
||||
Tree: '' as Asset,
|
||||
Document: '' as Asset
|
||||
Document: '' as Asset,
|
||||
Print: '' as Asset
|
||||
},
|
||||
category: {
|
||||
General: '' as Ref<ActionCategory>,
|
||||
@@ -344,6 +347,10 @@ const view = plugin(viewId, {
|
||||
textProvider: Resource<(doc: Doc, props: Record<string, any>) => Promise<string>>
|
||||
props?: Record<string, any>
|
||||
}>,
|
||||
CopyDocumentMarkdown: '' as ViewAction<{
|
||||
contentClass: Ref<Class<Doc>>
|
||||
contentField: string
|
||||
}>,
|
||||
UpdateDocument: '' as ViewAction<{
|
||||
key: string
|
||||
value: any
|
||||
|
||||
Reference in New Issue
Block a user