Skip to content

Commit 72e5c1d

Browse files
Merge pull request #5748 from christianbeeznest/ofaj-21647-9
Internal: Fix file manager pagination and tab visibility issues - refs BT#21647
2 parents a2e5ba4 + a2a81ea commit 72e5c1d

File tree

12 files changed

+83
-42
lines changed

12 files changed

+83
-42
lines changed

assets/css/app.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ form .field {
813813

814814
.thumbnail-item {
815815
width: 150px;
816-
padding: 10px;
816+
padding: 5px;
817817
border: 1px solid #ccc;
818818
border-radius: 5px;
819819
text-align: center;

assets/css/scss/_documents.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
}
4343

4444
.filemanager-container .thumbnails {
45-
@apply flex flex-wrap gap-2.5 justify-center mb-12;
45+
@apply flex flex-wrap gap-2.5 justify-center;
4646
}
4747

4848
.filemanager-container .thumbnail-item {

assets/vue/components/basecomponents/BaseTinyEditor.vue

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ if (props.fullPage) {
170170
const editorConfig = computed(() => ({
171171
...defaultEditorConfig,
172172
...props.editorConfig,
173+
file_picker_callback: filePickerCallback,
173174
}))
174175
175176
watch(modelValue, (newValue) => {
@@ -189,19 +190,16 @@ async function filePickerCallback(callback, value, meta) {
189190
window.addEventListener("message", function (event) {
190191
let data = event.data
191192
if (data.url) {
192-
url = data.url
193-
callback(url)
193+
callback(data.url)
194194
}
195195
})
196196
197-
// tinymce is already in the global scope, set by backend and php
198197
window.tinymce.activeEditor.windowManager.openUrl({
199198
url: url,
200-
title: "File manager",
199+
title: "File Manager",
201200
onMessage: (api, message) => {
202201
if (message.mceAction === "fileSelected") {
203-
const fileUrl = message.content
204-
callback(fileUrl)
202+
callback(message.content.url)
205203
api.close()
206204
}
207205
},
@@ -218,19 +216,11 @@ function getUrlForTinyEditor() {
218216
}).href
219217
}
220218
221-
let nodeId = course.value.resourceNode ? course.value.resourceNode.id : null
222-
223-
if (!nodeId) {
224-
console.error("Resource node ID is not available.")
225-
return
226-
}
227-
219+
let queryParams = { cid: course.value.id, sid: 0, gid: 0, filetype: 'file' }
228220
return router.resolve({
229-
name: "DocumentForHtmlEditor",
230-
params: {
231-
node: nodeId,
232-
},
233-
query: route.query,
221+
name: 'FileManagerList',
222+
params: { node: parentResourceNodeId.value },
223+
query: queryParams,
234224
}).href
235225
}
236226
</script>

assets/vue/components/filemanager/CourseDocuments.vue

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@
102102
<div class="thumbnail-title">{{ file.resourceNode.title }}</div>
103103
</div>
104104
</div>
105+
<div v-if="totalPages > 1" class="flex justify-center mt-4 space-x-4">
106+
<button class="btn btn--plain px-4 py-2 rounded-md hover:bg-blue-600 disabled:bg-gray-300" :disabled="filters.page === 1" @click="previousPage">Previous</button>
107+
<span class="text-gray-700 font-semibold">Page {{ filters.page }} of {{ totalPages }}</span>
108+
<button class="btn btn--plain px-4 py-2 rounded-md hover:bg-blue-600 disabled:bg-gray-300" :disabled="filters.page === totalPages" @click="nextPage">Next</button>
109+
</div>
105110
<BaseContextMenu :visible="contextMenuVisible" :position="contextMenuPosition" @close="contextMenuVisible = false">
106111
<ul>
107112
<li @click="selectFile(contextMenuFile)">
@@ -216,7 +221,10 @@ const {
216221
uploadDocumentHandler,
217222
onMountedCallback,
218223
isAuthenticated,
219-
selectFile
224+
selectFile,
225+
nextPage,
226+
previousPage,
227+
totalPages
220228
} = useFileManager('documents', '/api/documents', 'CourseDocumentsUploadFile', true);
221229
222230
onMountedCallback();

assets/vue/components/filemanager/PersonalFiles.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
</template>
5454
</Column>
5555

56-
<Column :header="$t('Size')" :sortable="true" field="resourceNode.firstResourceFile.size">
56+
<Column :header="$t('Size')" field="resourceNode.firstResourceFile.size">
5757
<template #body="slotProps">
5858
{{ slotProps.data.resourceNode.firstResourceFile ? prettyBytes(slotProps.data.resourceNode.firstResourceFile.size) : ""
5959
}}
@@ -103,6 +103,11 @@
103103
<div class="thumbnail-title">{{ file.resourceNode.title }}</div>
104104
</div>
105105
</div>
106+
<div v-if="totalPages > 1" class="flex justify-center mt-4 space-x-4">
107+
<button class="btn btn--plain px-4 py-2 rounded-md hover:bg-blue-600 disabled:bg-gray-300" :disabled="filters.page === 1" @click="previousPage">Previous</button>
108+
<span class="text-gray-700 font-semibold">Page {{ filters.page }} of {{ totalPages }}</span>
109+
<button class="btn btn--plain px-4 py-2 rounded-md hover:bg-blue-600 disabled:bg-gray-300" :disabled="filters.page === totalPages" @click="nextPage">Next</button>
110+
</div>
106111
<BaseContextMenu :visible="contextMenuVisible" :position="contextMenuPosition" @close="contextMenuVisible = false">
107112
<ul>
108113
<li @click="selectFile(contextMenuFile)">
@@ -217,7 +222,10 @@ const {
217222
uploadDocumentHandler,
218223
onMountedCallback,
219224
isAuthenticated,
220-
selectFile
225+
selectFile,
226+
nextPage,
227+
previousPage,
228+
totalPages
221229
} = useFileManager('personalfile', '/api/personal_files', 'FileManagerUploadFile');
222230
223231
onMountedCallback();

assets/vue/composables/useFileManager.js

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function useFileManager(entity, apiEndpoint, uploadRoute, isCourseDocumen
3131
const itemToDelete = ref(null);
3232
const item = ref({});
3333
const submitted = ref(false);
34-
const filters = ref({ shared: 0, loadNode: 1 });
34+
const filters = ref({ shared: 0, loadNode: 1, itemsPerPage: 10, page: 1, sortBy: '', sortDesc: false });
3535
const viewMode = ref('thumbnails');
3636
const contextMenuVisible = ref(false);
3737
const contextMenuPosition = ref({ x: 0, y: 0 });
@@ -48,7 +48,12 @@ export function useFileManager(entity, apiEndpoint, uploadRoute, isCourseDocumen
4848
};
4949

5050
const onUpdateOptions = async () => {
51-
let flattenedFilters = flattenFilters({
51+
52+
if (!filters.value) {
53+
filters.value = { shared: 0, loadNode: 1 };
54+
}
55+
56+
const flattenedFilters = flattenFilters({
5257
...filters.value,
5358
cid: route.query.cid || '',
5459
sid: route.query.sid || '',
@@ -58,16 +63,15 @@ export function useFileManager(entity, apiEndpoint, uploadRoute, isCourseDocumen
5863

5964
const params = {
6065
...flattenedFilters,
61-
page: 1,
62-
itemsPerPage: 10,
63-
sortBy: '',
64-
sortDesc: false,
66+
page: filters.value.page || 1,
67+
itemsPerPage: filters.value.itemsPerPage || 10,
68+
[`order[${filters.value.sortBy}]`]: filters.value.sortDesc ? 'desc' : 'asc',
6569
};
6670

6771
isLoading.value = true;
6872

6973
try {
70-
const response = await fetch(`${apiEndpoint}?page=${params.page}&rows=${params.itemsPerPage}&sortBy=${params.sortBy}&sortDesc=${params.sortDesc}&shared=${params.shared}&loadNode=${params.loadNode}&resourceNode.parent=${params['resourceNode.parent']}&cid=${params.cid}&sid=${params.sid}&gid=${params.gid}&type=${params.type}`, {
74+
const response = await fetch(`${apiEndpoint}?${new URLSearchParams(params).toString()}`, {
7175
method: 'GET',
7276
headers: {
7377
'Content-Type': 'application/json'
@@ -260,15 +264,15 @@ export function useFileManager(entity, apiEndpoint, uploadRoute, isCourseDocumen
260264
};
261265

262266
const onFilesPage = (event) => {
263-
filters.value.itemsPerPage = event.rows;
267+
filters.value.itemsPerPage = event.rows || 10;
264268
filters.value.page = event.page + 1;
265269
filters.value.sortBy = event.sortField;
266270
filters.value.sortDesc = event.sortOrder === -1;
267271
onUpdateOptions();
268272
};
269273

270274
const sortingFilesChanged = (event) => {
271-
filters.value.sortBy = event.sortField;
275+
filters.value.sortBy = event.sortField || '';
272276
filters.value.sortDesc = event.sortOrder === -1;
273277
onUpdateOptions();
274278
};
@@ -337,6 +341,24 @@ export function useFileManager(entity, apiEndpoint, uploadRoute, isCourseDocumen
337341
dialog.value = true;
338342
};
339343

344+
const totalPages = computed(() => {
345+
return Math.ceil(totalFiles.value / filters.value.itemsPerPage);
346+
});
347+
348+
const nextPage = () => {
349+
if (filters.value.page < totalPages.value) {
350+
filters.value.page++;
351+
onUpdateOptions();
352+
}
353+
};
354+
355+
const previousPage = () => {
356+
if (filters.value.page > 1) {
357+
filters.value.page--;
358+
onUpdateOptions();
359+
}
360+
};
361+
340362
return {
341363
files,
342364
totalFiles,
@@ -383,6 +405,9 @@ export function useFileManager(entity, apiEndpoint, uploadRoute, isCourseDocumen
383405
isAuthenticated,
384406
selectFile,
385407
showHandler,
386-
editHandler
408+
editHandler,
409+
nextPage,
410+
previousPage,
411+
totalPages
387412
};
388413
}

assets/vue/views/filemanager/List.vue

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
{{ t('Personal Files') }}
1313
</button>
1414
<button
15-
v-if="isAllowedToEdit"
15+
v-if="isAllowedToEdit && courseIsSet"
1616
class="px-4 py-2 -mb-px font-semibold border-b-2"
1717
:class="{
1818
'border-blue-500 text-blue-600': activeTab === 'documents',
@@ -28,7 +28,7 @@
2828
<PersonalFiles />
2929
</div>
3030

31-
<div v-if="activeTab === 'documents' && isAllowedToEdit" class="mt-4">
31+
<div v-if="activeTab === 'documents' && isAllowedToEdit && courseIsSet" class="mt-4">
3232
<CourseDocuments />
3333
</div>
3434
</div>
@@ -41,6 +41,8 @@ import PersonalFiles from "../../components/filemanager/PersonalFiles.vue"
4141
import CourseDocuments from "../../components/filemanager/CourseDocuments.vue"
4242
import { checkIsAllowedToEdit } from "../../composables/userPermissions"
4343
import { useI18n } from "vue-i18n"
44+
import { useCidReqStore } from "../../store/cidReq"
45+
import { storeToRefs } from 'pinia'
4446
4547
const route = useRoute()
4648
const router = useRouter()
@@ -50,6 +52,10 @@ const isAllowedToEdit = ref(false)
5052
const isLoading = ref(true)
5153
const { t } = useI18n()
5254
55+
const cidReqStore = useCidReqStore()
56+
const { course } = storeToRefs(cidReqStore)
57+
const courseIsSet = ref(false)
58+
5359
const changeTab = (tab) => {
5460
activeTab.value = tab
5561
router.replace({ query: { ...route.query, tab } })
@@ -63,6 +69,7 @@ watch(route, (newRoute) => {
6369
6470
onMounted(async () => {
6571
isAllowedToEdit.value = await checkIsAllowedToEdit()
72+
courseIsSet.value = !!course.value
6673
isLoading.value = false
6774
})
6875
</script>

public/main/inc/lib/formvalidator/Element/DateTimePicker.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ private function getLocaleCode(): string
134134
}
135135

136136
$courseInfo = api_get_course_info();
137-
if (isset($courseInfo)) {
137+
if (!empty($courseInfo)) {
138138
$locale = $courseInfo['language'];
139139
}
140140

public/main/ticket/tickets.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ function display_advanced_search_form () {
236236
if ('true' === api_get_setting('ticket_allow_student_add') || api_is_platform_admin()) {
237237
$actionRight = Display::url(
238238
Display::getMdiIcon(ActionIcon::ADD, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Add')),
239-
api_get_path(WEB_CODE_PATH).'ticket/new_ticket.php?project_id='.$projectId.'&'.api_get_cidReq(),
239+
api_get_path(WEB_CODE_PATH).'ticket/new_ticket.php?project_id='.$projectId,
240240
['title' => get_lang('Add')]
241241
);
242242
}

src/CoreBundle/Component/Editor/CkEditor/CkEditor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ private function getImagePicker(): string
194194
*
195195
* @return string javaScript function as string
196196
*/
197-
private function getFileManagerPicker($onlyPersonalfiles = true): string
197+
private function getFileManagerPicker(bool $onlyPersonalfiles = true): string
198198
{
199199
$user = api_get_user_entity();
200200
$course = api_get_course_entity();

0 commit comments

Comments
 (0)