Skip to content
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

Get rid of the double modals stack #4536

Merged
merged 22 commits into from
May 28, 2024
Merged

Conversation

ValJed
Copy link
Contributor

@ValJed ValJed commented May 14, 2024

PRO-5818

Summary

  • Adds pinia
  • Stores modals and modals logic in a pinia store. Methods are attached to apos.modal accessible in and out of vue components.
  • Only BC is that apos.modal.stack isn't existing anymore, a method called apos.modal.get() allows to get all modals or one by ID. Not sure users needed to call this apos.modal.stack before.
  • Fixes the esc that close modals that wasn't working like before.

PR in Cypress-tools:

  • hasModalCount method has been updated to use apos.modal.get() instead of apos.modal.stack.

PR in document-versions:

  • Use the store to get the stack. It'll need to be updated with core. If needed we can tweak document-versions to support both?

Tests are green:
https://github.com/apostrophecms/testbed/actions/runs/9176562447

What are the specific steps to test this change?

Everything works as expected. There is just one fix to make for shortcuts that'll come in another PR.

What kind of change does this PR introduce?

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Build-related changes
  • Other

Make sure the PR fulfills these requirements:

  • It includes a) the existing issue ID being resolved, b) a convincing reason for adding this feature, or c) a clear description of the bug it resolves
  • The changelog is updated
  • Related documentation has been updated
  • Related tests have been updated

Copy link

linear bot commented May 14, 2024

@ValJed ValJed self-assigned this May 14, 2024
@ValJed ValJed marked this pull request as draft May 14, 2024 11:41
@ValJed ValJed changed the title adds pinia store for modals Gets rid of the double modals stack May 14, 2024
@ValJed ValJed changed the title Gets rid of the double modals stack Get rid of the double modals stack May 14, 2024
Copy link
Member

@boutell boutell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just questions for now.

@@ -17,6 +17,10 @@
<script>
import cuid from 'cuid';
import AposThemeMixin from 'Modules/@apostrophecms/ui/mixins/AposThemeMixin';
import { useModalStore } from 'Modules/@apostrophecms/ui/stores/modal';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much value is a new dependency on Pinia bringing? apos.modal.modals has been visible in the code as a property other modules might try to look at for a while now - can we maintain that interface to reduce backwards compatibility issues?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apos.modal.modals comes from the backend and is static data so we have no reason to put it does not move.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh right, never mind.

@ValJed ValJed force-pushed the pro-5818-get-rid-of-double-stacks branch from 373b970 to c4b3e17 Compare May 15, 2024 13:00
@@ -6,131 +6,72 @@
<component
v-bind="modal.props"
:is="modal.componentName"
v-for="modal in stack"
v-for="modal in store.stack"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting the stack from the store, dynamic.

if (!elementsToFocus.value.length) {
function cycleElementsToFocus(e, elements) {
const elems = elements || elementsToFocus.value;
if (!elems.length) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The power of the composable, modals want to pass elements because they come from the store. But in AposButtonSplit it simply uses the provided elementsToFocus from this composable.

});
}

// Returns true if el1 is "on top of" el2 in the
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this function is never used..
modals use the overlay click event to close themselves.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at AposTiptapAnchor.vue:

      v-click-outside-element="close"

This is used to edit links in rich text. Needs to keep working, so click-outside-element.js still needs to work, but could be factored to use the store.

@boutell boutell self-requested a review May 15, 2024 17:28
@ValJed ValJed force-pushed the pro-5818-get-rid-of-double-stacks branch 3 times, most recently from 30659c0 to 87a9bbb Compare May 21, 2024 14:29
@@ -6,7 +6,6 @@
@inactive="modal.active = false"
@show-modal="modal.showModal = true"
@esc="close"
@no-modal="$emit('safe-close')"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been removed because people using modals forget to call it.
The safe-close event is emitting in AposModal when it closes.
I kept the event no-modal to avoid BC.

const modal = apos.modal.getAt(index);
const properties = apos.modal.getProperties(modal.id);
const modal = this.getAt(index);
const properties = this.getProperties(modal.id);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would still work using apos.modal but more idiomatic way to use store.

// similar functionality. This is necessary because
// sometimes Vue removes elements from the DOM before
// we can examine their relationships.
function onTopOf(el1, el2) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method moved in store. Not sure it's used anymore since we use the overlay click to close a modal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See click-outside-element.js. Make sure that functionality does not break with this change.

apos.modal.getProperties = modalStore.getProperties;
apos.modal.onTopOf = modalStore.onTopOf;
apos.confirm = modalStore.confirm;
apos.alert = modalStore.alert;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We attach methods from the store. it's working well for function (can be used out of vue).
It's not for computed and refs. (That why I added the get function that allow to get all modals or one by ID).

}
store.updateModalData(props.modalId, { modalEl: modalEl.value });
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating instantiated Modal in the store (from TheAposModals) with data only available in this component. Allows to have only one array of modals.


function onTab(e) {
const currentModal = store.get(props.modalId);
cycleElementsToFocus(e, currentModal.elementsToFocus);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only triggered on tab.

@@ -258,21 +264,24 @@ function trapFocus() {
.map(addExcludingAttributes)
.join(', ');

elementsToFocus.value = [ ...modalEl.value.querySelectorAll(selector) ]
const elementsToFocus = [ ...modalEl.value.querySelectorAll(selector) ]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now store them in the modal in the store directly.

const properties = {
...this.modals
.find(modal => modal.componentName === stackModal.componentName &&
modal.props.moduleName === stackModal.props.moduleName)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic moved in the store.

@ValJed ValJed marked this pull request as ready for review May 22, 2024 12:58
@@ -6,7 +6,6 @@
@inactive="modal.active = false"
@show-modal="modal.showModal = true"
@esc="confirmAndCancel"
@no-modal="$emit('safe-close')"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad you found a way to eliminate this, I always considered it a code wart but wasn't sure how it could be eliminated.

// similar functionality. This is necessary because
// sometimes Vue removes elements from the DOM before
// we can examine their relationships.
function onTopOf(el1, el2) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See click-outside-element.js. Make sure that functionality does not break with this change.

});
}

// Returns true if el1 is "on top of" el2 in the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at AposTiptapAnchor.vue:

      v-click-outside-element="close"

This is used to edit links in rich text. Needs to keep working, so click-outside-element.js still needs to work, but could be factored to use the store.

@ValJed ValJed force-pushed the pro-5818-get-rid-of-double-stacks branch from c5d346a to 4d8b3a8 Compare May 27, 2024 09:54
@ValJed
Copy link
Contributor Author

ValJed commented May 27, 2024

@boutell The click outside feature is working well.
I just think that the function onTopOf that is used only for modals isn't used anymore because:

  • The directive isn't attached to any modal DOM element
  • Modals are close using esc or by clicking on tthe overlay, and each modal has its own overlay so it cannot close a modal that is below the current one.

I keep it for now, I didn't change any behavior about it, and this PR is big enough. But I'll make tests later to see if we can get rid of this onTopOf method.

@ValJed ValJed requested a review from boutell May 27, 2024 10:29
@ValJed ValJed merged commit 1959ef0 into main May 28, 2024
8 checks passed
@ValJed ValJed deleted the pro-5818-get-rid-of-double-stacks branch May 28, 2024 13:53
haroun added a commit that referenced this pull request May 28, 2024
* main:
  Get rid of the double modals stack (#4536)
  Add field access to the reactive document value (#4552)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants