2424 v-model =" item.contentFile"
2525 :full-page =" isFullPage"
2626 :title =" t('Content')"
27+ :editor-config =" tinyEditorConfig"
2728 editor-id =" item_content"
2829 />
2930 </div >
114115
115116 <div
116117 v-if =" searchEnabled"
117- class =" mb-2 flex flex-row"
118+ class =" mb-3 flex flex-col gap-2 sm:flex- row sm:items-center "
118119 >
119- <label class =" w-40 font-semibold" >{{ $t("Options") }}:</label >
120-
121- <BaseCheckbox
122- id =" indexDocumentContent"
123- v-model =" item.indexDocumentContent"
124- :label =" $t('Index document content?')"
125- name =" indexDocumentContent"
126- />
120+ <div class =" flex w-40 shrink-0 items-center gap-1 font-semibold" >
121+ <span >{{ $t("Options") }}:</span >
122+ </div >
123+
124+ <div class =" flex items-center gap-2" >
125+ <BaseCheckbox
126+ id =" indexDocumentContent"
127+ v-model =" item.indexDocumentContent"
128+ :label =" $t('Index document content?')"
129+ name =" indexDocumentContent"
130+ />
131+
132+ <span
133+ class =" mdi mdi-information-outline cursor-help text-primary"
134+ role =" img"
135+ tabindex =" 0"
136+ :aria-label =" t('Information about indexing document content')"
137+ :title =" t('When enabled, the document text is indexed by the search engine so users can find it from platform search.')"
138+ />
139+ </div >
127140 </div >
128141
129142 <div
@@ -251,6 +264,7 @@ export default {
251264 editorDraftIntervalId: null ,
252265 lastEditorDraftContent: " " ,
253266 maxEditorDrafts: 5 ,
267+ editorDraftIntervalMs: 60000 ,
254268 showEditorDrafts: false ,
255269 }
256270 },
@@ -308,11 +322,16 @@ export default {
308322 return aiHelpersEnabled && (imageGeneratorEnabled || videoGeneratorEnabled)
309323 },
310324 tinyEditorConfig () {
325+ const config = {
326+ content_style: this .getDocumentEditorContentStyle (),
327+ }
328+
311329 if (! this .showAiMediaButton ) {
312- return {}
330+ return config
313331 }
314332
315333 return {
334+ ... config,
316335 appendToolbar: " chamiloAiMedia" ,
317336 setup : (editor ) => {
318337 editor .ui .registry .addIcon (
@@ -365,10 +384,10 @@ export default {
365384 this .item .indexDocumentContent = true
366385 }
367386
368- this .ensureResourceLanguage ()
369-
370387 await this .loadCourseContext ()
371388
389+ this .ensureResourceLanguage ()
390+
372391 if (! this .searchEnabled ) {
373392 return
374393 }
@@ -379,7 +398,7 @@ export default {
379398 mounted () {
380399 this .refreshEditorDrafts ()
381400 this .lastEditorDraftContent = this .normalizeEditorDraftContent (this .item .contentFile )
382- this .editorDraftIntervalId = window .setInterval (this .saveEditorDraft , 30000 )
401+ this .editorDraftIntervalId = window .setInterval (this .saveEditorDraft , this . editorDraftIntervalMs )
383402 window .addEventListener (" beforeunload" , this .saveEditorDraftOnUnload )
384403 },
385404 beforeUnmount () {
@@ -399,35 +418,88 @@ export default {
399418 },
400419 },
401420 methods: {
421+ getDocumentEditorContentStyle () {
422+ const baseStyle =
423+ typeof window !== " undefined" ? String (window .CHAMILO_TINYMCE_BASE_CONFIG ? .content_style || " " ) : " "
424+
425+ return ` ${ baseStyle}
426+ body {
427+ box-sizing: border-box;
428+ padding-left: 0.5rem;
429+ padding-right: 0.5rem;
430+ }
431+ `
432+ },
433+ normalizeLanguageIso (value ) {
434+ const raw = String (value || " " ).trim ()
435+ if (! raw) {
436+ return " "
437+ }
438+
439+ const languages = Array .isArray (window .languages ) ? window .languages : []
440+ const iriMatch = raw .match (/ \/ api\/ languages\/ (\d + )/ )
441+ if (iriMatch) {
442+ const byId = languages .find ((language ) => String (language? .id || " " ) === iriMatch[1 ])
443+ return String (byId? .isocode || byId? .isoCode || " " )
444+ }
445+
446+ const normalizedRaw = raw .replace (" -" , " _" ).toLowerCase ()
447+ const exact = languages .find ((language ) => {
448+ const code = String (language? .isocode || language? .isoCode || " " )
449+ .replace (" -" , " _" )
450+ .toLowerCase ()
451+
452+ return code === normalizedRaw
453+ })
454+
455+ if (exact) {
456+ return String (exact .isocode || exact .isoCode || " " )
457+ }
458+
459+ const shortCode = normalizedRaw .split (" _" )[0 ]
460+ const byShortCode = languages .find ((language ) => {
461+ const code = String (language? .isocode || language? .isoCode || " " )
462+ .replace (" -" , " _" )
463+ .toLowerCase ()
464+
465+ return code === shortCode || code .startsWith (` ${ shortCode} _` )
466+ })
467+
468+ return String (byShortCode? .isocode || byShortCode? .isoCode || raw)
469+ },
402470 extractResourceLanguageIso (language ) {
403471 if (! language) {
404472 return " "
405473 }
406474
407475 if (" string" === typeof language) {
408- const iriMatch = language .match (/ \/ api\/ languages\/ (\d + )/ )
409- if (! iriMatch) {
410- return language
411- }
412-
413- const languages = Array .isArray (window .languages ) ? window .languages : []
414- const found = languages .find ((item ) => String (item? .id || " " ) === iriMatch[1 ])
415-
416- return String (found? .isocode || " " )
476+ return this .normalizeLanguageIso (language)
417477 }
418478
419- return String (language .isocode || language .isoCode || " " )
479+ return this . normalizeLanguageIso (language .isocode || language .isoCode || language[ " @id " ] || " " )
420480 },
421481 ensureResourceLanguage () {
422- if (! this .item || undefined !== this . item . language ) {
482+ if (! this .item ) {
423483 return
424484 }
425485
426- this .item .language = this .extractResourceLanguageIso (
486+ const currentLanguage = this .extractResourceLanguageIso (this .item .language )
487+ if (currentLanguage) {
488+ if (currentLanguage !== this .item .language ) {
489+ this .item .language = currentLanguage
490+ }
491+
492+ return
493+ }
494+
495+ const fallbackLanguage = this .extractResourceLanguageIso (
427496 this .item ? .resourceNode ? .language ||
428497 this .item ? .resourceNode ? .firstResourceFile ? .language ||
429498 this .item ? .firstResourceFile ? .language ,
430499 )
500+
501+ const courseLanguage = this .extractResourceLanguageIso (this .courseContextLanguage )
502+ this .item .language = fallbackLanguage || courseLanguage || " "
431503 },
432504 getEditorDraftUserId () {
433505 const user = this .securityStore ? .user || {}
@@ -550,9 +622,15 @@ export default {
550622 return
551623 }
552624
553- const drafts = this .readEditorDrafts ().filter (
554- (draft ) => this .normalizeEditorDraftContent (draft .content ) !== content,
555- )
625+ const storedDrafts = this .readEditorDrafts ()
626+ const latestStoredDraft = storedDrafts[0 ] || null
627+
628+ if (latestStoredDraft && this .normalizeEditorDraftContent (latestStoredDraft .content ) === content) {
629+ this .lastEditorDraftContent = content
630+ return
631+ }
632+
633+ const drafts = storedDrafts .filter ((draft ) => this .normalizeEditorDraftContent (draft .content ) !== content)
556634 const draft = {
557635 id: ` ${ Date .now ()} -${ Math .random ().toString (16 ).slice (2 )} ` ,
558636 title: String (this .item .title || " " ).trim (),
@@ -660,7 +738,7 @@ export default {
660738 async loadCourseContext () {
661739 const cid = Number (this .$route ? .query ? .cid || 0 )
662740 this .courseContextTitle = String (this .$route ? .query ? .course_title || " " ).trim ()
663- this .courseContextLanguage = String (this .$route ? .query ? .course_language || this . locale || " en " ).trim ()
741+ this .courseContextLanguage = String (this .$route ? .query ? .course_language || " " ).trim ()
664742
665743 if (! cid) {
666744 return
@@ -671,14 +749,15 @@ export default {
671749 const data = response? .data || {}
672750
673751 const apiTitle = String (data? .title || data? .name || " " ).trim ()
674- const apiLanguage = String (data? .language || " " ).trim ()
752+ const apiLanguage = String (data? .courseLanguage || data ? . course_language || data ? . language || " " ).trim ()
675753
676754 if (apiTitle) {
677755 this .courseContextTitle = apiTitle
678756 }
679757
680758 if (apiLanguage) {
681759 this .courseContextLanguage = apiLanguage
760+ this .ensureResourceLanguage ()
682761 }
683762 } catch (error) {
684763 console .warn (" [DocumentsForm] Failed to load course context." , error)
0 commit comments