diff --git a/kolibri/plugins/user_profile/frontend/composables/useCurrentUser.js b/kolibri/plugins/user_profile/frontend/composables/useCurrentUser.js index d3e77b517dc..8c7afc465a4 100644 --- a/kolibri/plugins/user_profile/frontend/composables/useCurrentUser.js +++ b/kolibri/plugins/user_profile/frontend/composables/useCurrentUser.js @@ -1,24 +1,17 @@ -import { ref, onMounted } from 'vue'; +import { computed, onMounted } from 'vue'; import FacilityUserResource from 'kolibri-common/apiResources/FacilityUserResource'; import useUser from 'kolibri/composables/useUser'; -import { get } from '@vueuse/core'; // A usable that returns the Facility user tied to the session export default function useCurrentUser() { const { currentUserId } = useUser(); - const currentUser = ref({}); - const isLoading = ref(false); + const { data, loading, fetchData } = FacilityUserResource.useRetrieve(currentUserId); - onMounted(() => { - isLoading.value = true; - return FacilityUserResource.fetchModel({ id: get(currentUserId) }).then(userModel => { - currentUser.value = { ...userModel }; - isLoading.value = false; - }); - }); + onMounted(fetchData); return { - currentUser, - isLoading, + // The template reads fields off this object directly, so the pre-fetch null needs a stand-in. + currentUser: computed(() => data.value || {}), + isLoading: loading, }; } diff --git a/kolibri/plugins/user_profile/frontend/machines/changeFacilityMachine.js b/kolibri/plugins/user_profile/frontend/machines/changeFacilityMachine.js index 1f67348b311..c4f382fdab1 100644 --- a/kolibri/plugins/user_profile/frontend/machines/changeFacilityMachine.js +++ b/kolibri/plugins/user_profile/frontend/machines/changeFacilityMachine.js @@ -293,14 +293,7 @@ const states = { }, fetchSourceFacilityUsers: { invoke: { - src: context => { - return FacilityUserResource.fetchCollection({ - getParams: { member_of: context.sourceFacility }, - force: true, - }).then(users => { - return users; - }); - }, + src: context => FacilityUserResource.list({ member_of: context.sourceFacility }), onDone: { target: 'checkFacilityHasNoMoreUsers', actions: [setSourceFacilityUsers], diff --git a/kolibri/plugins/user_profile/frontend/modules/profile/actions.js b/kolibri/plugins/user_profile/frontend/modules/profile/actions.js index 9ad1ad924c6..295006c213f 100644 --- a/kolibri/plugins/user_profile/frontend/modules/profile/actions.js +++ b/kolibri/plugins/user_profile/frontend/modules/profile/actions.js @@ -10,20 +10,12 @@ export function updateUserProfile(store, { updates }) { const { currentUserId, setSession } = useUser(); - return FacilityUserResource.saveModel({ - id: get(currentUserId), - data: updates, - exists: true, - }).then(() => { + return FacilityUserResource.update(get(currentUserId), updates).then(() => { setSession({ session: updates }); }); } export function updateUserProfilePassword(store, password) { const { currentUserId } = useUser(); - return FacilityUserResource.saveModel({ - id: get(currentUserId), - data: { password }, - exists: true, - }); + return FacilityUserResource.update(get(currentUserId), { password }); } diff --git a/kolibri/plugins/user_profile/frontend/views/ChangeFacility/ConfirmChangeFacility.vue b/kolibri/plugins/user_profile/frontend/views/ChangeFacility/ConfirmChangeFacility.vue index 92ae712176d..69d25eb4bb3 100644 --- a/kolibri/plugins/user_profile/frontend/views/ChangeFacility/ConfirmChangeFacility.vue +++ b/kolibri/plugins/user_profile/frontend/views/ChangeFacility/ConfirmChangeFacility.vue @@ -82,12 +82,7 @@ }, }, created() { - FacilityUserResource.fetchCollection({ - force: true, - getParams: { - member_of: this.state.sourceFacility, - }, - }).then(users => { + FacilityUserResource.list({ member_of: this.state.sourceFacility }).then(users => { if (Object.keys(users).length === 1) { this.lastUserOnDevice = true; } diff --git a/kolibri/plugins/user_profile/frontend/views/ChangeFacility/MergeFacility.vue b/kolibri/plugins/user_profile/frontend/views/ChangeFacility/MergeFacility.vue index 471d2045b6d..f6b2cbb2958 100644 --- a/kolibri/plugins/user_profile/frontend/views/ChangeFacility/MergeFacility.vue +++ b/kolibri/plugins/user_profile/frontend/views/ChangeFacility/MergeFacility.vue @@ -169,7 +169,7 @@ function pollTask() { if (taskId.value === null) { // first, try to see if there's already one running - TaskResource.fetchCollection() + TaskResource.list() .then(allTasks => { const tasks = allTasks.filter( t => t.type === 'kolibri.plugins.user_profile.tasks.mergeuser', @@ -236,13 +236,13 @@ isPolling = false; }); } else { - TaskResource.fetchModel({ id: taskId.value, force: true }) + TaskResource.retrieve(taskId.value) .then(startedTask => { task.value = startedTask; if (startedTask.status == TaskStatuses.COMPLETED) { isPolling = false; } else if (startedTask.status === TaskStatuses.FAILED) { - TaskResource.clear(taskId.value); // start a new one + TaskResource.clear_v2(taskId.value); // start a new one isTaskRequested = false; taskError.value = true; } @@ -274,7 +274,7 @@ function to_finish() { const token = task.value.extra_metadata.token; - TaskResource.clear(taskId.value); + TaskResource.clear_v2(taskId.value); changeFacilityService.send({ type: 'FINISH' }); // use the token to login in the device using the new user in the target facility const params = { @@ -302,7 +302,7 @@ function to_retry() { if (taskId.value !== null) { - TaskResource.clear(taskId.value); + TaskResource.clear_v2(taskId.value); } taskError.value = false; changeFacilityService.send('TASKERROR'); diff --git a/kolibri/plugins/user_profile/frontend/views/ChangeFacility/SelectFacility.vue b/kolibri/plugins/user_profile/frontend/views/ChangeFacility/SelectFacility.vue index 464e816bf70..8158f974ee3 100644 --- a/kolibri/plugins/user_profile/frontend/views/ChangeFacility/SelectFacility.vue +++ b/kolibri/plugins/user_profile/frontend/views/ChangeFacility/SelectFacility.vue @@ -122,7 +122,7 @@ const fetchDeviceFacilities = useMemoize( async device => { try { - const { facilities } = await NetworkLocationResource.fetchFacilities(device.id); + const { facilities } = await NetworkLocationResource.fetchFacilities_v2(device.id); return facilities.map(facility => { return { diff --git a/kolibri/plugins/user_profile/frontend/views/ChangeFacility/__tests__/MergeFacility.spec.js b/kolibri/plugins/user_profile/frontend/views/ChangeFacility/__tests__/MergeFacility.spec.js index 2b390467a69..09ffde93a59 100644 --- a/kolibri/plugins/user_profile/frontend/views/ChangeFacility/__tests__/MergeFacility.spec.js +++ b/kolibri/plugins/user_profile/frontend/views/ChangeFacility/__tests__/MergeFacility.spec.js @@ -12,10 +12,10 @@ jest.mock('kolibri/client'); jest.mock('kolibri/urls'); jest.mock('kolibri/utils/redirectBrowser'); jest.mock('kolibri/apiResources/TaskResource', () => ({ - fetchModel: jest.fn(), - fetchCollection: jest.fn(), + retrieve: jest.fn(), + list: jest.fn(), startTask: jest.fn(), - clear: jest.fn(), + clear_v2: jest.fn(), })); const TARGET_FACILITY_NAME = 'Test Facility'; @@ -70,7 +70,7 @@ describe(`ChangeFacility/ConfirmMerge`, () => { beforeEach(() => { jest.clearAllMocks(); sessionStorage.clear(); - TaskResource.fetchModel.mockResolvedValue(task); + TaskResource.retrieve.mockResolvedValue(task); setTimeoutSpy = jest.spyOn(global, 'setTimeout').mockImplementation(() => 0); }); @@ -84,7 +84,7 @@ describe(`ChangeFacility/ConfirmMerge`, () => { }); it(`finish button does not appear if the task is not completed`, async () => { - TaskResource.fetchModel.mockResolvedValue(incompleteTask); + TaskResource.retrieve.mockResolvedValue(incompleteTask); renderComponent(); await flushUi(); @@ -92,7 +92,7 @@ describe(`ChangeFacility/ConfirmMerge`, () => { }); it(`when the task is completed, finish button appears`, async () => { - TaskResource.fetchModel.mockResolvedValue(completedTask); + TaskResource.retrieve.mockResolvedValue(completedTask); renderComponent(); await flushUi(); @@ -103,7 +103,7 @@ describe(`ChangeFacility/ConfirmMerge`, () => { }); it(`clicking finish button sends the finish event to the state machine`, async () => { - TaskResource.fetchModel.mockResolvedValue(completedTask); + TaskResource.retrieve.mockResolvedValue(completedTask); client.mockResolvedValue({ data: { picture_password: null } }); renderComponent(); @@ -118,7 +118,7 @@ describe(`ChangeFacility/ConfirmMerge`, () => { }); it('stores picture password in sessionStorage and redirects when picture password is assigned', async () => { - TaskResource.fetchModel.mockResolvedValue(completedTask); + TaskResource.retrieve.mockResolvedValue(completedTask); client.mockResolvedValue({ data: { picture_password: '3.7.12' } }); renderComponent({ targetFacility: { @@ -140,7 +140,7 @@ describe(`ChangeFacility/ConfirmMerge`, () => { // The facility has picture_password_settings but the user's picture_password hasn't synced yet; // the flag must stay set so the modal can appear after the next sync. it('stores picture password pending in sessionStorage when picture passwords are enabled but not yet synced', async () => { - TaskResource.fetchModel.mockResolvedValue(completedTask); + TaskResource.retrieve.mockResolvedValue(completedTask); client.mockResolvedValue({ data: { picture_password: null } }); renderComponent({ targetFacility: { @@ -158,7 +158,7 @@ describe(`ChangeFacility/ConfirmMerge`, () => { }); it('redirects without storing in sessionStorage when picture password is null and picture passwords are not enabled', async () => { - TaskResource.fetchModel.mockResolvedValue(completedTask); + TaskResource.retrieve.mockResolvedValue(completedTask); client.mockResolvedValue({ data: { picture_password: null } }); renderComponent(); await flushUi(); @@ -169,7 +169,7 @@ describe(`ChangeFacility/ConfirmMerge`, () => { }); it(`clicking retry button sends the task error event to the state machine`, async () => { - TaskResource.fetchCollection.mockResolvedValue([]); + TaskResource.list.mockResolvedValue([]); TaskResource.startTask.mockRejectedValue({ response: { status: 400, data: [{ metadata: { message: 'USERNAME_ALREADY_EXISTS' } }] }, }); diff --git a/kolibri/plugins/user_profile/frontend/views/ProfileEditPage.vue b/kolibri/plugins/user_profile/frontend/views/ProfileEditPage.vue index 2a1d95e3fb9..bbac60831ed 100644 --- a/kolibri/plugins/user_profile/frontend/views/ProfileEditPage.vue +++ b/kolibri/plugins/user_profile/frontend/views/ProfileEditPage.vue @@ -170,7 +170,7 @@ methods: { // Have to query FacilityUser again since we don't put demographic info on the session setFacilityUser() { - FacilityUserResource.fetchModel({ id: this.currentUserId }).then(facilityUser => { + FacilityUserResource.retrieve(this.currentUserId).then(facilityUser => { this.birthYear = facilityUser.birth_year; this.gender = facilityUser.gender; this.fullName = facilityUser.full_name; diff --git a/kolibri/plugins/user_profile/frontend/views/ProfilePage/__tests__/ProfilePage.spec.js b/kolibri/plugins/user_profile/frontend/views/ProfilePage/__tests__/ProfilePage.spec.js index b0ca8e53ba8..5b37110e4c3 100644 --- a/kolibri/plugins/user_profile/frontend/views/ProfilePage/__tests__/ProfilePage.spec.js +++ b/kolibri/plugins/user_profile/frontend/views/ProfilePage/__tests__/ProfilePage.spec.js @@ -18,7 +18,6 @@ import useOnMyOwnSetup, { import useFacilities, { useFacilitiesMock } from 'kolibri-common/composables/useFacilities'; // eslint-disable-line import useFacility, { useFacilityMock } from 'kolibri-common/composables/useFacility'; // eslint-disable-line -jest.mock('kolibri-common/apiResources/FacilityUserResource'); jest.mock('../../../composables/useOnMyOwnSetup'); jest.mock('kolibri-design-system/lib/composables/useKResponsiveWindow'); jest.mock('kolibri/composables/useUser'); @@ -29,7 +28,7 @@ jest.mock('kolibri-common/composables/useFacility'); const { fullNameLabel$ } = coreStrings; const { changePasswordPrompt$ } = createTranslator(ProfilePage.name, ProfilePage.$trs); -FacilityUserResource.fetchModel = jest.fn().mockResolvedValue({}); +jest.spyOn(FacilityUserResource, 'retrieve').mockResolvedValue({}); const localVue = createLocalVue(); localVue.use(VueRouter); @@ -102,9 +101,7 @@ describe('picture password row', () => { }), }), ); - FacilityUserResource.fetchModel = jest - .fn() - .mockResolvedValue({ picture_password: picturePassword }); + FacilityUserResource.retrieve.mockResolvedValue({ picture_password: picturePassword }); const localRouter = new VueRouter(); localRouter.getRoute = () => '/';