Fix labels applied to a wrong issue in boards
What does this MR do?
Resolves #334465 (comment 665652425) AND #340068 (closed).
What was the cause of the bug?
The labels select has its own vuex store which has the following states:
state.labels
state.labelsFetched
Then the labels select itself accepts the prop selectedLabels
.
On mounting, the labels select initially displays the labels stored in selectedLabels
.
Then when a user opens a dropdown (and only then) calls the backend to fetch labels and updates
state.labels
and state.labelsFetched
to true
(see !65530 (merged)).
Now this design is very problematic when the labels select is used in the boards sidebar. Because an actual update request happens in board_sidebar_labels_select.vue
through apollo then the updated labels information is passed via selectedLabels
,
the labels select must be told to update state.labels
whenever selectedLabels
changes.
The mechanism for this is a watcher on selectedLabels
placed in the labels select component. Unfortunately, when the board sidebar is hidden, the labels select component is destroyed temporarily
and the watcher does not become activated on a re-mount. This has a particularly pernicious effect when the vuex store for the labels select is already initialized
(state.labelsFetched
is true
) because the vuex action fetchLabels()
will immediately return and state.labels
will become stale without the watcher.
Walkthrough
- User clicks on an issue card (for the first time)
- labels are fetched from the backend
-
board_sidebar_labels_select.vue
passes the labels info tolabels_select_root.vue
viaselectedLabels
- User updates the labels on the issue
- opening the dropdown triggers
fetchLabels()
eventually updatingstate.labels
and settingstate.labelsFetched
totrue
. (it's important to note that these are vuex states for the labels component, NOT the board).
- User closes the sidebar
- The sidebar is closed unmounting the labels select.
- User clicks on another issue card and re-opens the sidebar.
- When the sidebar is re-opened for the newly selected issue, the labels info for the issue is fetched then passed via
selectedLabels
but the watcher in labels_select_root.vue doesn't immediately trigger.
- User opens the labels dropdown
- Because
state.labelsFetched
is alreadytrue
,fetchLabels()
returns andstate.labels
has stale values that are then used in an update request.
Does this MR meet the acceptance criteria?
Conformity
-
I have included changelog trailers, or none are needed. (Does this MR need a changelog?) -
I have added/updated documentation, or it's not needed. (Is documentation required?) -
I have properly separated EE content from FOSS, or this MR is FOSS only. (Where should EE code go?) -
I have added information for database reviewers in the MR description, or it's not needed. (Does this MR have database related changes?) -
I have self-reviewed this MR per code review guidelines. -
This MR does not harm performance, or I have asked a reviewer to help assess the performance impact. (Merge request performance guidelines) -
I have followed the style guides. -
This change is backwards compatible across updates, or this does not apply.
Availability and Testing
-
I have added/updated tests following the Testing Guide, or it's not needed. (Consider all test levels. See the Test Planning Process.) -
I have tested this MR in all supported browsers, or it's not needed. -
I have informed the Infrastructure department of a default or new setting change per definition of done, or it's not needed.
Security
Does this MR contain changes to processing or storing of credentials or tokens, authorization and authentication methods or other items described in the security review guidelines? If not, then delete this Security section.
-
Label as security and @ mention @gitlab-com/gl-security/appsec
-
The MR includes necessary changes to maintain consistency between UI, API, email, or other methods -
Security reports checked/validated by a reviewer from the AppSec team