diff --git a/locales/default.pot b/locales/default.pot index 2d3c04601..730692e22 100644 --- a/locales/default.pot +++ b/locales/default.pot @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: BEdita 4 \n" -"POT-Creation-Date: 2025-10-29 11:08:16 \n" +"POT-Creation-Date: 2025-12-31 09:53:48 \n" "MIME-Version: 1.0 \n" "Content-Transfer-Encoding: 8bit \n" "Language-Team: BEdita I18N & I10N Team \n" @@ -451,6 +451,9 @@ msgstr "" msgid "Less" msgstr "" +msgid "Limit" +msgstr "" + msgid "List" msgstr "" @@ -585,6 +588,9 @@ msgstr "" msgid "Number of created objects" msgstr "" +msgid "Number of folders" +msgstr "" + msgid "Number of login errors" msgstr "" @@ -876,6 +882,9 @@ msgstr "" msgid "Temporary folder missing" msgstr "" +msgid "The number of folders is too high to be displayed in tree-compact view" +msgstr "" + msgid "There were errors creating the thumbnail(s)" msgstr "" @@ -927,6 +936,12 @@ msgstr "" msgid "Trashd" msgstr "" +msgid "Tree" +msgstr "" + +msgid "Tree compact" +msgstr "" + msgid "Tree view" msgstr "" @@ -1017,6 +1032,9 @@ msgstr "" msgid "You are not authorized to access this resource" msgstr "" +msgid "You cannot see folders in tree-compact view" +msgstr "" + msgid "You do not have the required permissions to view this page." msgstr "" @@ -1550,6 +1568,30 @@ msgstr "" msgid "View" msgstr "" +msgid "New content" +msgstr "" + +msgid "New folder" +msgstr "" + +msgid "Open in new tab" +msgstr "" + +msgid "Undo" +msgstr "" + +msgid "Choose object type" +msgstr "" + +msgid "Object type" +msgstr "" + +msgid "Parent folder" +msgstr "" + +msgid "/ (root)" +msgstr "" + msgid "Add new tag" msgstr "" @@ -1612,9 +1654,6 @@ msgstr "" msgid "Edit related objects" msgstr "" -msgid "Choose object type" -msgstr "" - msgid "Choose relation" msgstr "" @@ -1922,9 +1961,6 @@ msgstr "" msgid "Invalid date range" msgstr "" -msgid "Undo" -msgstr "" - msgid "Copied!" msgstr "" @@ -1940,6 +1976,12 @@ msgstr "" msgid "Error on deleting category" msgstr "" +msgid "Create new" +msgstr "" + +msgid "Loading" +msgstr "" + msgid "Allowed types" msgstr "" diff --git a/locales/en_US/default.po b/locales/en_US/default.po index 04a352a16..f253ceb9d 100644 --- a/locales/en_US/default.po +++ b/locales/en_US/default.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: BEdita Manager \n" -"POT-Creation-Date: 2025-10-29 11:08:16 \n" +"POT-Creation-Date: 2025-12-31 09:53:48 \n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: BEdita I18N & I10N Team \n" @@ -454,6 +454,9 @@ msgstr "" msgid "Less" msgstr "" +msgid "Limit" +msgstr "" + msgid "List" msgstr "" @@ -588,6 +591,9 @@ msgstr "" msgid "Number of created objects" msgstr "" +msgid "Number of folders" +msgstr "" + msgid "Number of login errors" msgstr "" @@ -879,6 +885,9 @@ msgstr "" msgid "Temporary folder missing" msgstr "" +msgid "The number of folders is too high to be displayed in tree-compact view" +msgstr "" + msgid "There were errors creating the thumbnail(s)" msgstr "" @@ -930,6 +939,12 @@ msgstr "" msgid "Trashd" msgstr "Trashed" +msgid "Tree" +msgstr "" + +msgid "Tree compact" +msgstr "" + msgid "Tree view" msgstr "" @@ -1020,6 +1035,9 @@ msgstr "" msgid "You are not authorized to access this resource" msgstr "" +msgid "You cannot see folders in tree-compact view" +msgstr "" + msgid "You do not have the required permissions to view this page." msgstr "" @@ -1553,6 +1571,30 @@ msgstr "" msgid "View" msgstr "" +msgid "New content" +msgstr "" + +msgid "New folder" +msgstr "" + +msgid "Open in new tab" +msgstr "" + +msgid "Undo" +msgstr "" + +msgid "Choose object type" +msgstr "" + +msgid "Object type" +msgstr "" + +msgid "Parent folder" +msgstr "" + +msgid "/ (root)" +msgstr "" + msgid "Add new tag" msgstr "" @@ -1615,9 +1657,6 @@ msgstr "" msgid "Edit related objects" msgstr "" -msgid "Choose object type" -msgstr "" - msgid "Choose relation" msgstr "" @@ -1925,9 +1964,6 @@ msgstr "" msgid "Invalid date range" msgstr "" -msgid "Undo" -msgstr "" - msgid "Copied!" msgstr "" @@ -1943,6 +1979,12 @@ msgstr "" msgid "Error on deleting category" msgstr "" +msgid "Create new" +msgstr "" + +msgid "Loading" +msgstr "" + msgid "Allowed types" msgstr "" diff --git a/locales/it_IT/default.po b/locales/it_IT/default.po index bf1b9d702..d30fad502 100644 --- a/locales/it_IT/default.po +++ b/locales/it_IT/default.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: BEdita Manager \n" -"POT-Creation-Date: 2025-10-29 11:08:16 \n" +"POT-Creation-Date: 2025-12-31 09:53:48 \n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: BEdita I18N & I10N Team \n" @@ -457,6 +457,9 @@ msgstr "Tipi di sinistra" msgid "Less" msgstr "Meno" +msgid "Limit" +msgstr "Limite" + msgid "List" msgstr "Lista" @@ -593,6 +596,9 @@ msgstr "Non trovato" msgid "Number of created objects" msgstr "Numero di oggetti creati" +msgid "Number of folders" +msgstr "Numero di cartelle" + msgid "Number of login errors" msgstr "Numero di errori di accesso" @@ -887,6 +893,9 @@ msgstr "Tag" msgid "Temporary folder missing" msgstr "Cartella temporanea mancante" +msgid "The number of folders is too high to be displayed in tree-compact view" +msgstr "Il numero di cartelle è troppo alto per essere visualizzato nella vista ad albero compatta" + msgid "There were errors creating the thumbnail(s)" msgstr "È avvenuto un errore nella creazione delle miniature" @@ -938,6 +947,12 @@ msgstr "Cestino" msgid "Trashd" msgstr "Cancellato" +msgid "Tree" +msgstr "Albero" + +msgid "Tree compact" +msgstr "Albero compatto" + msgid "Tree view" msgstr "Vista ad albero" @@ -1028,6 +1043,9 @@ msgstr "Non sei autorizzato ad accedere a quest'area." msgid "You are not authorized to access this resource" msgstr "Non sei autorizzato ad accedere a questa risorsa" +msgid "You cannot see folders in tree-compact view" +msgstr "Non puoi vedere le cartelle nella vista ad albero compatta" + msgid "You do not have the required permissions to view this page." msgstr "Non hai i permessi necessari per visualizzare questa pagina." @@ -1572,6 +1590,30 @@ msgstr "pagina" msgid "View" msgstr "Vedi" +msgid "New content" +msgstr "Nuovo contenuto" + +msgid "New folder" +msgstr "Nuova cartella" + +msgid "Open in new tab" +msgstr "Apri in una nuova scheda" + +msgid "Undo" +msgstr "Annulla" + +msgid "Choose object type" +msgstr "Scegli il tipo di oggetto" + +msgid "Object type" +msgstr "Tipo di oggetto" + +msgid "Parent folder" +msgstr "Cartella genitore" + +msgid "/ (root)" +msgstr "/ (radice)" + msgid "Add new tag" msgstr "Aggiungi un nuovo tag" @@ -1634,9 +1676,6 @@ msgstr "Si è verificato un errore durante la creazione del nuovo oggetto." msgid "Edit related objects" msgstr "Modifica oggetti correlati" -msgid "Choose object type" -msgstr "Scegli il tipo di oggetto" - msgid "Choose relation" msgstr "Scegli la relazione" @@ -1950,9 +1989,6 @@ msgstr "Tutti i giorni" msgid "Invalid date range" msgstr "Intervallo date non valido" -msgid "Undo" -msgstr "Annulla" - msgid "Copied!" msgstr "Copiato!" @@ -1968,6 +2004,12 @@ msgstr "Errore durante il salvataggio della categoria" msgid "Error on deleting category" msgstr "Errore durante l'eliminazione della categoria" +msgid "Create new" +msgstr "Crea nuovo" + +msgid "Loading" +msgstr "Caricamento in corso" + msgid "Allowed types" msgstr "Tipi consentiti" diff --git a/package.json b/package.json index 6b6b14f51..86069126f 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,12 @@ }, "dependencies": { "@chialab/typos": "^0.1.1", + "@fullcalendar/core": "^6.1.15", + "@fullcalendar/daygrid": "^6.1.15", + "@fullcalendar/interaction": "^6.1.15", + "@fullcalendar/list": "^6.1.15", + "@fullcalendar/timegrid": "^6.1.15", + "@fullcalendar/vue": "^6.1.15", "@riophae/vue-treeselect": "^0.4.0", "@trevoreyre/autocomplete-vue": "^2.4.1", "abortcontroller-polyfill": "^1.7.6", @@ -76,4 +82,4 @@ "webpack-watch-files-plugin": "^1.2.0" }, "packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610" -} \ No newline at end of file +} diff --git a/resources/js/app/app.js b/resources/js/app/app.js index f131e488d..d3dc74b73 100644 --- a/resources/js/app/app.js +++ b/resources/js/app/app.js @@ -113,6 +113,7 @@ const _vueInstance = new Vue({ FieldString: () => import(/* webpackChunkName: "field-string" */'app/components/form/field-string'), FieldTextarea: () => import(/* webpackChunkName: "field-textarea" */'app/components/form/field-textarea'), FieldTitle: () => import(/* webpackChunkName: "field-title" */'app/components/form/field-title'), + CalendarView: () => import(/* webpackChunkName: "calendar-view" */'app/components/calendar-view/calendar-view'), ObjectInfo: () => import(/* webpackChunkName: "object-info" */'app/components/object-info/object-info'), RelatedObjectsFilter: () => import(/* webpackChunkName: "related-objects-filter" */'app/components/related-objects-filter/related-objects-filter'), ModuleProperties: () => import(/* webpackChunkName: "module-properties" */'app/components/module/module-properties'), @@ -629,6 +630,7 @@ window._vueInstance = _vueInstance; // use component everywhere in Manager Vue.component('AppIcon', AppIcon); +Vue.component('CalendarView', _vueInstance.$options.components.CalendarView); Vue.component('ClipboardItem', _vueInstance.$options.components.ClipboardItem); Vue.component('DateRangesView', _vueInstance.$options.components.DateRangesView); Vue.component('FieldCheckbox', _vueInstance.$options.components.FieldCheckbox); diff --git a/resources/js/app/components/calendar-view/calendar-view.vue b/resources/js/app/components/calendar-view/calendar-view.vue new file mode 100644 index 000000000..02664e0a2 --- /dev/null +++ b/resources/js/app/components/calendar-view/calendar-view.vue @@ -0,0 +1,526 @@ + + + diff --git a/resources/js/app/components/date-range/date-range.vue b/resources/js/app/components/date-range/date-range.vue index 4f8db81bb..9d536d1c3 100644 --- a/resources/js/app/components/date-range/date-range.vue +++ b/resources/js/app/components/date-range/date-range.vue @@ -7,6 +7,7 @@ {{ msgFrom }}
diff --git a/resources/js/app/components/object-info/object-info.vue b/resources/js/app/components/object-info/object-info.vue index bcd61f551..bac50fc49 100644 --- a/resources/js/app/components/object-info/object-info.vue +++ b/resources/js/app/components/object-info/object-info.vue @@ -6,6 +6,7 @@ diff --git a/resources/js/app/helpers/view.js b/resources/js/app/helpers/view.js index 4ffc7797d..adb360550 100644 --- a/resources/js/app/helpers/view.js +++ b/resources/js/app/helpers/view.js @@ -348,6 +348,12 @@ export default { return d ? new Date(d).toLocaleDateString(locale) + ' ' + new Date(d).toLocaleTimeString(locale, {hour: '2-digit', minute:'2-digit'}) : ''; }, + formatTime(d) { + const locale = BEDITA?.locale?.slice(0, 2) || 'en'; + + return d ? new Date(d).toLocaleTimeString(locale, {hour: '2-digit', minute:'2-digit'}) : ''; + }, + formatBytes(size) { let i = size == 0 ? 0 : Math.floor( Math.log(size) / Math.log(1024) ); diff --git a/resources/js/app/pages/modules/index.js b/resources/js/app/pages/modules/index.js index 198498bdd..cd7850338 100644 --- a/resources/js/app/pages/modules/index.js +++ b/resources/js/app/pages/modules/index.js @@ -21,6 +21,7 @@ export default { IndexCell: () => import(/* webpackChunkName: "index-cell" */'app/components/index-cell/index-cell'), PermissionToggle: () => import(/* webpackChunkName: "permission-toggle" */'app/components/permission-toggle/permission-toggle'), DropUpload: () => import(/* webpackChunkName: "drop-upload" */'app/components/drop-upload'), + CalendarView: () => import(/* webpackChunkName: "calendar-view" */'app/components/calendar-view/calendar-view'), }, /** diff --git a/resources/styles/_elements.scss b/resources/styles/_elements.scss index eab63161d..90cd3c5c3 100644 --- a/resources/styles/_elements.scss +++ b/resources/styles/_elements.scss @@ -353,3 +353,60 @@ nav.pagination { right: 6px; font-size: 11px; } + +// fullcalendar +.fc { + .fc-list-day-cushion { + background-color: #154362 !important; + } + + .fc-list-event:hover td { + background-color: #5389ae !important; + } +} + +:root { + --fc-small-font-size: .75em; + --fc-highlight-color: #bcd6f14d; + --fc-today-bg-color: #002732; + --fc-event-bg-color: #4871ed; +} + +.fc-toolbar-chunk .fc-datePicker-button input[type="month"], +.fc-toolbar-chunk .fc-datePicker-button input[type="date"] { + background: #fff !important; + color: #222 !important; + border: 1px solid #ccc; + border-radius: 4px; + box-shadow: none !important; + padding: 2px 6px; + font-size: 1em; + outline: none; + margin: 0 4px; + min-width: 120px; + height: 2em; +} + +.fc-toolbar-chunk .fc-datePicker-button input[type="month"]:focus, +.fc-toolbar-chunk .fc-datePicker-button input[type="date"]:focus { + border-color: #888; +} + +.fc-toolbar-chunk .fc-datePicker-button { + background: transparent !important; + box-shadow: none !important; + padding: 0 !important; +} + +.fc-toolbar-chunk .fc-datePicker-button, +.fc-toolbar-chunk .fc-datePicker-button.fc-button { + background: transparent !important; + border: none !important; + box-shadow: none !important; + padding: 0 !important; + min-width: 0 !important; + height: auto !important; + display: flex; + align-items: center; + cursor: default; +} diff --git a/src/View/Helper/LayoutHelper.php b/src/View/Helper/LayoutHelper.php index d1a62347c..e95c5194e 100644 --- a/src/View/Helper/LayoutHelper.php +++ b/src/View/Helper/LayoutHelper.php @@ -281,8 +281,11 @@ public function moduleIndexDefaultViewType(): string { $module = (array)$this->getView()->get('currentModule'); $name = (string)Hash::get($module, 'name'); + $schema = (array)$this->_View->get('schema'); + $defaultType = in_array('DateRanges', (array)Hash::get($schema, 'associations')) ? 'calendar' : 'list'; + $defaultType = $name === 'folders' ? 'tree' : $defaultType; - return $name === 'folders' ? 'tree' : 'list'; + return $defaultType; } /** @@ -305,8 +308,10 @@ public function moduleIndexViewType(): string public function moduleIndexViewTypes(): array { $defaultType = $this->moduleIndexDefaultViewType(); + $defaultList = $defaultType === 'calendar' ? ['calendar', 'list'] : ['list']; + $defaultList = $defaultType === 'tree' ? ['tree', 'tree-compact', 'list'] : $defaultList; - return $defaultType === 'tree' ? ['tree', 'tree-compact', 'list'] : ['list']; + return $defaultList; } /** diff --git a/templates/Element/Modules/calendar.twig b/templates/Element/Modules/calendar.twig new file mode 100644 index 000000000..83e65301e --- /dev/null +++ b/templates/Element/Modules/calendar.twig @@ -0,0 +1,5 @@ + diff --git a/templates/Element/Modules/sidebar.twig b/templates/Element/Modules/sidebar.twig index aaea6daf6..ab32c0084 100644 --- a/templates/Element/Modules/sidebar.twig +++ b/templates/Element/Modules/sidebar.twig @@ -36,7 +36,21 @@ {% endfor %} {% endif %} -{{ Layout.appendViewTypeButtons() }} +{% set indexViewTypes = Layout.moduleIndexViewTypes() %} +{% if indexViewTypes|length > 1 %} + {% set mapIcon = { + 'list': 'carbon:list', + 'tree': 'carbon:tree-view', + 'calendar': 'carbon:calendar', + } %} + {% set mapLabel = { + 'list': __('List'), + 'tree': __('Tree'), + 'calendar': __('Calendar'), + } %} + {{ Layout.appendViewTypeButtons() }} +{% endif %} + {% if in_array('admin', user.roles) %} {% do _view.append( diff --git a/templates/Pages/Modules/index.twig b/templates/Pages/Modules/index.twig index 283758351..9167bd5dd 100644 --- a/templates/Pages/Modules/index.twig +++ b/templates/Pages/Modules/index.twig @@ -1,11 +1,10 @@ {% do _view.assign('title', __(currentModule.name|humanize)) %} {% set indexViewType = Layout.moduleIndexViewType() %} -{% if indexViewType != 'tree-compact' %} - {{ element('Modules/index_header', { 'meta': meta, 'filter': filter, 'Schema': Schema, 'hidePagination': indexViewType == 'tree'}) }} +{% if not indexViewType in ['calendar', 'tree-compact'] %} + {{ element('Modules/index_header', { 'meta': meta, 'filter': filter, 'Schema': Schema, 'hidePagination': indexViewType == 'tree'}) }} {% endif %} - {% set ids = Array.extract(objects, '{*}.id') %}
diff --git a/yarn.lock b/yarn.lock index d0c714dd0..4ee83a9f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1014,6 +1014,40 @@ resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== +"@fullcalendar/core@^6.1.15": + version "6.1.15" + resolved "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.15.tgz#6c3f5259fc4589870228853072131219bb533f6e" + integrity sha512-BuX7o6ALpLb84cMw1FCB9/cSgF4JbVO894cjJZ6kP74jzbUZNjtwffwRdA+Id8rrLjT30d/7TrkW90k4zbXB5Q== + dependencies: + preact "~10.12.1" + +"@fullcalendar/daygrid@^6.1.15", "@fullcalendar/daygrid@~6.1.15": + version "6.1.15" + resolved "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.15.tgz#91208b0955ba805ddad285a53ee6f53855146963" + integrity sha512-j8tL0HhfiVsdtOCLfzK2J0RtSkiad3BYYemwQKq512cx6btz6ZZ2RNc/hVnIxluuWFyvx5sXZwoeTJsFSFTEFA== + +"@fullcalendar/interaction@^6.1.15": + version "6.1.15" + resolved "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.15.tgz#1c685d5c269388d4877b75ab2185e97d7c386cc7" + integrity sha512-DOTSkofizM7QItjgu7W68TvKKvN9PSEEvDJceyMbQDvlXHa7pm/WAVtAc6xSDZ9xmB1QramYoWGLHkCYbTW1rQ== + +"@fullcalendar/list@^6.1.15": + version "6.1.15" + resolved "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.15.tgz#d9b7ff0a50d7efa0d31234ed6caea06db6090c29" + integrity sha512-U1bce04tYDwkFnuVImJSy2XalYIIQr6YusOWRPM/5ivHcJh67Gm8CIMSWpi3KdRSNKFkqBxLPkfZGBMaOcJYug== + +"@fullcalendar/timegrid@^6.1.15": + version "6.1.15" + resolved "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.15.tgz#c4630b7c03c813065154c6e3981f8d51d9d692e5" + integrity sha512-61ORr3A148RtxQ2FNG7JKvacyA/TEVZ7z6I+3E9Oeu3dqTf6M928bFcpehRTIK6zIA6Yifs7BeWHgOE9dFnpbw== + dependencies: + "@fullcalendar/daygrid" "~6.1.15" + +"@fullcalendar/vue@^6.1.15": + version "6.1.15" + resolved "https://registry.npmjs.org/@fullcalendar/vue/-/vue-6.1.15.tgz#3f8069f63769ebb0eb0fa9f3696f226223965781" + integrity sha512-ptTyhJMwY0kgUQSQtR7Nh8AMdUOdEYUmQu7aU604m776glDh80U6bfm/xLdZKG7EmlAbFAtXnymOUSSxnsGhEQ== + "@humanwhocodes/config-array@^0.13.0": version "0.13.0" resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" @@ -4560,6 +4594,11 @@ potpack@^2.0.0: resolved "https://registry.npmjs.org/potpack/-/potpack-2.0.0.tgz#61f4dd2dc4b3d5e996e3698c0ec9426d0e169104" integrity sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw== +preact@~10.12.1: + version "10.12.1" + resolved "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz#8f9cb5442f560e532729b7d23d42fd1161354a21" + integrity sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"