Skip to content

Commit 1623892

Browse files
authored
Merge pull request #8532 from nextcloud-libraries/feat/reference_picker_return_object
feat(referencePicker): introduce getReferenceWithPicker()
2 parents e32cc26 + 26c3411 commit 1623892

9 files changed

Lines changed: 85 additions & 5 deletions

File tree

src/components/NcRichText/NcReferencePicker/NcCustomPickerElement.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default {
2929
emits: [
3030
'cancel',
3131
'submit',
32+
'pick',
3233
],
3334
3435
data() {
@@ -62,11 +63,15 @@ export default {
6263
this.renderResult = result
6364
if (this.renderResult.object?._isVue && this.renderResult.object?.$on) {
6465
this.renderResult.object.$on('submit', this.onSubmit)
66+
this.renderResult.object.$on('pick', this.onPick)
6567
this.renderResult.object.$on('cancel', this.onCancel)
6668
}
6769
this.renderResult.element.addEventListener('submit', (e) => {
6870
this.onSubmit(e.detail)
6971
})
72+
this.renderResult.element.addEventListener('pick', (e) => {
73+
this.onPick(e.detail)
74+
})
7075
this.renderResult.element.addEventListener('cancel', this.onCancel)
7176
})
7277
},
@@ -75,6 +80,10 @@ export default {
7580
this.$emit('submit', value)
7681
},
7782
83+
onPick(value) {
84+
this.$emit('pick', value)
85+
},
86+
7887
onCancel() {
7988
this.$emit('cancel')
8089
},

