Skip to content

Commit 2ab99f6

Browse files
pkp/pkp-lib#10067 Update Plugins docs
1 parent b280aa5 commit 2ab99f6

1 file changed

Lines changed: 79 additions & 25 deletions

File tree

src/docs/guide/Plugins/Plugins.mdx

Lines changed: 79 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -66,53 +66,46 @@ Check out example of adding an additional tab in a Smarty template in [backend-u
6666

6767
Starting with version 3.5, most new pages/managers have hooks to inject your custom component in various locations.
6868

69-
Pinia stores are used as an underlying mechanism to inject components and are exposing configuration functions that are driving the UI. It also makes it straightforward to interact with the store to retrieve data or trigger any existing actions.
69+
More details about available hooks for individual pages/managers are covered in individual documentation ([Dashboard](../?path=/docs/pages-dashboard--docs), [Workflow](../?path=/docs/pages-workflow--docs), [FileManager](../?path=/docs/managers-filemanager--docs), [ReviewerManager](../?path=/docs/managers-reviewermanager--docs), [ParticipantManager](../?path=/docs/managers-participantmanager--docs), [GalleyManager](../?path=/docs/managers-galleymanager--docs)).
70+
71+
Pinia stores are used as an underlying tool for extensibility. JS Hooks can be leveraged using `store.extender`.
7072

7173
Example
7274

7375
```js
74-
// Adding iThenticate column
75-
pkp.registry.storeExtendFn(
76-
// Pinia store name
77-
'fileManager_SUBMISSION_FILES',
78-
// Function to extend
79-
'getColumns',
80-
// Columns is the result from the original function, which can be adjusted
81-
// Args are the arguments that the getColumns function retrieved to calculate the columns
82-
// Context exposes props that are passed to given component
76+
pkp.registry.storeExtend('fileManager_SUBMISSION_FILES', (piniaContext) => {
77+
const fileStore = piniaContext.store;
8378

84-
(columns, args, context) => {
85-
// Adding new column last to the end
79+
// Function to extend
80+
fileStore.extender.extendFn('getColumns', (columns, args) => {
81+
// adding new column last to the end
82+
console.log('extending getColumn');
8683
const newColumns = [...columns];
8784

8885
const {useLocalize} = pkp.modules.useLocalize;
8986
const {t} = useLocalize();
9087

91-
// to get file object
92-
console.log(args.file);
93-
9488
// to get prop passed to FileManager
95-
console.log(context.props.submission);
89+
console.log('submission:');
90+
console.log(fileStore.props.submission);
9691

97-
// to get anything thats not available in args/props, but its available on particular store.
98-
const store = pkp.registry.getPiniaStore('fileManager_SUBMISSION_FILES');
99-
console.log(store.files);
92+
// to get anything thats not available in args/props, but its available on store.
93+
console.log('files:');
94+
console.log(fileStore.files);
10095

10196
newColumns.splice(newColumns.length - 1, 0, {
102-
// Header label of new column
97+
// header label of new column
10398
header: t('plugins.generic.backendUiExample.ithenticate'),
104-
// Component responsible for rendering that table cell
99+
// component responsible for rendering that table cell
105100
component: 'BuiFileManagerCellIthenticate',
106101
props: {},
107102
});
108103

109104
return newColumns;
110-
},
111-
);
105+
});
106+
});
112107
```
113108

114-
More details about available hooks for individual pages/managers are covered in individual documentation ([Dashboard](../?path=/docs/pages-dashboard--docs), [Workflow](../?path=/docs/pages-workflow--docs), [FileManager](../?path=/docs/managers-filemanager--docs), [ReviewerManager](../?path=/docs/managers-reviewermanager--docs), [ParticipantManager](../?path=/docs/managers-participantmanager--docs), [GalleyManager](../?path=/docs/managers-galleymanager--docs)).
115-
116109
When the given store is present on the screen, it's also possible to get a list of available functions in the browser dev console with:
117110

118111
```js
@@ -135,6 +128,67 @@ console.log(dashboardStore.dashboardPage);
135128
dashboardStore.openFiltersModal();
136129
```
137130

131+
### Extending the store
132+
133+
In addition to extending configuration functions, it's also possible to add new logic to the existing store. It's executed when the store is created.
134+
135+
```js
136+
pkp.registry.storeExtend('fileManager_SUBMISSION_FILES', (piniaContext) => {
137+
const store = piniaContext.store;
138+
// Add custom logic here
139+
});
140+
```
141+
142+
`pkp.registry.storeExtend` is shorthand for the [Pinia plugin API](https://pinia.vuejs.org/core-concepts/plugins.html):
143+
144+
```js
145+
pkp.registry.getPiniaInstance().use((context) => {
146+
if (context.store.$id === 'fileManager_SUBMISSION_FILES') {
147+
// Add custom logic here
148+
}
149+
});
150+
```
151+
152+
For example, if some additional data are needed, it's possible to fetch them and attach them to the store, so they're available within the given manager/page. The same [Composition API](../?path=/docs/guide-vue-composition-api--docs) syntax is used.
153+
154+
```js
155+
// File manager extensions
156+
pkp.registry.storeExtend('fileManager_SUBMISSION_FILES', (piniaContext) => {
157+
const {useUrl} = pkp.modules.useUrl;
158+
const {useFetch} = pkp.modules.useFetch;
159+
160+
const fileStore = piniaContext.store;
161+
162+
// build query params reactively based on current files
163+
const ithenticateQueryParams = computed(() => {
164+
const fileIds = fileStore?.files?.map((file) => file.id) || [];
165+
166+
return {fileIds};
167+
});
168+
169+
const {apiUrl} = useUrl(`submissions/ithenticate`);
170+
171+
const {fetch: fetchIthenticateStatus, data: ithenticateStatus} = useFetch(
172+
apiUrl,
173+
{
174+
query: ithenticateQueryParams,
175+
},
176+
);
177+
178+
// fetch the ithenticate status when the fileIds changes
179+
watch(ithenticateQueryParams, (newQueryParams) => {
180+
if (newQueryParams?.fileIds?.length) {
181+
fetchIthenticateStatus();
182+
}
183+
});
184+
185+
// attach the state to the store, so its possible to retrieve it for example in the components that are injected via JS Hooks
186+
fileStore.ithenticateStatus = ithenticateStatus;
187+
});
188+
```
189+
190+
Complete example is available in [example plugin](https://github.com/jardakotesovec/backend-ui-example-plugin?tab=readme-ov-file#how-to-extend-filemanager-with-additional-column-and-custom-action).
191+
138192
### Advanced use cases
139193
140194
Pinia stores have their own [plugins API](https://pinia.vuejs.org/core-concepts/plugins.html). Therefore, as a plugin developer, you can leverage that. It should be used with caution, as any attempts to override store internals will likely lead to a fragile solution. But it provides some additional options for use cases which we have not considered.

0 commit comments

Comments
 (0)