Skip to content

Commit

Permalink
Merge pull request #12589 from nathanaelg16/use_snackbar
Browse files Browse the repository at this point in the history
Creating useSnackbar composable and replacing existing logic with it
  • Loading branch information
rtibbles committed Aug 28, 2024
2 parents bbeea3b + c7418f7 commit cef47b7
Show file tree
Hide file tree
Showing 52 changed files with 434 additions and 186 deletions.
85 changes: 85 additions & 0 deletions kolibri/core/assets/src/composables/__mocks__/useSnackbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* `useSnackbar` composable function mock.
*
* If default values are sufficient for tests,
* you only need call `jest.mock('<useSnackbar file path>')`
* at the top of a test file.
*
* If you need to override some default values for some tests,
* or if you need to inspect the state of the refs during tests,
* you can import a helper function `useSnackbarMock` that accepts
* an object with values to be overriden and use it together
* with `mockImplementation` as follows:
*
* ```
* // eslint-disable-next-line import/named
* import useSnackbar, { useSnackbarMock } from '<useSnackbar file path>';
*
* jest.mock('<useSnackbar file path>')
* describe('describe test', function () {
* let snackbar = { snackbarIsVisible: ref(false) }
*
* beforeAll(() => {
* useSnackbar.mockImplementation(() => useSnackbarMock(snackbar)
* })
*
* it('the test', () => {
* expect(get(snackbar.snackbarIsVisible)).toEqual(false);
* )
* })
* ```
*/
import { ref } from 'kolibri.lib.vueCompositionApi';
import { get, set } from '@vueuse/core';

const MOCK_DEFAULTS = {
snackbarIsVisible: ref(false),
snackbarOptions: ref({
text: '',
autoDismiss: true,
}),
};

export function useSnackbarMock(overrides = {}) {
const mocks = {
...MOCK_DEFAULTS,
...overrides,
};

const createSnackbar = (options = {}) => {
// reset
set(mocks.snackbarIsVisible, false);
set(mocks.snackbarOptions, {});

// set new options
set(mocks.snackbarIsVisible, true);

// options include text, autoDismiss, duration, actionText, actionCallback,
// hideCallback, bottomPosition
// if the options are a string, set it as the snackbar text
// and default autoDismiss to true
if (typeof options === 'string') {
set(mocks.snackbarOptions, { text: options, autoDismiss: true });
} else {
set(mocks.snackbarOptions, options);
}
};

const clearSnackbar = () => {
set(mocks.snackbarIsVisible, false);
set(mocks.snackbarOptions, {});
};

const setSnackbarText = text => {
set(mocks.snackbarOptions, { ...get(mocks.snackbarOptions), text });
};

return {
createSnackbar,
clearSnackbar,
setSnackbarText,
...mocks,
};
}

export default jest.fn(() => useSnackbarMock());
49 changes: 49 additions & 0 deletions kolibri/core/assets/src/composables/useSnackbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ref } from 'kolibri.lib.vueCompositionApi';
import { get, set } from '@vueuse/core';

const snackbarIsVisible = ref(false);
const snackbarOptions = ref({
text: '',
autoDismiss: true,
});

export default function useSnackbar() {
const createSnackbar = (options = {}) => {
// reset
set(snackbarIsVisible, false);
set(snackbarOptions, {});

// set new options
set(snackbarIsVisible, true);

// options include text, autoDismiss, duration, actionText, actionCallback,
// hideCallback, bottomPosition
// if the options are a string, set it as the snackbar text
// and default autoDismiss to true
if (typeof options === 'string') {
set(snackbarOptions, { text: options, autoDismiss: true });
} else {
set(snackbarOptions, options);
}
};

const clearSnackbar = () => {
set(snackbarIsVisible, false);
set(snackbarOptions, {});
};

const setSnackbarText = text => {
set(snackbarOptions, { ...get(snackbarOptions), text });
};

return {
// state
snackbarIsVisible,
snackbarOptions,

// mutators
createSnackbar,
clearSnackbar,
setSnackbarText,
};
}
2 changes: 2 additions & 0 deletions kolibri/core/assets/src/core-app/apiSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ import NotificationsRoot from '../views/NotificationsRoot';
import useMinimumKolibriVersion from '../composables/useMinimumKolibriVersion';
import useUserSyncStatus from '../composables/useUserSyncStatus';
import useUser from '../composables/useUser';
import useSnackbar from '../composables/useSnackbar';
import { registerNavItem } from '../composables/useNav';
import useNow from '../composables/useNow';

Expand Down Expand Up @@ -202,6 +203,7 @@ export default {
useNow,
useUser,
useUserSyncStatus,
useSnackbar,
},
},
resources,
Expand Down
16 changes: 10 additions & 6 deletions kolibri/core/assets/src/disconnection.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createTranslator } from 'kolibri.utils.i18n';
import { get } from '@vueuse/core';
import useSnackbar from 'kolibri.coreVue.composables.useSnackbar';
import useConnection from './composables/useConnection';

