-
Notifications
You must be signed in to change notification settings - Fork 242
[Remove Vuetify from Studio] Send e-mail dialog #5487
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
base: unstable
Are you sure you want to change the base?
[Remove Vuetify from Studio] Send e-mail dialog #5487
Conversation
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.
Thanks so much for updating the EmailUsersDialog component. This is a good start so far. There’s still a couple of Vuetify components that can be removed. The VBtn and VCardText can be replaced with KButton and a div. There’s also a few user-facing strings that still need to be translated. The KModal title, the From and To labels within the form, “Subject line”, “Email body”, and the phrase “Add placeholder to message”, and all of the placeholder labels.
| </div> | ||
| <div class="email-textarea"> | ||
| <KTextbox | ||
| ref="message" |
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.
Now that this "message" ref references KTextbox, on line 261, we need to update it to include $el to avoid this error in the console:
"TypeError: Cannot read properties of null (reading 'focus')"
| <KTextbox | ||
| ref="message" | ||
| v-model="message" | ||
| :label="'Email body'" |
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.
The text for this label should be a translated string $tr
| :submitText="$tr('sendButton')" | ||
| :cancelText="$tr('cancelButton')" | ||
| data-test="email-dialog" | ||
| @submit="submit" |
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.
The method to send the email is named onSubmit , it should be updated here and on line 15 in the <form> as well.
| <KModal | ||
| v-if="show" | ||
| :size="600" | ||
| :title="'Send Email'" |
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 KModal title should be a translated string
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.
Administration plugin is an exception. Since it's used internally, we don't translate strings. A general rule of thumb is to preserve the original approach: If there is a translated string - use it, if there is an untranslated string - use it :)
| :showLabel="true" | ||
| :appearanceOverrides="getAppearanceOverrides(errors.subject)" | ||
| /> | ||
| <div class="caption grey--text">Add placeholder to message</div> |
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 phrase should be a translated string
| expect(wrapper.vm.showWarning).toBe(true); | ||
| }); | ||
|
|
||
| it('should not show warning when canceling with no draft content', async () => { |
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 a great addition to test for, thanks for including this!
| }, | ||
| handleClose() { | ||
| this.$emit('close'); | ||
| this.$emit('input'); |
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 shouldn't need to emit both close and input. I think in this case, only emitting close is more clear.
| 'studio-chip--active': isActive, | ||
| }" | ||
| :style="chipStyles" | ||
| @click="handleClick" |
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 div should be converted into a real button if it is meant to be interactive and clickable.
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.
thanks for the review @LianaHarris360 .I would like a suggestion on what to do here i think we can complelely get rid of the clickable feature . what are your thoughts on it .we will keep the kicon button clickable and the rest will be same?
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.
and if we want to make it interactive can u tell me how to apply hover and clickable effects to kbutton.This would be helpful in this and here
The VBtn and VCardText can be replaced with KButton and a div
I’ve replaced the VBtn and VCardText components with KButton and a div. However, I’m facing a bit of confusion while trying to apply the hover and clickable effects similar to those in VBtn. Could you please guide me through how to implement these interactions correctly or share a reference example where this has been done? It would be really helpful.
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 will add a bit more nuance:
(1) Whole-area-clickable chips
These need to be <button> s. To ensure proper a11y-related behaviors.
KButton is not suitable for this purpose. It's quite a different component compared to a chip-like-button. You can use native <button>.
(2) Chips with clear X button
I think that these would be best <div>s with the inner clear <button>.
Here KIconButton for X could be good, but if there are any specific challenges, raise them here please and we can decide if there's something we need to update in KDS, or if the native <button> would be more suitable.
| </slot> | ||
| </div> | ||
|
|
||
| <KIconButton |
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 icon button needs an accessible name attached to it, like ariaLabel ="Remove {username}", using the KIconButton ariaLabel prop.
I have a doubt related #5426 (comment) this.Here i was told that wrapped strings are not to be used in administraion.So please do tell what i need to do here in this context |
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.
Chiming in with some additional notes.
Overall congratulations on your first more complex issue. Overall nice work. All main features seem to be preserved Thanks for examining the current experience carefully.
| <KModal | ||
| v-if="show" | ||
| :size="600" | ||
| :title="'Send Email'" |
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.
Administration plugin is an exception. Since it's used internally, we don't translate strings. A general rule of thumb is to preserve the original approach: If there is a translated string - use it, if there is an untranslated string - use it :)
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.
For this file, I would recommend to take the same approach that I suggested in your other PR. For the same reasons.
| }); | ||
| }; | ||
|
|
||
| // Configure Testing Library to use data-test attributes |
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 appreciate that you were attentive to the current naming. This would better be done on the global configuration level though. And since we don't really yet have a pattern for VTL, you can remove it and use the default attribute. If I recall that's what most other VTL test suites use.
| expect(screen.queryByTestId('remove-chip')).not.toBeInTheDocument(); | ||
| }); | ||
|
|
||
| test('applies small class when small prop is 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.
There is no need to test for the presence of a class. It won't say that much about the resulting experience. Typically we just test markup, content, and logic.
Same applies to other similar tests in this file.
| 'studio-chip--active': isActive, | ||
| }" | ||
| :style="chipStyles" | ||
| @click="handleClick" |
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 will add a bit more nuance:
(1) Whole-area-clickable chips
These need to be <button> s. To ensure proper a11y-related behaviors.
KButton is not suitable for this purpose. It's quite a different component compared to a chip-like-button. You can use native <button>.
(2) Chips with clear X button
I think that these would be best <div>s with the inner clear <button>.
Here KIconButton for X could be good, but if there are any specific challenges, raise them here please and we can decide if there's something we need to update in KDS, or if the native <button> would be more suitable.
| }, | ||
| }, | ||
| mounted() { | ||
| document.addEventListener('click', this.handleClickOutside); |
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 is quite unusual to add event listener to style active/inactive state. What was the reason for doing it in this way? Have you tried to use common hover and focus styling approaches?
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.
Thanks @MisRob — you’re right, typically hover/focus styling would handle active/inactive states more cleanly.
In this case, the event listener was added to detect clicks outside the component to toggle the isActive state off when the user clicks elsewhere on the page. This was mainly done to simulate a “chip selection”interaction where the chip remains active after being clicked, and only deactivates when the user clicks outside of it.
However, I agree that for purely visual feedback (like hover/focus), CSS pseudo-classes would be more appropriate. I can refactor it to use CSS states for hover/focus, and only keep the event listener if we still need outside-click detection for interaction purposes.
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.
Thanks for explaining. @Prashant-thakur77. I think it'd be a bit more suitable to use state for what you're trying to achieve, but perhaps we don't even need it. For now let's just use CSS and remove the event listener completely. We will then preview and see.
contentcuration/contentcuration/frontend/administration/pages/Users/EmailUsersDialog.vue
Show resolved
Hide resolved
| margin: 2px; | ||
| } | ||
| /* Custom layout styles to replace Vuetify flex system */ |
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 wouldn't be meaningful to have a copy of Vuetify utilities in this specific file. They are used across the whole Studio, and at some point, we may actually remove them. Please delete these copies and just apply styles to containing elements without using the utilities, in a similar way you do above this section.
| :showLabel="true" | ||
| :appearanceOverrides="getAppearanceOverrides(errors.subject)" | ||
| /> | ||
| <div class="caption grey--text">Add placeholder to message</div> |
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.
Would you remove all these Vuetify helpers classes?
Relatedly, for color-related ones, such as here grey--text, KDS theme tokens and palette approach needs to be used instead.
Please revisit the whole file.
| return { | ||
| ...baseStyles, | ||
| focusBorderColor: this.$themeTokens.error, | ||
| focusBoxShadow: `0 0 0 2px ${this.$themeTokens.error}33`, |
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.
Do these focus... take effect actually?
Also, I think it'd be fine, and even better for consistency, to just go with the default error state for KTextbox.
Perhaps you can upload a screenshot of what you're trying to achieve and explain why, and then we can decide.
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 agree it makes sense to stay consistent with the default KTextbox error state and avoid introducing separate handling unless absolutely necessary.Will update it
Fixes #5425
Summary
This PR completes the removal of Vuetify from the Send Email dialog as part of the larger Vuetify migration effort (#5060). The dialog now uses Kolibri Design System components exclusively while maintaining all existing functionality.
Changes Made:
✅ Replaced VDialog and ConfirmationDialog with KModal
✅ Replaced VFlex and VLayout with custom CSS flex styles
✅ Replaced VForm with native form element
✅ Replaced VTextField and VTextarea with KTextbox
✅ Replaced VTooltip with KTooltip
✅ Implemented form validation using generateFormMixin
✅ Created new StudioChip component to replace VChip



References
Sub-issue of #5060.
Reviewer guidance
Login as [email protected] with password a
Go to Administration > Users
Select few users in the table
Click Email
Visual Changes:
Minor styling differences due to KDS vs Vuetify
Consistent with Kolibri Design System patterns
Maintains all existing functionality