Skip to content

Commit 117fecb

Browse files
authored
Merge pull request #5698 from christianbeeznest/ofaj-21604
Internal: Update session course permissions and visibility indicators - refs BT#21604
2 parents 41bdaec + 6e410c7 commit 117fecb

35 files changed

+691
-420
lines changed

.env.dist

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ DATABASE_PASSWORD='{{DATABASE_PASSWORD}}'
1616
###< doctrine/doctrine-bundle ###
1717

1818
###> symfony/framework-bundle ###
19-
APP_ENV='dev'
19+
APP_ENV='{{APP_ENV}}'
2020
APP_SECRET='{{APP_SECRET}}'
21-
APP_DEBUG='1'
21+
APP_DEBUG='{{APP_DEBUG}}'
2222
#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
2323
#TRUSTED_HOSTS='^(localhost|example\.com)$'
2424
###< symfony/framework-bundle ###
@@ -29,28 +29,28 @@ APP_INSTALLED='{{APP_INSTALLED}}'
2929
## Encrypt method bcrypt/sha1/md5
3030
APP_ENCRYPT_METHOD='{{APP_ENCRYPT_METHOD}}'
3131

32-
APP_LOCALE='en_US'
32+
APP_LOCALE='{{APP_LOCALE}}'
3333

34-
APP_CUSTOM_VUE_TEMPLATE='0'
34+
APP_CUSTOM_VUE_TEMPLATE='{{APP_CUSTOM_VUE_TEMPLATE}}'
3535

36-
GOOGLE_MAPS_API_KEY=''
36+
GOOGLE_MAPS_API_KEY='{{GOOGLE_MAPS_API_KEY}}'
3737

3838
#APP_API_PLATFORM_URL='http://localhost/api/' #deprecated
3939

4040
###< chamilo ###
4141

4242
###> symfony/mailer ###
43-
MAILER_DSN=sendmail://default
43+
MAILER_DSN='{{MAILER_DSN}}'
4444
###< symfony/mailer ###
4545

4646
###> nelmio/cors-bundle ###
47-
CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$
47+
CORS_ALLOW_ORIGIN='{{CORS_ALLOW_ORIGIN}}'
4848
###< nelmio/cors-bundle ###
4949

5050
###> lexik/jwt-authentication-bundle ###
51-
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
52-
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
53-
JWT_PASSPHRASE=your_secret_passphrase
51+
JWT_SECRET_KEY='{{JWT_SECRET_KEY}}'
52+
JWT_PUBLIC_KEY='{{JWT_PUBLIC_KEY}}'
53+
JWT_PASSPHRASE='{{JWT_PASSPHRASE}}'
5454
###< lexik/jwt-authentication-bundle ###
5555

5656
###> symfony/messenger ###
@@ -59,3 +59,12 @@ JWT_PASSPHRASE=your_secret_passphrase
5959
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
6060
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
6161
###< symfony/messenger ###
62+
63+
###> additional settings ###
64+
DB_MANAGER_ENABLED='{{DB_MANAGER_ENABLED}}'
65+
SECURITY_KEY='{{SECURITY_KEY}}'
66+
SOFTWARE_NAME='{{SOFTWARE_NAME}}'
67+
SOFTWARE_URL='{{SOFTWARE_URL}}'
68+
DENY_DELETE_USERS='{{DENY_DELETE_USERS}}'
69+
HOSTING_TOTAL_SIZE_LIMIT='{{HOSTING_TOTAL_SIZE_LIMIT}}'
70+
###< additional settings ###

assets/vue/components/assignments/AssignmentsForm.vue

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@
101101
/>
102102
</BaseAdvancedSettingsButton>
103103

104-
<BaseButton :label="t('Save')" :disabled="isFormLoading" icon="save" is-submit type="secondary" />
104+
<div class="flex justify-end space-x-2 mt-4">
105+
<BaseButton :label="t('Back')" type="white" icon="arrow-left" @click="goBack" />
106+
<BaseButton :label="t('Save')" :disabled="isFormLoading" icon="save" is-submit type="secondary" />
107+
</div>
105108
</form>
106109
</template>
107110

@@ -118,8 +121,8 @@ import { computed, reactive, ref, watch, watchEffect } from "vue"
118121
import { maxValue, minValue, required } from "@vuelidate/validators";
119122
import { useI18n } from "vue-i18n";
120123
import { useCidReq } from "../../composables/cidReq";
121-
import { RESOURCE_LINK_PUBLISHED } from "../../constants/entity/resourcelink"
122-
import { useRoute } from "vue-router"
124+
import { useRoute, useRouter } from "vue-router";
125+
import { RESOURCE_LINK_PUBLISHED } from "../../constants/entity/resourcelink";
123126
124127
const props = defineProps({
125128
defaultAssignment: {
@@ -137,6 +140,7 @@ const props = defineProps({
137140
const emit = defineEmits(["submit"]);
138141
139142
const route = useRoute();
143+
const router = useRouter();
140144
const { t } = useI18n();
141145
const { cid, sid, gid } = useCidReq();
142146
@@ -299,4 +303,8 @@ const onSubmit = async () => {
299303
300304
emit("submit", publicationStudent);
301305
};
302-
</script>
306+
307+
function goBack() {
308+
router.push({ name: "AssignmentsList", query: { cid, sid, gid } })
309+
}
310+
</script>

assets/vue/components/assignments/TeacherAssignmentList.vue

Lines changed: 108 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@
2323
:header="t('Title')"
2424
:sortable="true"
2525
field="title"
26-
/>
26+
>
27+
<template #body="slotProps">
28+
<div class="flex items-center">
29+
<BaseIcon v-if="isAllowedToEdit && getSessionId(slotProps.data)" icon="session-star" size="small" class="mr-2" />
30+
{{ slotProps.data.title }}
31+
</div>
32+
</template>
33+
</Column>
2734
<Column
2835
:header="t('Send date')"
2936
:sortable="true"
@@ -55,43 +62,45 @@
5562
body-class="space-x-2"
5663
>
5764
<template #body="slotProps">
58-
<BaseButton
59-
:icon="
60-
RESOURCE_LINK_PUBLISHED === slotProps.data.firstResourceLink.visibility
61-
? 'eye-on'
62-
: RESOURCE_LINK_DRAFT === slotProps.data.firstResourceLink.visibility
63-
? 'eye-off'
64-
: ''
65-
"
66-
:label="t('Visibility')"
67-
only-icon
68-
size="small"
69-
type="black"
70-
@click="onClickVisibility(slotProps.data)"
71-
/>
72-
<BaseButton
73-
:label="t('Upload corrections')"
74-
icon="file-upload"
75-
only-icon
76-
size="small"
77-
type="black"
78-
/>
79-
<BaseButton
80-
:disabled="0 === slotProps.data.uniqueStudentAttemptsTotal"
81-
:label="t('Save')"
82-
icon="download"
83-
only-icon
84-
size="small"
85-
type="black"
86-
/>
87-
<BaseButton
88-
:label="t('Edit')"
89-
icon="edit"
90-
only-icon
91-
size="small"
92-
type="black"
93-
@click="onClickEdit(slotProps.data)"
94-
/>
65+
<div v-if="canEdit(slotProps.data)">
66+
<BaseButton
67+
:icon="
68+
RESOURCE_LINK_PUBLISHED === slotProps.data.firstResourceLink.visibility
69+
? 'eye-on'
70+
: RESOURCE_LINK_DRAFT === slotProps.data.firstResourceLink.visibility
71+
? 'eye-off'
72+
: ''
73+
"
74+
:label="t('Visibility')"
75+
only-icon
76+
size="small"
77+
type="black"
78+
@click="onClickVisibility(slotProps.data)"
79+
/>
80+
<BaseButton
81+
:label="t('Upload corrections')"
82+
icon="file-upload"
83+
only-icon
84+
size="small"
85+
type="black"
86+
/>
87+
<BaseButton
88+
:disabled="0 === slotProps.data.uniqueStudentAttemptsTotal"
89+
:label="t('Save')"
90+
icon="download"
91+
only-icon
92+
size="small"
93+
type="black"
94+
/>
95+
<BaseButton
96+
:label="t('Edit')"
97+
icon="edit"
98+
only-icon
99+
size="small"
100+
type="black"
101+
@click="onClickEdit(slotProps.data)"
102+
/>
103+
</div>
95104
</template>
96105
</Column>
97106

@@ -110,20 +119,24 @@
110119
<script setup>
111120
import DataTable from "primevue/datatable"
112121
import Column from "primevue/column"
113-
import { onMounted, reactive, ref, watch } from "vue"
122+
import { onMounted, reactive, ref, watch, computed } from "vue"
114123
import { useI18n } from "vue-i18n"
115124
import cStudentPublicationService from "../../services/cstudentpublication"
116125
import { useCidReq } from "../../composables/cidReq"
117126
import { useFormatDate } from "../../composables/formatDate"
118127
import BaseTag from "../basecomponents/BaseTag.vue"
119128
import BaseButton from "../basecomponents/BaseButton.vue"
129+
import BaseIcon from "../basecomponents/BaseIcon.vue"
120130
import { RESOURCE_LINK_DRAFT, RESOURCE_LINK_PUBLISHED } from "../../constants/entity/resourcelink"
121131
import { useNotification } from "../../composables/notification"
122132
import { useConfirm } from "primevue/useconfirm"
123133
import resourceLinkService from "../../services/resourcelink"
124-
import { useRouter } from "vue-router"
134+
import { useRoute, useRouter } from "vue-router"
135+
import { checkIsAllowedToEdit } from "../../composables/userPermissions"
136+
import { useSecurityStore } from "../../store/securityStore"
125137
126138
const { t } = useI18n()
139+
const route = useRoute();
127140
const router = useRouter()
128141
129142
const assignments = ref([])
@@ -136,6 +149,8 @@ const { cid, sid, gid } = useCidReq()
136149
const notification = useNotification()
137150
138151
const confirm = useConfirm()
152+
const securityStore = useSecurityStore()
153+
const isCurrentTeacher = computed(() => securityStore.isCurrentTeacher)
139154
140155
const { abbreviatedDatetime } = useFormatDate()
141156
@@ -145,20 +160,33 @@ const loadParams = reactive({
145160
itemsPerPage: 10,
146161
})
147162
148-
function loadData() {
163+
const isAllowedToEdit = ref(false)
164+
165+
onMounted(async () => {
166+
isAllowedToEdit.value = await checkIsAllowedToEdit(true, true, true)
167+
loadData()
168+
})
169+
170+
watch(loadParams, () => {
171+
loadData()
172+
})
173+
174+
async function loadData() {
149175
loading.value = true
150176
151-
cStudentPublicationService
152-
.findAll({
177+
try {
178+
const response = await cStudentPublicationService.findAll({
153179
params: { ...loadParams, cid, sid, gid },
154180
})
155-
.then((response) => response.json())
156-
.then((json) => {
157-
assignments.value = json["hydra:member"]
158-
totalRecords.value = json["hydra:totalItems"]
181+
const json = await response.json()
159182
160-
loading.value = false
161-
})
183+
assignments.value = json["hydra:member"]
184+
totalRecords.value = json["hydra:totalItems"]
185+
} catch (error) {
186+
notification.showErrorNotification(error)
187+
} finally {
188+
loading.value = false
189+
}
162190
}
163191
164192
const onPage = (event) => {
@@ -175,14 +203,6 @@ const onSort = (event) => {
175203
})
176204
}
177205
178-
onMounted(() => {
179-
loadData()
180-
})
181-
182-
watch(loadParams, () => {
183-
loadData()
184-
})
185-
186206
function onClickMultipleDelete() {
187207
confirm.require({
188208
header: t("Confirmation"),
@@ -226,9 +246,37 @@ async function onClickVisibility(assignment) {
226246
}
227247
228248
function onClickEdit(assignment) {
249+
const assignmentId = parseInt(assignment["@id"].split('/').pop(), 10);
250+
251+
console.log('onClickEdit id :::', assignmentId);
252+
229253
router.push({
230-
name: "AssigmnentsUpdate",
231-
query: { id: assignment["@id"], cid, sid, gid },
232-
})
254+
name: "AssignmentsUpdate",
255+
params: { id: assignment["@id"] },
256+
query: route.query,
257+
});
258+
}
259+
260+
const getSessionId = (item) => {
261+
if (!item.firstResourceLink || !item.firstResourceLink.session) {
262+
return null;
263+
}
264+
265+
const sessionParts = item.firstResourceLink.session.split('/');
266+
return parseInt(sessionParts[sessionParts.length - 1]);
267+
}
268+
269+
const canEdit = (item) => {
270+
const sessionId = getSessionId(item);
271+
272+
console.log('sessionId ::: ', sessionId)
273+
274+
const isSessionDocument = sessionId && sessionId === sid;
275+
const isBaseCourse = !sessionId;
276+
277+
return (
278+
(isSessionDocument && isAllowedToEdit.value) ||
279+
(isBaseCourse && !sid && isCurrentTeacher.value)
280+
);
233281
}
234282
</script>

assets/vue/components/basecomponents/ChamiloIcons.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,5 @@ export const chamiloIconToClass = {
122122
"add-topic": "mdi mdi-forum-outline",
123123
"event-reminder": "mdi mdi-alarm",
124124
"add-event-reminder": "mdi mdi-alarm-plus",
125+
"session-star": "mdi mdi-star",
125126
};

assets/vue/components/glossary/GlossaryForm.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ const submitGlossaryForm = async () => {
126126
notification.showSuccessNotification(t("Glossary term saved"))
127127
128128
await router.push({
129-
title: "GlossaryList",
129+
name: "GlossaryList",
130130
query: route.query,
131131
})
132132
} catch (error) {

0 commit comments

Comments
 (0)