export const trs = createTranslator('DisconnectionSnackbars', {
Expand All @@ -24,8 +25,9 @@ export const trs = createTranslator('DisconnectionSnackbars', {
},
});

export function createTryingToReconnectSnackbar(store) {
store.commit('CORE_CREATE_SNACKBAR', {
export function createTryingToReconnectSnackbar() {
const { createSnackbar } = useSnackbar();
createSnackbar({
text: trs.$tr('tryingToReconnect'),
backdrop: true,
autoDismiss: false,
Expand All @@ -42,7 +44,8 @@ export function createDisconnectedSnackbar(store, beatCallback) {
const { reconnectTime } = useConnection();
setDynamicReconnectTime(get(reconnectTime));
// create snackbar
store.commit('CORE_CREATE_SNACKBAR', {
const { createSnackbar, setSnackbarText } = useSnackbar();
createSnackbar({
text: generateDisconnectedSnackbarText(),
actionText: trs.$tr('tryNow'),
actionCallback: beatCallback,
Expand All @@ -53,7 +56,7 @@ export function createDisconnectedSnackbar(store, beatCallback) {
// start timeout
timer = setInterval(() => {
setDynamicReconnectTime(dynamicReconnectTime - 1);
store.commit('CORE_SET_SNACKBAR_TEXT', generateDisconnectedSnackbarText());
setSnackbarText(generateDisconnectedSnackbarText());
}, 1000);
}

Expand All @@ -73,7 +76,8 @@ function clearTimer() {
}
}

export function createReconnectedSnackbar(store) {
export function createReconnectedSnackbar() {
clearTimer();
store.dispatch('createSnackbar', trs.$tr('successfullyReconnected'));
const { createSnackbar } = useSnackbar();
createSnackbar(trs.$tr('successfullyReconnected'));
}
2 changes: 1 addition & 1 deletion kolibri/core/assets/src/heartbeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export class HeartBeat {
_setConnected() {
set(this._connection.connected, true);
set(this._connection.reconnectTime, null);
createReconnectedSnackbar(store);
createReconnectedSnackbar();
if (get(this._connection.reloadOnReconnect)) {
// If we were disconnected while loading, we need to reload the page
// to ensure that we are in a consistent state.
Expand Down
6 changes: 4 additions & 2 deletions kolibri/core/assets/src/mixins/commonCoreStrings.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import camelCase from 'lodash/camelCase';
import get from 'lodash/get';
import invert from 'lodash/invert';
import * as METADATA from 'kolibri.coreVue.vuex.constants';
import useSnackbar from 'kolibri.coreVue.composables.useSnackbar';
import notificationStrings from './notificationStrings';

export const coreStrings = createTranslator('CommonCoreStrings', {
Expand Down Expand Up @@ -1609,14 +1610,15 @@ export default {
* `CORE_CREATE_SNACKBAR` mutation.
*/
showSnackbarNotification(key, args, coreCreateSnackbarArgs) {
const { createSnackbar } = useSnackbar();
const text = notificationStrings.$tr(key, args || {});
if (coreCreateSnackbarArgs) {
this.$store.commit('CORE_CREATE_SNACKBAR', {
createSnackbar({
...coreCreateSnackbarArgs,
text,
});
} else {
this.$store.dispatch('createSnackbar', text);
createSnackbar(text);
}
},
},
Expand Down
9 changes: 0 additions & 9 deletions kolibri/core/assets/src/state/modules/core/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,6 @@ export function fetchPoints(store) {
}
}

// Creates a snackbar that automatically dismisses and has no action buttons.
export function createSnackbar(store, text) {
store.commit('CORE_CREATE_SNACKBAR', { text, autoDismiss: true });
}

export function clearSnackbar(store) {
store.commit('CORE_CLEAR_SNACKBAR');
}

export function loading(store) {
return new Promise(resolve => {
store.commit('CORE_SET_PAGE_LOADING', true);
Expand Down
2 changes: 0 additions & 2 deletions kolibri/core/assets/src/state/modules/core/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import sessionModule from '../session';
import snackbarModule from '../snackbar';
import * as getters from './getters';
import * as actions from './actions';
import mutations from './mutations';
Expand Down Expand Up @@ -29,6 +28,5 @@ export default {
mutations,
modules: {
session: sessionModule,
snackbar: snackbarModule,
},
};
36 changes: 0 additions & 36 deletions kolibri/core/assets/src/state/modules/snackbar.js

This file was deleted.

7 changes: 5 additions & 2 deletions kolibri/core/assets/src/views/CoreSnackbar/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@

<script>
import { mapActions } from 'vuex';
import UiSnackbar from 'kolibri-design-system/lib/keen/UiSnackbar.vue';
import Backdrop from 'kolibri.coreVue.components.Backdrop';
import useSnackbar from 'kolibri.coreVue.composables.useSnackbar';
/* Snackbars are used to display notification. */
export default {
Expand All @@ -51,6 +51,10 @@
Backdrop,
UiSnackbar,
},
setup() {
const { clearSnackbar } = useSnackbar();
return { clearSnackbar };
},
props: {
/* Text of notification to be displayed */
text: {
Expand Down Expand Up @@ -119,7 +123,6 @@
}
},
methods: {
...mapActions(['clearSnackbar']),
hideSnackbar() {
this.isVisible = false;
this.$emit('hide');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

<script>
import useSnackbar from 'kolibri.coreVue.composables.useSnackbar';
import AddDeviceForm from './AddDeviceForm';
import SelectDeviceForm from './SelectDeviceForm';
Expand All @@ -37,6 +38,10 @@
AddDeviceForm,
SelectDeviceForm,
},
setup() {
const { createSnackbar } = useSnackbar();
return { createSnackbar };
},
props: {
// Channel filter only needed on ManageContentPage/SelectNetworkDeviceModal
filterByChannelId: {
Expand Down Expand Up @@ -74,9 +79,6 @@
};
},
methods: {
createSnackbar(args) {
this.$store.dispatch('createSnackbar', args);
},
goToAddAddress() {
this.addedAddressId = '';
this.addingAddress = true;
Expand Down
Loading

0 comments on commit cef47b7

Please sign in to comment.