Skip to content

Commit

Permalink
Merge pull request #12845 from AllanOXDi/basic-layout-for-lesson-reso…
Browse files Browse the repository at this point in the history
…urces

Basic layout  for displaying "resources currently in lesson"
  • Loading branch information
marcellamaki authored Dec 19, 2024
2 parents 49555de + 2218fbb commit af1eedb
Show file tree
Hide file tree
Showing 6 changed files with 441 additions and 14 deletions.
3 changes: 2 additions & 1 deletion kolibri/plugins/coach/assets/src/routes/lessonsRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import QuestionLearnersPage from '../views/common/reports/QuestionLearnersPage.v
import EditLessonDetails from '../views/lessons/LessonSummaryPage/sidePanels/EditLessonDetails';
import PreviewSelectedResources from '../views/lessons/LessonSummaryPage/sidePanels/PreviewSelectedResources';
import LessonResourceSelection from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection';
import ManageSelectedLessonResources from '../views/lessons/LessonSummaryPage/sidePanels/ManageSelectedLessonResource';
import { classIdParamRequiredGuard, RouteSegments } from './utils';

const {
Expand Down Expand Up @@ -138,7 +139,7 @@ export default [
{
name: PageNames.LESSON_PREVIEW_SELECTED_RESOURCES,
path: 'preview-resources/',
component: PreviewSelectedResources,
component: ManageSelectedLessonResources,
},
{
name: PageNames.LESSON_PREVIEW_RESOURCE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@
</KPageContainer>

<BottomAppBar>
<KRouterLink
v-if="workingResources.length > 0"
:text="numberOfSelectedResource$({ count: workingResources.length })"
:primary="true"
:to="goToPreviewSelection()"
:style="{ marginRight: '1em', marginTop: '0.5em' }"
/>

<KRouterLink
:text="bottomBarButtonText"
:primary="true"
Expand All @@ -121,6 +129,7 @@
import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow';
import useUser from 'kolibri/composables/useUser';
import useSnackbar from 'kolibri/composables/useSnackbar';
import { searchAndFilterStrings } from 'kolibri-common/strings/searchAndFilterStrings';
import commonCoach from '../../common';
import CoachAppBarPage from '../../CoachAppBarPage';
import CoachImmersivePage from '../../CoachImmersivePage';
Expand Down Expand Up @@ -154,11 +163,13 @@
const { windowIsSmall } = useKResponsiveWindow();
const { getUserPermissions } = useUser();
const { createSnackbar, clearSnackbar } = useSnackbar();
const { numberOfSelectedResource$ } = searchAndFilterStrings;
return {
windowIsSmall,
getUserPermissions,
createSnackbar,
clearSnackbar,
numberOfSelectedResource$,
};
},
data() {
Expand Down Expand Up @@ -561,6 +572,11 @@
topicsLink(topicId) {
return this.topicListingLink({ ...this.$route.params, topicId });
},
goToPreviewSelection() {
return {
name: PageNames.LESSON_PREVIEW_SELECTED_RESOURCES,
};
},
},
$trs: {
resources: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,13 @@
</div>

<template #bottomNavigation>
<div
v-if="showSearch"
class="bottom-nav-container"
>
<div class="bottom-nav-container">
<KRouterLink
:text="numberOfSelectedResource$({ count: workingResources.length })"
:primary="true"
:to="{ name: PageNames.LESSON_PREVIEW_SELECTED_RESOURCES }"
:style="{ marginRight: '1em', marginTop: '0.5em' }"
/>
<KButton
primary
:text="saveAndFinishAction$()"
Expand All @@ -118,24 +121,21 @@
import ContentNodeResource from 'kolibri-common/apiResources/ContentNodeResource';
import ChannelResource from 'kolibri-common/apiResources/ChannelResource';
import AccessibleChannelCard from 'kolibri-common/components/Cards/AccessibleChannelCard.vue';
import SearchFiltersPanel from 'kolibri-common/components/SearchFiltersPanel/index.vue';
import useBaseSearch from 'kolibri-common/composables/useBaseSearch';
import { mapState } from 'vuex';
import { searchAndFilterStrings } from 'kolibri-common/strings/searchAndFilterStrings';
import { PageNames } from '../../../../constants';
export default {
name: 'LessonResourceSelection',
components: {
SidePanelModal,
AccessibleChannelCard,
SearchFiltersPanel,
},
setup() {
const loading = ref(false);
const bookmarks = ref([]);
const channels = ref([]);
const showSearch = ref(true);
const topic = ref(null);
const { searchTerms } = useBaseSearch(topic);
const { numberOfSelectedResource$ } = searchAndFilterStrings;
const loadBookmarks = async () => {
const data = await ContentNodeResource.fetchBookmarks({
Expand Down Expand Up @@ -175,16 +175,23 @@
loading,
bookmarks,
channels,
showSearch,
searchTerms,
selectFromChannels$,
numberOfBookmarks$,
bookmarksLabel$,
selectFromBookmarks$,
searchLabel$,
saveAndFinishAction$,
numberOfSelectedResource$,
};
},
data() {
return {
PageNames,
};
},
computed: {
...mapState('lessonSummary', ['workingResources']),
},
methods: {
closeSidePanel() {
this.$router.go(-1);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
<template>

<div>
<SidePanelModal
alignment="right"
sidePanelWidth="700px"
closeButtonIconType="close"
@closePanel="closeSidePanel"
@shouldFocusFirstEl="() => null"
>
<template #header>
<div :style="{ display: 'inline-flex' }">
<KIconButton
v-if="true"
icon="back"
@click="closeSidePanel"
/>
<h1
:style="{ fontWeight: '600', fontSize: '18px' }"
class="side-panel-title"
>
{{ numberOfSelectedResource$({ count: resources.length }) }}
</h1>
</div>
</template>

<SelectedResources
:resourceList="resources"
:currentLesson="currentLesson"
:loading="resources.length === 0"
@removeResource="removeResource"
@navigateToParent="navigateToParent"
/>

<template #bottomNavigation>
<div class="bottom-buttons-style">
<KButton
:primary="true"
:text="saveLessonResources$()"
@click="closeSidePanel()"
/>
</div>
</template>
</SidePanelModal>

<KModal
v-if="showModal"
:submitText="coreString('continueAction')"
:cancelText="coreString('cancelAction')"
:title="closeConfirmationTitle$()"
@cancel="closeModal"
@submit="$router.go(-1)"
>
{{ closeConfirmationMessage$() }}
</KModal>
</div>

</template>


<script>
import SidePanelModal from 'kolibri-common/components/SidePanelModal';
import { mapState } from 'vuex';
import { searchAndFilterStrings } from 'kolibri-common/strings/searchAndFilterStrings';
import commonCoreStrings from 'kolibri/uiText/commonCoreStrings';
import { ref, getCurrentInstance } from 'vue';
import { enhancedQuizManagementStrings } from 'kolibri-common/strings/enhancedQuizManagementStrings';
import { PageNames } from '../../../../constants';
import commonCoach from '../../../common';
import SelectedResources from './SelectedResources';
export default {
name: 'ManageSelectedLessonResources',
components: {
SidePanelModal,
SelectedResources,
},
mixins: [commonCoach, commonCoreStrings],
setup() {
const showModal = ref(false);
const hasArrayChanged = ref(false);
const router = getCurrentInstance().proxy.$router;
const { saveLessonResources$, numberOfSelectedResource$ } = searchAndFilterStrings;
const { closeConfirmationTitle$, closeConfirmationMessage$ } = enhancedQuizManagementStrings;
function closeModal() {
showModal.value = false;
}
function hasModifiedResource() {
hasArrayChanged.value = true;
}
function closeSidePanel() {
if (hasArrayChanged.value) {
showModal.value = true;
} else {
router.go(-1);
}
}
return {
saveLessonResources$,
numberOfSelectedResource$,
closeConfirmationTitle$,
closeConfirmationMessage$,
showModal,
closeModal,
closeSidePanel,
hasModifiedResource,
};
},
data() {
return {
resources: [],
};
},
computed: {
// we will have to move this to composable after the final refactor
// leaving it for now to guide the process
...mapState('lessonSummary', ['currentLesson', 'workingResources', 'resourceCache']),
},
mounted() {
this.getResources();
},
methods: {
removeResource(id) {
this.resources = this.resources.filter(lesson => lesson.id !== id);
this.hasModifiedResource();
},
navigateToParent(id) {
this.$router.push({
name: PageNames.LESSONS_ROOT,
params: { classId: this.$route.params.classId, lessonId: id },
});
},
// we will have to move this to the composable after the final refactor
// leaving it for now to guide the process
getResources() {
const response = this.workingResources.map(resource => {
const content = this.resourceCache[resource.contentnode_id];
if (!content) {
return this.missingResourceObj(resource.contentnode_id);
}
const tally = this.getContentStatusTally(
content.content_id,
this.getLearnersForLesson(this.currentLesson),
);
const tableRow = {
...content,
node_id: content.id,
hasAssignments: Object.values(tally).reduce((a, b) => a + b, 0),
tally,
};
const link = this.resourceLink(tableRow);
if (link) {
tableRow.link = link;
}
return tableRow;
});
Promise.all(response).then(results => {
this.resources = results;
});
},
// we will have to move this to the composable after the final refactor
// leaving it for now to guide the process
resourceLink(resource) {
if (resource.hasAssignments) {
if (resource.kind === this.ContentNodeKinds.EXERCISE) {
return this.classRoute(
this.group
? PageNames.GROUP_LESSON_EXERCISE_LEARNER_REPORT
: PageNames.LESSON_EXERCISE_LEARNERS_REPORT,
{ exerciseId: resource.content_id },
);
} else {
return this.classRoute(
this.group ? PageNames.GROUPS_ROOT : PageNames.LESSON_RESOURCE_LEARNERS_REPORT,
{ resourceId: resource.content_id },
);
}
}
},
},
};
</script>


<style scoped>
.bottom-buttons-style {
position: absolute;
right: 0;
bottom: 0;
left: 0;
padding: 1em;
margin-top: 1em;
text-align: right;
background-color: #ffffff;
border-top: 1px solid black;
}
</style>
Loading

0 comments on commit af1eedb

Please sign in to comment.