-
Notifications
You must be signed in to change notification settings - Fork 601
make widget operations dynamic to add custom ones #4897
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
51c8b02
to
dbce534
Compare
6001c86
to
02912d7
Compare
} | ||
if (modal) { | ||
apos.modal.execute(modal, { | ||
modelValue: this.modelValue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we'll just add additional data if needed
278bd9e
to
64232c1
Compare
// Maintain a knowledge of which tray item toggles are active | ||
const trayItem = this.trayItems.find(trayItem => trayItem.name === item.action); | ||
|
||
if (trayItem && trayItem.options.toggle) { | ||
this.trayItemState = { | ||
...this.trayItemState, | ||
[item.action]: !this.trayItemState[item.action] | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
block moved from the late onAdminMenuClick
(unnecessary? right?) event listener
…247-widget-operations
…247-widget-operations
// TODO: make sure the update method from | ||
// modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue | ||
// does the job and does not mess with the widget type and _id: | ||
this.$emit('update', result.widget); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some suggestions / questions.
Also one thing is unclear to me:
When we create the widget operation backend side there is no action
.
Does it refer to the name of the operation? If it's the case why not keeping the same name for both?
There is an action inside the permission object but I don't think it's related to what is called item.action
on the frontend.
emitEvent(name) { | ||
apos.bus.$emit('admin-menu-click', name); | ||
emitEvent(item) { | ||
apos.bus.$emit('admin-menu-click', item.action); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So item-clicked
emits the entire item, but admin-menu-click
emits only the action name?
Shouldn't we make it more consistent and emit the item all the time, maybe it's a lot more work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, but in the end, the component that listens to admin-menu-click
event will need to adapt, and so on.
Since the scope of this PR has already been way over, I prefer to limit the changes to the minimum.
@@ -138,11 +138,11 @@ export default { | |||
togglePublishDraftMode() { | |||
if (this.canTogglePublishDraftMode) { | |||
const mode = this.draftMode === 'draft' ? 'published' : 'draft'; | |||
this.switchDraftMode(mode); | |||
this.$emit('switch-draft-mode', mode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.$emit('switch-draft-mode', mode); | |
const action = this.draftMode === 'draft' ? 'published' : 'draft'; | |
this.switchDraftMode({ action }); |
|
||
self.widgetOperations = self.widgetOperations.filter( | ||
({ name }) => name !== operation.name | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this to avoid duplicates? I think that throwing an error would be easier to debug and fix for users?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this replaces an already-registered operation with the same name.
I took the same logic that's for customOperations:
apostrophe/modules/@apostrophecms/doc/index.js
Line 1538 in 62cdeaa
self.contextOperations = [ |
const widgetOperations = self.widgetOperations.filter(({ permission }) => { | ||
if (permission?.action && permission?.type) { | ||
return self.apos.permission.can(req, permission.action, permission.type, permission.mode || 'draft'); | ||
} | ||
return true; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const widgetOperations = self.widgetOperations.filter(({ permission }) => { | |
if (permission?.action && permission?.type) { | |
return self.apos.permission.can(req, permission.action, permission.type, permission.mode || 'draft'); | |
} | |
return true; | |
}); | |
const widgetOperations = self.widgetOperations.filter(({ permission = {} }) => { | |
if (permission.action && permission.type) { | |
return self.apos.permission.can(req, permission.action, permission.type, permission.mode || 'draft'); | |
} | |
return true; | |
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like my version better 🍃
@@ -1,75 +1,36 @@ | |||
<template> | |||
<div class="apos-area-modify-controls"> | |||
<AposButtonGroup | |||
v-if="!foreign" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AposWidgetControls.vue
is never rendered if foreign
is falsy,
You should remove the prop foreign
from the component AposWidgetControls
it serves no purpose.
See:
<AposWidgetControls
v-if="!foreign" // Never rendered if foreign is falsy
:first="i === 0"
:last="i === next.length - 1"
:options="{ contextual: isContextual }"
:foreign="foreign" // Useless prop, can be removed
:disabled="disabled"
:max-reached="maxReached"
:tabbable="isFocused"
:model-value="widget"
:area-field="field"
@up="$emit('up', i);"
@remove="$emit('remove', i);"
@edit="$emit('edit', i);"
@cut="$emit('cut', i);"
@copy="$emit('copy', i);"
@clone="$emit('clone', i);"
@down="$emit('down', i);"
@update="$emit('update')"
/>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
.filter(operation => !operation.secondaryLevel), | ||
widgetSecondaryOperations: filteredOperations | ||
.filter(operation => operation.secondaryLevel) | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional but logic could be in a method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
}, | ||
methods: { | ||
filterByWidgetType(operation) { | ||
return !operation.type || operation.type === this.modelValue.type; | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is never used, you could use it in data
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was used.
But now it's been moved to the shared method, see 5873267
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Erratum.
It wasn't used 👍
widget: this.modelValue, | ||
field: this.areaField | ||
}); | ||
if (result.widget) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Result can be undefined:
if (result?.widget) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well spotted
@@ -81,7 +81,6 @@ | |||
"chooseDocType": "{{ type }} auswählen", | |||
"clear": "Löschen", | |||
"clearSelection": "Auswahl löschen", | |||
"clone": "Duplizieren", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't have clone anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is called "Duplicate..." now
I am not sure I understand, but I can say that I started with not setting the But actually, we'd like to be able to add operations that have the same modal, with different props. Regarding Indeed, permission's action is related to our permission system, as we usually provide an 'action' (create, edit publish etc) for a specific 'type':
I hope this answers your question. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍🏼
TODO: check that other modules have not been broken with the✅menuItemClicked
changed to pass an item object and not justitem.action
Related to https://github.com/apostrophecms/testbed/pull/343
Summary
apos.area.addWidgetOperation
method to:@apostrophecms/widget-type
module to register operations only for widgets that match the type of the module where the wrapper is invoked.apos.area.getBrowserData
AposContextMenu.vue
AposContextMenu.vue
to make it emit the whole clicked item, not only itsaction
property, in order to access themodal
property.action
->item.action
)Lot's of eslint(done in Fix eslint warnings #4923)max-len
warnings fixed (marked as "linter" in the PR comments)What are the specific steps to test this change?
- Primary level
- Secondary level
- Specific widget type
What kind of change does this PR introduce?
(Check at least one)
Make sure the PR fulfills these requirements:
If adding a new feature without an already open issue, it's best to open a feature request issue first and wait for approval before working on it.
Other information: