From ae076bc2858bc8c0403a6abea5150a7500a8776b Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Thu, 25 Jun 2026 20:55:38 -0700 Subject: [PATCH] Route admin users from notification into submission review mode Gate SubmissionDetailsModal review actions on isAdmin from the Vuex store rather than an adminReview prop, so admin users arriving via any route automatically see the Review button and side panel. Remove the adminReview prop and all call sites that set it; simplify administration/router.js to props: true. --- .../frontend/administration/router.js | 6 +- .../__tests__/index.spec.js | 81 +++++++++++++++++++ .../SubmissionDetailsModal/index.vue | 13 ++- 3 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 contentcuration/contentcuration/frontend/shared/views/communityLibrary/SubmissionDetailsModal/__tests__/index.spec.js diff --git a/contentcuration/contentcuration/frontend/administration/router.js b/contentcuration/contentcuration/frontend/administration/router.js index d5de3506f2..af9b716776 100644 --- a/contentcuration/contentcuration/frontend/administration/router.js +++ b/contentcuration/contentcuration/frontend/administration/router.js @@ -34,11 +34,7 @@ const router = new VueRouter({ name: RouteNames.COMMUNITY_LIBRARY_SUBMISSION, path: '/community-library/:channelId/:submissionId', component: SubmissionDetailsModal, - props: route => ({ - channelId: route.params.channelId, - submissionId: route.params.submissionId, - adminReview: true, - }), + props: true, }, // Catch-all redirect to channels tab { diff --git a/contentcuration/contentcuration/frontend/shared/views/communityLibrary/SubmissionDetailsModal/__tests__/index.spec.js b/contentcuration/contentcuration/frontend/shared/views/communityLibrary/SubmissionDetailsModal/__tests__/index.spec.js new file mode 100644 index 0000000000..54d19d794c --- /dev/null +++ b/contentcuration/contentcuration/frontend/shared/views/communityLibrary/SubmissionDetailsModal/__tests__/index.spec.js @@ -0,0 +1,81 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; +import VueRouter from 'vue-router'; +import SubmissionDetailsModal from '../index.vue'; +import { + AdminCommunityLibrarySubmission, + ChannelVersion, + CommunityLibrarySubmission, +} from 'shared/data/resources'; + +jest.mock('shared/data/resources', () => ({ + AdminCommunityLibrarySubmission: { fetchModel: jest.fn() }, + ChannelVersion: { fetchCollection: jest.fn() }, + CommunityLibrarySubmission: { + fetchModel: jest.fn(), + fetchCollection: jest.fn(() => Promise.resolve({ results: [] })), + }, +})); + +const localVue = createLocalVue(); +localVue.use(Vuex); +localVue.use(VueRouter); + +const stubChannel = { + id: 'ch1', + name: 'Test', + thumbnail_url: null, + thumbnail_encoding: null, + description: '', +}; +const stubSubmission = { + id: 'sub1', + channel_id: 'ch1', + channel_version: 1, + status: 'PENDING', + version_token: null, +}; +const stubChannelVersion = { id: 'cv1' }; + +function makeStore(isAdmin) { + return new Vuex.Store({ + getters: { isAdmin: () => isAdmin }, + modules: { + channel: { + namespaced: true, + actions: { loadChannel: jest.fn(() => Promise.resolve(stubChannel)) }, + }, + errors: { namespaced: true, actions: { handleAxiosError: jest.fn() } }, + }, + }); +} + +describe('SubmissionDetailsModal', () => { + beforeEach(() => { + AdminCommunityLibrarySubmission.fetchModel.mockResolvedValue(stubSubmission); + CommunityLibrarySubmission.fetchModel.mockResolvedValue(stubSubmission); + ChannelVersion.fetchCollection.mockResolvedValue([stubChannelVersion]); + }); + + afterEach(() => jest.clearAllMocks()); + + it('uses AdminCommunityLibrarySubmission when user is admin', () => { + shallowMount(SubmissionDetailsModal, { + localVue, + store: makeStore(true), + router: new VueRouter(), + propsData: { channelId: 'ch1', submissionId: 'sub1' }, + }); + expect(AdminCommunityLibrarySubmission.fetchModel).toHaveBeenCalledWith('sub1'); + }); + + it('uses CommunityLibrarySubmission when user is not admin', () => { + shallowMount(SubmissionDetailsModal, { + localVue, + store: makeStore(false), + router: new VueRouter(), + propsData: { channelId: 'ch1', submissionId: 'sub1' }, + }); + expect(CommunityLibrarySubmission.fetchModel).toHaveBeenCalledWith('sub1'); + }); +}); diff --git a/contentcuration/contentcuration/frontend/shared/views/communityLibrary/SubmissionDetailsModal/index.vue b/contentcuration/contentcuration/frontend/shared/views/communityLibrary/SubmissionDetailsModal/index.vue index a0393fc8cb..30a460119b 100644 --- a/contentcuration/contentcuration/frontend/shared/views/communityLibrary/SubmissionDetailsModal/index.vue +++ b/contentcuration/contentcuration/frontend/shared/views/communityLibrary/SubmissionDetailsModal/index.vue @@ -74,12 +74,12 @@
@@ -105,7 +105,7 @@ :channelId="channelId" /> store.getters.isAdmin); const { windowBreakpoint } = useKResponsiveWindow(); const isModalOpen = computed({ @@ -206,7 +203,7 @@ } = useFetch({ asyncFetchFunc: async () => { try { - const Resource = props.adminReview + const Resource = isAdmin.value ? AdminCommunityLibrarySubmission : CommunityLibrarySubmission; const submission = await Resource.fetchModel(props.submissionId);