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

Have KModal pass through their 'submit' and 'cancel' events to simplify other modals #5439

Merged
4 changes: 2 additions & 2 deletions kolibri/core/assets/src/views/CoreBase/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@
:msg="mostRecentNotification.msg"
:linkText="mostRecentNotification.linkText"
:linkUrl="mostRecentNotification.linkUrl"
@closeModal="dismissUpdateModal"
@submit="dismissUpdateModal"
/>
<LanguageSwitcherModal
v-if="languageModalShown"
:style="{ color: $coreTextDefault }"
@close="languageModalShown = false"
@cancel="languageModalShown = false"
/>

</div>
Expand Down
15 changes: 15 additions & 0 deletions kolibri/core/assets/src/views/KModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,13 @@
<script>

import themeMixin from 'kolibri.coreVue.mixins.themeMixin';
import logger from 'kolibri.lib.logging';
import responsiveWindow from 'kolibri.coreVue.mixins.responsiveWindow';
import debounce from 'lodash/debounce';
import KButton from 'kolibri.coreVue.components.KButton';

const logging = logger.getLogger(__filename);

/**
* Used to focus attention on a singular action/task
*/
Expand Down Expand Up @@ -189,6 +192,18 @@
return { 'max-height': `${this.maxContentHeight}px` };
},
},
created() {
if (this.$props.cancelText && !this.$listeners.cancel) {
logging.warn(
'A "cancelText" has been set, but there is no "cancel" listener. The "cancel" button may not work correctly.'
);
}
if (this.$props.submitText && !this.$listeners.submit) {
logging.warn(
'A "submitText" has been set, but there is no "submit" listener. The "submit" button may not work correctly.'
);
}
},
beforeMount() {
this.lastFocus = document.activeElement;
},
Expand Down
2 changes: 1 addition & 1 deletion kolibri/core/assets/src/views/SideNav.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>

<div ref="sideNav" class="side-nav-wrapper" @keydown.esc="toggleNav">
<div ref="sideNav" class="side-nav-wrapper" @keyup.esc="toggleNav">
<transition name="side-nav">
<div
v-show="navShown"
Expand Down
2 changes: 1 addition & 1 deletion kolibri/core/assets/src/views/UpdateNotification.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
this.saveDismissedNotification(this.id);
}
this.removeNotification(this.id);
this.$emit('closeModal');
this.$emit('submit');
Copy link
Contributor

Choose a reason for hiding this comment

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