src/components/NcRichText/NcReferencePicker/NcProviderList.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export default {
6565
emits: [
6666
'selectProvider',
6767
'submit',
68+
'pick',
6869
],
6970
7071
data() {
@@ -102,6 +103,7 @@ export default {
102103
if (p !== null) {
103104
if (p.isLink) {
104105
this.$emit('submit', p.title)
106+
this.$emit('pick', { link: p.title })
105107
} else {
106108
this.$emit('selectProvider', p)
107109
}

src/components/NcRichText/NcReferencePicker/NcRawLinkInput.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export default {
7171
7272
emits: [
7373
'submit',
74+
'pick',
7475
],
7576
7677
data() {
@@ -102,6 +103,7 @@ export default {
102103
const value = e.target.value
103104
if (this.isLinkValid) {
104105
this.$emit('submit', value)
106+
this.$emit('pick', { link: value })
105107
}
106108
},
107109

src/components/NcRichText/NcReferencePicker/NcReferencePicker.vue

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,30 @@
1414
ref="provider-list"
1515
@selectProvider="onProviderSelected"
1616
@submit="submitLink"
17+
@pick="pickLink"
1718
@cancel="cancelProviderSelection" />
1819
<NcRawLinkInput
1920
v-else-if="mode === MODES.standardLinkInput"
2021
ref="url-input"
2122
:provider="selectedProvider"
2223
@submit="submitLink"
24+
@pick="pickLink"
2325
@cancel="cancelRawLinkInput" />
2426
<NcSearch
2527
v-else-if="mode === MODES.searchInput"
2628
ref="url-input"
2729
:provider="selectedProvider"
28-
@cancel="cancelSearch"
29-
@submit="submitLink" />
30+
@submit="submitLink"
31+
@pick="pickLink"
32+
@cancel="cancelSearch" />
3033
<div
3134
v-else-if="mode === MODES.customElement"
3235
class="custom-element-wrapper">
3336
<NcCustomPickerElement
3437
:provider="selectedProvider"
3538
class="custom-element"
3639
@submit="submitLink"
40+
@pick="pickLink"
3741
@cancel="cancelCustomElement" />
3842
</div>
3943
</div>
@@ -97,6 +101,7 @@ export default {
97101
'cancelSearch',
98102
'providerSelected',
99103
'submit',
104+
'pick',
100105
],
101106
102107
data() {
@@ -181,6 +186,14 @@ export default {
181186
this.deselectProvider()
182187
},
183188
189+
pickLink(reference) {
190+
if (this.selectedProvider !== null) {
191+
touchProvider(this.selectedProvider.id)
192+
}
193+
this.$emit('pick', reference)
194+
this.deselectProvider()
195+
},
196+
184197
deselectProvider() {
185198
this.selectedProvider = null
186199
this.$emit('providerSelected', null)

src/components/NcRichText/NcReferencePicker/NcReferencePickerModal.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
:focusOnCreate="focusOnCreate"
4242
@providerSelected="onProviderSelect"
4343
@submit="onSubmit"
44+
@pick="onPick"
4445
@cancel="onCancel" />
4546
</div>
4647
</NcModal>
@@ -96,6 +97,7 @@ export default {
9697
emits: [
9798
'cancel',
9899
'submit',
100+
'pick',
99101
],
100102
101103
data() {
@@ -152,6 +154,11 @@ export default {
152154
this.$emit('submit', value)
153155
},
154156
157+
onPick(value) {
158+
this.show = false
159+
this.$emit('pick', value)
160+
},
161+
155162
onProviderSelect(provider) {
156163
this.selectedProvider = provider
157164
// provider was deselected and we started with an inital one: just close the modal

src/components/NcRichText/NcReferencePicker/NcSearch.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ export default {
122122
123123
emits: [
124124
'submit',
125+
'pick',
125126
],
126127
127128
data() {
@@ -248,6 +249,11 @@ export default {
248249
if (item.resourceUrl) {
249250
this.cancelSearchRequests()
250251
this.$emit('submit', item.resourceUrl)
252+
const reference = { link: item.resourceUrl }
253+
if (item.title) {
254+
reference.title = item.title
255+
}
256+
this.$emit('pick', reference)
251257
} else if (item.isMore) {
252258
this.searchMoreOf(item.providerId).then(() => {
253259
// allow clicking twice on the same "more" item

src/components/NcRichText/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
searchProvider,
2323
sortProviders,
2424
} from '../../functions/reference/providerHelper.ts'
25-
import { getLinkWithPicker } from '../../functions/reference/referencePickerModal.ts'
25+
import { getLinkWithPicker, getReferenceWithPicker } from '../../functions/reference/referencePickerModal.ts'
2626
import { isWidgetRegistered, registerWidget, renderWidget } from './../../functions/reference/widgets.ts'
2727

2828
export default NcRichText
@@ -32,6 +32,7 @@ export {
3232
getLinkWithPicker,
3333
getProvider,
3434
getProviders,
35+
getReferenceWithPicker,
3536
isCustomPickerElementRegistered,
3637
isWidgetRegistered,
3738
NcCustomPickerRenderResult,

src/functions/reference/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ export {
1313
renderWidget,
1414
} from './widgets.ts'
1515

16-
export { getLinkWithPicker } from './referencePickerModal.ts'
16+
export {
17+
getLinkWithPicker,
18+
getReferenceWithPicker,
19+
} from './referencePickerModal.ts'
1720

1821
export {
1922
type ReferenceProvider,

src/functions/reference/referencePickerModal.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import NcReferencePickerModal from './../../components/NcRichText/NcReferencePic
88
import { getProvider } from './providerHelper.js'
99

1010
/**
11-
* Creates a reference picker modal and return a promise which provides the result
11+
* Creates a reference picker modal and return a promise which provides the link URL
1212
*
1313
* @param providerId - Optional ID of initial selected provider
1414
* @param isInsideViewer - Should be true if this function is called while the Viewer is displayed
@@ -37,3 +37,40 @@ export async function getLinkWithPicker(providerId?: string, isInsideViewer?: bo
3737

3838
return promise
3939
}
40+
41+
/**
42+
* Creates a reference picker modal and return a promise which provides the reference object.
43+
*
44+
* The function guarantees a `link: string` on the resolved object. Custom picker elements may
45+
* include additional fields (e.g. `title`).
46+
*
47+
* @experimental The shape of the resolved reference and the signature of this function may still change.
48+
*
49+
* @template T - Expected shape of the resolved reference, must include `link: string`
50+
* @param providerId - Optional ID of initial selected provider
51+
* @param isInsideViewer - Should be true if this function is called while the Viewer is displayed
52+
*/
53+
export async function getReferenceWithPicker<T extends { link: string }>(providerId?: string, isInsideViewer?: boolean): Promise<T> {
54+
const modalId = 'referencePickerModal'
55+
const modalElement = document.createElement('div')
56+
modalElement.id = modalId
57+
document.body.append(modalElement)
58+
59+
const { promise, reject, resolve } = Promise.withResolvers<T>()
60+
const initialProvider = (providerId && getProvider(providerId)) || null
61+
const view = createApp(NcReferencePickerModal, {
62+
initialProvider,
63+
isInsideViewer,
64+
onCancel() {
65+
view.unmount()
66+
reject(new Error('User cancellation'))
67+
},
68+
onPick(reference: T) {
69+
view.unmount()
70+
resolve(reference)
71+
},
72+
})
73+
view.mount(modalElement)
74+
75+
return promise
76+
}

0 commit comments

Comments
 (0)