is it necessary to emit anything here? I think the v-on will do this for you?

},
},
$trs: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
>
<slot v-if="$slots.default"></slot>
<template v-else>
{{ text }}
<span>{{ text }}</span>
</template>
<mat-svg
v-if="hasDropdown"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<LanguageSwitcherModal
v-if="showLanguageModal"
class="ta-l"
@close="showLanguageModal = false"
@cancel="showLanguageModal = false"
/>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
:title="$tr('changeLanguageModalHeader')"
:submitText="$tr('confirmButtonText')"
:cancelText="$tr('cancelButtonText')"
@cancel="$emit('cancel')"
@submit="setLang"
@cancel="closeModal"
>
<KGrid>
<KGridItem
Expand Down Expand Up @@ -66,9 +66,6 @@
},
},
methods: {
closeModal() {
this.$emit('close');
},
setLang() {
this.switchLanguage(this.selectedLanguage);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
:hasError="false"
:submitText="$tr('remove')"
:cancelText="$tr('cancel')"
@submit="$emit('confirm')"
@cancel="$emit('cancel')"
@submit="$emit('submit')"
>
<p>
{{ $tr('confirmation', { username: username, classname: groupName }) }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
:groupName="currentGroup.name"
:username="userForRemoval.full_name"
@cancel="userForRemoval = null"
@confirm="removeSelectedUserFromGroup"
@submit="removeSelectedUserFromGroup"
/>
</div>
</KPageContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
:submitText="$tr('save')"
:cancelText="$tr('cancel')"
:submitDisabled="submitting"
@cancel="$emit('cancel')"
@submit="callCreateGroup"
@cancel="close"
>
<KTextbox
ref="name"
Expand Down Expand Up @@ -82,21 +82,18 @@
},
},
methods: {
...mapActions('groups', ['displayModal', 'createGroup']),
...mapActions('groups', ['createGroup']),
callCreateGroup() {
this.formSubmitted = true;
if (this.formIsValid) {
this.submitting = true;
this.createGroup({ groupName: this.name, classId: this.classId }).then(() => {
this.$emit('success');
this.$emit('submit');
Copy link
Contributor

Choose a reason for hiding this comment

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

won't this emit submit twice? Once for v-on="$listeners" and once here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

CreateGroupModal only emits 'submit' once. I think if you explicitly set a @submit=customListener, it sort of overwrites the {submit: parentListener} hidden in v-on="$listeners

Copy link
Contributor Author

@jonboiser jonboiser May 17, 2019

Choose a reason for hiding this comment

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

Interestingly, though, if you remove this $emit, the event from CreateGroupModal does not appear in the devtools, but it seems that it still goes through the GroupsPage, which is not really what I want since i want to wait till the promise is resolved before emitting 'submit'.

I'm just going to remove the v-on="listeners" for the handful of modals that might emit the same event asynchronously.

In the future, I would like to to remove async behavior API calls from modals, and delegate them to the parents of modals. So modals just synchronously emit events and data, basically.

Copy link
Contributor

@indirectlylit indirectlylit May 17, 2019

Choose a reason for hiding this comment

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

yeah that seems reasonable.

another alternative is for modals that handle their own internal async code, to explicitly emit an event that's not submit or cancel. For example:

.then(() => this.$emit('finished'))

});
} else {
this.$refs.name.focus();
}
},
close() {
this.displayModal(false);
},
},
$trs: {
newLearnerGroup: 'Create new group',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
:submitText="$tr('deleteGroup')"
:cancelText="$tr('cancel')"
@submit="handleSubmit"
@cancel="close"
@cancel="$emit('cancel')"
>
<p>{{ $tr('areYouSure', { groupName: groupName }) }}</p>
</KModal>
Expand Down Expand Up @@ -34,15 +34,12 @@
},
},
methods: {
...mapActions('groups', ['displayModal', 'deleteGroup']),
...mapActions('groups', ['deleteGroup']),
handleSubmit() {
this.deleteGroup(this.groupId).then(() => {
this.$emit('success');
this.$emit('submit');
});
},
close() {
this.displayModal(false);
},
},
$trs: {
deleteLearnerGroup: 'Delete group',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
:cancelText="$tr('cancel')"
:submitDisabled="submitting"
@submit="callRenameGroup"
@cancel="close"
@cancel="$emit('cancel')"
>
<KTextbox
ref="name"
Expand Down Expand Up @@ -92,7 +92,7 @@
},
},
methods: {
...mapActions('groups', ['renameGroup', 'displayModal']),
...mapActions('groups', ['renameGroup']),
callRenameGroup() {
this.formSubmitted = true;
if (this.formIsValid) {
Expand All @@ -105,9 +105,6 @@
this.$refs.name.focus();
}
},
close() {
this.displayModal(false);
},
},
$trs: {
renameLearnerGroup: 'Rename group',
Expand Down
10 changes: 8 additions & 2 deletions kolibri/plugins/coach/assets/src/views/plan/GroupsPage/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,24 @@
<CreateGroupModal
v-if="showCreateGroupModal"
:groups="sortedGroups"
@success="handleSuccessCreateGroup"
@submit="handleSuccessCreateGroup"
@cancel="closeModal"
/>

<RenameGroupModal
v-if="showRenameGroupModal"
:groupName="selectedGroup.name"
:groupId="selectedGroup.id"
:groups="sortedGroups"
@cancel="closeModal"
/>

<DeleteGroupModal
v-if="showDeleteGroupModal"
:groupName="selectedGroup.name"
:groupId="selectedGroup.id"
@success="handleSuccessDeleteGroup"
@submit="handleSuccessDeleteGroup"
@cancel="closeModal"
/>

</KPageContainer>
Expand Down Expand Up @@ -125,6 +128,9 @@
methods: {
...mapActions('groups', ['displayModal']),
...mapActions(['createSnackbar']),
closeModal() {
this.displayModal(false);
},
openCreateGroupModal() {
this.displayModal(GroupModals.CREATE_GROUP);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
:title="modalTitle"
:submitText="coachStrings.$tr('continueAction')"
:cancelText="coachStrings.$tr('cancelAction')"
@cancel="$emit('cancel')"
@submit="goToAvailableGroups"
@cancel="$emit('cancel')"
>
<KRadioButton
v-for="classroom in availableClassrooms"
Expand All @@ -27,8 +27,8 @@
:title="modalTitle"
:submitText="coachStrings.$tr('copyAction')"
:cancelText="coachStrings.$tr('cancelAction')"
@cancel="$emit('cancel')"
@submit="$emit('submit', selectedClassroomId, selectedCollectionIds)"
@cancel="$emit('cancel')"
>
<p>{{ $tr('destinationExplanation', { classroomName: selectedClassroomName }) }}</p>
<p>{{ assignmentQuestion }}</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,36 @@ const defaultProps = {
function makeWrapper(options) {
const wrapper = mount(AssignmentDeleteModal, options);
const els = {
submitButton: () => wrapper.find('button[type="submit"]'),
cancelButton: () => wrapper.find('button[type="button"]'),
form: () => wrapper.find('form'),
};
return { wrapper, els };
}

describe('AssignmentDeleteModal', () => {
it('clicking delete causes a "delete" event to be emitted', () => {
const { wrapper, els } = makeWrapper({
it('clicking delete causes a "submit" event to be emitted', () => {
const submitListener = jest.fn();
const { els } = makeWrapper({
propsData: { ...defaultProps },
store,
listeners: {
submit: submitListener,
},
});
// Again, clicking the submit button does not propagate to form, so doing a hack
// els.submitButton().trigger('click');
els.form().trigger('submit');
expect(wrapper.emitted().submit.length).toEqual(1);
expect(submitListener).toHaveBeenCalled();
});

it('clicking cancel causes a "cancel" event to be emitted', () => {
const { wrapper, els } = makeWrapper({
const cancelListener = jest.fn();
const { els } = makeWrapper({
propsData: { ...defaultProps },
store,
listeners: {
cancel: cancelListener,
},
});
els.cancelButton().trigger('click');
expect(wrapper.emitted().cancel.length).toEqual(1);
expect(cancelListener).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
:submitDisabled="formIsDisabled"
:cancelDisabled="formIsDisabled"
@submit="submitForm"
@cancel="$emit('closemodal')"
@cancel="$emit('cancel')"
>
<p>{{ $tr('tokenExplanation') }}</p>

Expand Down Expand Up @@ -80,9 +80,9 @@
// tokens can return one or more channels
if (channels.length > 1) {
this.setAvailableChannels(channels);
this.$emit('closemodal');
this.$emit('cancel');
} else {
this.$emit('channelfound', channels[0]);
this.$emit('submit', channels[0]);
}
})
.catch(error => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
>
<ChannelTokenModal
v-if="showTokenModal"
@closemodal="showTokenModal=false"
@channelfound="goToSelectContentPageForChannel"
@cancel="showTokenModal=false"
@submit="goToSelectContentPageForChannel"
/>
<span>{{ $tr('channelNotListedExplanation') }}&nbsp;</span>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<transition name="delay-entry">
<WelcomeModal
v-if="welcomeModalVisible"
@closeModal="hideWelcomeModal"
@submit="hideWelcomeModal"
/>
</transition>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<DeleteChannelModal
v-if="channelIsSelected"
:channelTitle="selectedChannelTitle"
@confirm="handleDeleteChannel"
@submit="handleDeleteChannel"
@cancel="selectedChannelId=null"
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
:title="$tr('title')"
:submitText="$tr('confirmButtonLabel')"
:cancelText="$tr('cancelButtonLabel')"
@submit="handleClickConfirm"
@cancel="handleClickCancel"
@submit="$emit('submit')"
@cancel="$emit('cancel')"
>
<p>{{ $tr('confirmationQuestion', { channelTitle }) }}</p>
</KModal>
Expand All @@ -28,14 +28,6 @@
required: true,
},
},
methods: {
handleClickCancel() {
this.$emit('cancel');
},
handleClickConfirm() {
this.$emit('confirm');
},
},
$trs: {
confirmationQuestion: `Are you sure you want to delete '{ channelTitle }' from your device?`,
title: 'Delete channel',
Expand Down
Loading