diff options
| author | Ron Lucke <lucke@elan-ev.de> | 2025-01-20 11:34:28 +0000 |
|---|---|---|
| committer | Ron Lucke <lucke@elan-ev.de> | 2025-01-20 11:34:28 +0000 |
| commit | 3484ee485a94c4cbf734367dc203ee14ba50bb81 (patch) | |
| tree | a3ab8628565f89ef794ec375b2f7641c418c06b1 | |
| parent | ddce12c92465e45f4456992990a5109c3c3f588e (diff) | |
Polishing: Courseware
Closes #5102
Merge request studip/studip!3851
20 files changed, 118 insertions, 151 deletions
diff --git a/resources/assets/stylesheets/mixins/colors.scss b/resources/assets/stylesheets/mixins/colors.scss index 249a6df..c1d5f96 100644 --- a/resources/assets/stylesheets/mixins/colors.scss +++ b/resources/assets/stylesheets/mixins/colors.scss @@ -281,6 +281,8 @@ $color--tile-marker-active: $color--green-1; $color--tile-marker-attention: $color--yellow-1; $color--tile-title-background: $color--gray-6; +$color--scrollbar-thumb: $color--gray-5; + $color--content-box-border: $color--gray-6; $color--content-box-header: $color--gray-6; $color--content-box-background: $color--white; diff --git a/resources/assets/stylesheets/scss/courseware/blockadder.scss b/resources/assets/stylesheets/scss/courseware/blockadder.scss index f393641..8086fe7 100644 --- a/resources/assets/stylesheets/scss/courseware/blockadder.scss +++ b/resources/assets/stylesheets/scss/courseware/blockadder.scss @@ -9,7 +9,7 @@ display: flex; position: relative; border: solid thin var(--color--tile-border); - background-color: var(--white); + background-color: var(--color--global-background); max-width: 268px; .cw-sortable-handle { @@ -114,10 +114,13 @@ .cw-container-style-selector { display: flex; + border-bottom: solid thin var(--color--content-box-border); + padding-bottom: 8px; margin-bottom: 8px; label { border: solid thin var(--color--tile-border); + border-right: none; padding: calc(0.5em + 32px) 1em 0.5em 1em; color: var(--base-color); text-align: center; @@ -126,6 +129,10 @@ background-repeat: no-repeat; cursor: pointer; + &:last-child { + border-right: solid thin var(--color--tile-border); + } + &.full { @include background-icon(column-full, $size: 32px); } diff --git a/resources/assets/stylesheets/scss/courseware/layouts/ribbon.scss b/resources/assets/stylesheets/scss/courseware/layouts/ribbon.scss index fe9d9c4..c04407b 100644 --- a/resources/assets/stylesheets/scss/courseware/layouts/ribbon.scss +++ b/resources/assets/stylesheets/scss/courseware/layouts/ribbon.scss @@ -280,7 +280,7 @@ $consum_ribbon_width: calc(100% - 58px); &.cw-ribbon-slide-leave-active { transition: transform var(--transition-duration-superslow); } - &.cw-ribbon-slide-enter, + &.cw-ribbon-slide-enter-from, &.cw-ribbon-slide-leave-to { transform: translateX(calc(100% + 30px)); } @@ -359,7 +359,7 @@ $consum_ribbon_width: calc(100% - 58px); overflow-y: auto; overflow-x: hidden; scrollbar-width: thin; - scrollbar-color: var(--base-color) var(--white); + scrollbar-color: var(--color--scrollbar-thumb) var(--white); &.cw-ribbon-tool-blockadder-tab { height: 100%; diff --git a/resources/assets/stylesheets/scss/courseware/structural-element.scss b/resources/assets/stylesheets/scss/courseware/structural-element.scss index 46fe3dd..8142aac 100644 --- a/resources/assets/stylesheets/scss/courseware/structural-element.scss +++ b/resources/assets/stylesheets/scss/courseware/structural-element.scss @@ -214,24 +214,3 @@ } } } - -.studip-dialog-with-tab { - .studip-dialog-body .studip-dialog-content { - padding: 0 4px; - .cw-tab-in-dialog { - .cw-tabs-nav { - border: none; - border-bottom: solid thin var(--content-color-40); - margin-bottom: 4px; - } - .cw-tabs-content { - border: none; - min-width: 500px; - min-height: 400px; - overflow-y: auto; - scrollbar-width: thin; - scrollbar-color: var(--base-color) var(--dark-gray-color-5); - } - } - } -} diff --git a/resources/assets/stylesheets/scss/courseware/toolbar.scss b/resources/assets/stylesheets/scss/courseware/toolbar.scss index 23bb42a..78a67e2 100644 --- a/resources/assets/stylesheets/scss/courseware/toolbar.scss +++ b/resources/assets/stylesheets/scss/courseware/toolbar.scss @@ -39,64 +39,24 @@ .cw-toolbar-tool-content { overflow-y: auto; - padding-right: 8px; + scrollbar-width: thin; + scrollbar-color: var(--color--scrollbar-thumb) var(--white); + padding-right: 6px; } .cw-toolbar-blocks { - .input-group.files-search { - &.search { - border: thin solid var(--dark-gray-color-30); - margin-bottom: 0px; - input { - border: none; - } - } - - .input-group-append { - .button { - border: none; - border-left: thin solid var(--dark-gray-color-30); - &.active { - background-color: var(--base-color); - } - } - .reset-search { - border: none; - background-color: var(--white); - } - } - - .active-filter { - display: flex; - align-items: center; - justify-content: space-between; - border: solid thin var(--black); - background-color: var(--content-color-10); - margin: 3px; - padding: 2px 3px; - - .removefilter { - border: none; - background-color: transparent; - } - } + .input-group.files-search.search { + margin-bottom: 0; } .cw-block-search { width: inherit; } - .filterpanel { - margin-bottom: 5px; - padding: 2px; - border: thin solid var(--dark-gray-color-30); - border-top: none; - background-color: #fff; - - .button { - min-width: inherit; - margin: 4px 2px; - } + .cw-toolbar-tool-header { + border-bottom: solid thin var(--color--content-box-border); + margin-bottom: 8px; + padding-bottom: 8px; } } diff --git a/resources/assets/stylesheets/scss/dialog.scss b/resources/assets/stylesheets/scss/dialog.scss index 6a5b29b..e11375c 100644 --- a/resources/assets/stylesheets/scss/dialog.scss +++ b/resources/assets/stylesheets/scss/dialog.scss @@ -321,6 +321,7 @@ v u e d i a l o g align-items: center; z-index: 1001; } + .studip-dialog-body { position: absolute; background: var(--white); @@ -411,8 +412,27 @@ v u e d i a l o g @include background-icon(question-circle-full, status-yellow, 32px); } } - + &.studip-dialog-with-tab { + .studip-dialog-content { + padding: 0 4px; + .cw-tab-in-dialog { + .cw-tabs-nav { + border: none; + border-bottom: solid thin var(--color--content-box-border); + margin-bottom: 4px; + } + .cw-tabs-content { + border: none; + overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: var(--color--scrollbar-thumb) var(--dark-gray-color-5); + } + } + } + } } + + /* * * * * * * * * * * * * v u e d i a l o g e n d * * * * * * * * * * * * */ diff --git a/resources/assets/stylesheets/scss/feedback.scss b/resources/assets/stylesheets/scss/feedback.scss index 5e11197..993bc1f 100644 --- a/resources/assets/stylesheets/scss/feedback.scss +++ b/resources/assets/stylesheets/scss/feedback.scss @@ -134,10 +134,10 @@ vue feedback components } } .five-stars-histogram-chart { - min-width: 260px; + min-width: 270px; span { display: inline-block; - width: 2em; + width: 30px; } img { vertical-align: text-bottom; @@ -147,7 +147,7 @@ vue feedback components display: inline-block; background-color: var(--content-color-10); width: calc(100% - 6em); - margin: 2px 10px; + margin: 4px 10px; .percentage-bar { background-color: var(--yellow); color: transparent; diff --git a/resources/assets/stylesheets/scss/table_of_contents.scss b/resources/assets/stylesheets/scss/table_of_contents.scss index e2db2b6..ef8077c 100644 --- a/resources/assets/stylesheets/scss/table_of_contents.scss +++ b/resources/assets/stylesheets/scss/table_of_contents.scss @@ -57,7 +57,7 @@ ul.numberedchapters { &.cw-ribbon-slide-leave-active { transition: transform var(--transition-duration-superslow); } - &.cw-ribbon-slide-enter, + &.cw-ribbon-slide-enter-from, &.cw-ribbon-slide-leave-to { transform: translateX(calc(100% + 30px)); } diff --git a/resources/assets/stylesheets/scss/variables.scss b/resources/assets/stylesheets/scss/variables.scss index b7b54f8..9ef3881 100644 --- a/resources/assets/stylesheets/scss/variables.scss +++ b/resources/assets/stylesheets/scss/variables.scss @@ -272,6 +272,8 @@ $button-icons: ( --color--tile-marker-attention: #{$color--tile-marker-attention}; --color--tile-title-background: #{$color--tile-title-background}; + --color--scrollbar-thumb: #{$color--scrollbar-thumb}; + --color--content-box-border: #{$color--content-box-border}; --color--content-box-header: #{$color--content-box-header}; --color--content-box-background: #{$color--content-box-background}; diff --git a/resources/vue/components/Datepicker.vue b/resources/vue/components/Datepicker.vue index eaedc83..9aeadf1 100644 --- a/resources/vue/components/Datepicker.vue +++ b/resources/vue/components/Datepicker.vue @@ -68,6 +68,9 @@ export default { return params; }, returnValue() { + if (this.modelValue === null) { + return ''; + } if (this.returnAs === 'unix') { return this.convertInputToUnixTimestamp(this.modelValue); } diff --git a/resources/vue/components/StudipDialog.vue b/resources/vue/components/StudipDialog.vue index 0861d19..ab42f48 100644 --- a/resources/vue/components/StudipDialog.vue +++ b/resources/vue/components/StudipDialog.vue @@ -27,8 +27,11 @@ > <div :style="{ width: dialogWidth, height: dialogHeight, top: top, left: left }" - :class="{ 'studip-dialog-warning': question, 'studip-dialog-alert': alert }" - class="studip-dialog-body" + :class="[ + { 'studip-dialog-warning': question, 'studip-dialog-alert': alert }, + 'studip-dialog-body', + $attrs.class + ]" role="dialog" aria-modal="true" :aria-labelledby="dialogTitleId" diff --git a/resources/vue/components/courseware/layouts/CoursewareTab.vue b/resources/vue/components/courseware/layouts/CoursewareTab.vue index 5e1f20b..1f5b31a 100644 --- a/resources/vue/components/courseware/layouts/CoursewareTab.vue +++ b/resources/vue/components/courseware/layouts/CoursewareTab.vue @@ -1,5 +1,5 @@ <template> - <div v-if="isActive"> + <div v-if="isActive" role="tabpanel" class="cw-tab"> <slot></slot> </div> </template> @@ -29,7 +29,7 @@ export default { }, mounted() { this.index = this.$parent.tabs.length; - this.addTab({ name: this.name, icon: this.icon}); + this.addTab({ name: this.name, icon: this.icon }); }, }; -</script>
\ No newline at end of file +</script> diff --git a/resources/vue/components/courseware/structural-element/CoursewareToolsContents.vue b/resources/vue/components/courseware/structural-element/CoursewareToolsContents.vue index 2842ace..432695e 100644 --- a/resources/vue/components/courseware/structural-element/CoursewareToolsContents.vue +++ b/resources/vue/components/courseware/structural-element/CoursewareToolsContents.vue @@ -14,7 +14,6 @@ </div> </component> <courseware-tree v-if="structuralElements.length" /> - <courseware-tree-units v-if="context.type === 'courses'" /> </div> </template> diff --git a/resources/vue/components/courseware/structural-element/CoursewareToolsUnits.vue b/resources/vue/components/courseware/structural-element/CoursewareToolsUnits.vue index 29ce79c..6177868 100644 --- a/resources/vue/components/courseware/structural-element/CoursewareToolsUnits.vue +++ b/resources/vue/components/courseware/structural-element/CoursewareToolsUnits.vue @@ -40,7 +40,7 @@ export default { this.coursewareUnits .filter( (unit) => - unit.relationships.range.data.id === this.context.id && unit.id !== this.currentUnit.id + unit.relationships.range.data.id === this.context.id ) .sort((a, b) => a.attributes.position - b.attributes.position) ?? [] ); diff --git a/resources/vue/components/courseware/structural-element/CoursewareToolsUnitsItem.vue b/resources/vue/components/courseware/structural-element/CoursewareToolsUnitsItem.vue index 9ec92ba..d577262 100644 --- a/resources/vue/components/courseware/structural-element/CoursewareToolsUnitsItem.vue +++ b/resources/vue/components/courseware/structural-element/CoursewareToolsUnitsItem.vue @@ -1,12 +1,12 @@ <template> - <a v-if="element" class="cw-tools-units-item-header" :href="url"> + <component :is="isCurrentUnit ? 'p' : 'a'" v-if="element" class="cw-tools-units-item-header" :href="isCurrentUnit ? '' : url"> <studip-ident-image v-model="identimage" :baseColor="headerColor.hex" :pattern="element.attributes.title" /> <div class="cw-tools-units-item-header-image" :style="headerImageStyle"></div> <div class="cw-tools-units-item-header-details"> - <header>{{ element.attributes.title }}</header> + <header :class="{'current' : isCurrentUnit }">{{ element.attributes.title }}</header> <p>{{ element.attributes.payload.description }}</p> </div> - </a> + </component> </template> <script> @@ -32,7 +32,11 @@ export default { computed: { ...mapGetters({ context: 'context', + currentUnit: 'currentUnit', }), + isCurrentUnit() { + return this.currentUnit.id === this.unit.id; + }, headerImageUrl() { return this.element.relationships?.image?.meta?.['download-url']; }, @@ -88,6 +92,10 @@ export default { margin: 0 0 6px 0; font-size: 16px; line-height: 16px; + &.current { + font-weight: 700; + color: var(--color--font-primary); + } } p { margin: 0; diff --git a/resources/vue/components/courseware/structural-element/CoursewareTreeItem.vue b/resources/vue/components/courseware/structural-element/CoursewareTreeItem.vue index 9ad0eb1..b6366b5 100644 --- a/resources/vue/components/courseware/structural-element/CoursewareTreeItem.vue +++ b/resources/vue/components/courseware/structural-element/CoursewareTreeItem.vue @@ -101,6 +101,8 @@ :siblingCount="nestedChildren.length" class="cw-tree-item" :elementid="element.id" + :data-id="element.id" + :data-parent-id="element.relationships.parent.data.id" @sort="sort" @moveItemUp="moveItemUp" @moveItemDown="moveItemDown" @@ -478,10 +480,10 @@ export default { } let data = { - id: e.item._underlying_vm_.id, + id: e.item.dataset.id, newPos: e.newIndex, oldPos: e.oldIndex, - oldParent: e.item._underlying_vm_.relationships.parent.data.id, + oldParent: e.item.dataset.parentId, newParent: e.to.__vnode.ctx.attrs.elementId, sortArray: sortArray, }; diff --git a/resources/vue/components/courseware/toolbar/CoursewareToolbarBlocks.vue b/resources/vue/components/courseware/toolbar/CoursewareToolbarBlocks.vue index 82e7a08..df98bb4 100644 --- a/resources/vue/components/courseware/toolbar/CoursewareToolbarBlocks.vue +++ b/resources/vue/components/courseware/toolbar/CoursewareToolbarBlocks.vue @@ -1,7 +1,7 @@ <template> <div class="cw-toolbar-blocks"> <div id="cw-toolbar-blocks-header" class="cw-toolbar-tool-header"> - <form @submit.prevent="loadSearch"> + <form class="default" @submit.prevent="loadSearch"> <div class="input-group files-search search cw-block-search"> <input ref="searchBox" @@ -32,29 +32,26 @@ </span> </div> </form> - - <div id="filterpanel" class="filterpanel"> - <form class="default"> - <span class="sr-only">{{ $gettext('Kategorien-Filter') }}</span> - <studip-select - :clearable="true" - label="title" - :options="blockCategories" - :placeholder="$gettext('Blockkategorien')" - :reduce="(category) => category.type" - v-model="currentFilterCategory" - > - <template #open-indicator="{ selectAttributes }"> - <span v-bind="selectAttributes"><studip-icon shape="arr_1down" :size="10" /></span> - </template> - <template #no-options> - {{ $gettext('Es steht keine Auswahl zur Verfügung.') }} - </template> - <template #selected-option="{ title }"><span>{{ title }}</span></template> - <template #option="{ title }"><span>{{ title }}</span></template> - </studip-select> - </form> - </div> + <form class="default"> + <span class="sr-only">{{ $gettext('Kategorien-Filter') }}</span> + <studip-select + :clearable="true" + label="title" + :options="blockCategories" + :placeholder="$gettext('Blockkategorien')" + :reduce="(category) => category.type" + v-model="currentFilterCategory" + > + <template #open-indicator="{ selectAttributes }"> + <span v-bind="selectAttributes"><studip-icon shape="arr_1down" :size="10" /></span> + </template> + <template #no-options> + {{ $gettext('Es steht keine Auswahl zur Verfügung.') }} + </template> + <template #selected-option="{ title }"><span>{{ title }}</span></template> + <template #option="{ title }"><span>{{ title }}</span></template> + </studip-select> + </form> </div> <div class="cw-toolbar-tool-content" :style="toolContentStyle"> <div v-if="filteredBlockTypes.length > 0" class="cw-blockadder-item-list"> @@ -149,8 +146,8 @@ export default { ]; }, toolContentStyle() { - const filterPanelHeight = document.getElementById("filterpanel")?.offsetHeight ?? 75; - const height = this.toolbarContentHeight - filterPanelHeight - 40; + const headerHeight = document.getElementById("cw-toolbar-blocks-header")?.offsetHeight ?? 75; + const height = this.toolbarContentHeight - headerHeight; return { height: height + 'px', diff --git a/resources/vue/components/courseware/toolbar/CoursewareToolbarClipboard.vue b/resources/vue/components/courseware/toolbar/CoursewareToolbarClipboard.vue index d11d4fc..f8f392a 100644 --- a/resources/vue/components/courseware/toolbar/CoursewareToolbarClipboard.vue +++ b/resources/vue/components/courseware/toolbar/CoursewareToolbarClipboard.vue @@ -21,6 +21,8 @@ <template #item="{element}"> <courseware-clipboard-item :clipboard="element" + :data-element-id="element.id" + :data-element-type="element.attributes['object-type']" @inserted="$emit('blockAdded')" /> </template> @@ -56,6 +58,8 @@ <template #item="{element}"> <courseware-clipboard-item :clipboard="element" + :data-element-id="element.id" + :data-element-type="element.attributes['object-type']" /> </template> </draggable> @@ -188,7 +192,7 @@ export default { return original; }, async dropClipboardBlock(e) { - const target = e.to.__vnode.ctx.attrs; + const target = e.to.dataset; // only execute if dropped in destined list if (!target.containerId) { return; @@ -199,7 +203,8 @@ export default { section: target.sectionId, position: e.newIndex, }); - await this.insertItem(e.item.__vnode.ctx.data.currentClipboard); + const clipboard = { id: e.item.dataset.elementId, attributes: { 'object-type': e.item.dataset.elementType } }; + await this.insertItem(clipboard); this.resetAdderStorage(); }, cloneClipboardContainer(original) { @@ -221,23 +226,8 @@ export default { return; } - const item = e.item._underlying_vm_; - - // if the container is from the clipboard, insert it via clipboard mixin, else add it via container mixin - if (item.clipContainer) { - this.insertItem(e.item.__vnode.ctx.data.currentClipboard, e.newIndex); - } else { - const data = { - type: item.attributes['container-type'], - colspan: item.containerStyle, - sections: { - firstSection: item.firstSection, - secondSection: item.secondSection, - }, - newPosition: e.newIndex, - }; - this.addContainer(data); - } + const clipboard = { id: e.item.dataset.elementId, attributes: { 'object-type': e.item.dataset.elementType } }; + this.insertItem(clipboard, e.newIndex); }, }, }; diff --git a/resources/vue/components/courseware/toolbar/CoursewareToolbarContainers.vue b/resources/vue/components/courseware/toolbar/CoursewareToolbarContainers.vue index 3523851..acc30b7 100644 --- a/resources/vue/components/courseware/toolbar/CoursewareToolbarContainers.vue +++ b/resources/vue/components/courseware/toolbar/CoursewareToolbarContainers.vue @@ -40,6 +40,7 @@ <courseware-container-adder-item :title="element.title" :type="element.type" + :data-type="element.type" :colspan="selectedContainerStyle" :description="element.description" :firstSection="firstSection" @@ -124,23 +125,17 @@ export default { return; } - const item = e.item._underlying_vm_; - - // if the container is from the clipboard, insert it via clipboard mixin, else add it via container mixin - if (item.clipContainer) { - this.insertItem(e.item.__node.ctx.data.currentClipboard, e.newIndex); - } else { - const data = { - type: item.attributes['container-type'], - colspan: item.containerStyle, + const data = { + type: e.item.dataset.type, + colspan: this.selectedContainerStyle, sections: { - firstSection: item.firstSection, - secondSection: item.secondSection - }, + firstSection: this.firstSection, + secondSection: this.secondSection + }, newPosition: e.newIndex - }; - this.addContainer(data); - } + }; + this.addContainer(data); + }, } }; diff --git a/resources/vue/components/courseware/unit/CoursewareUnitItemDialogLayout.vue b/resources/vue/components/courseware/unit/CoursewareUnitItemDialogLayout.vue index a188b44..ef18c33 100644 --- a/resources/vue/components/courseware/unit/CoursewareUnitItemDialogLayout.vue +++ b/resources/vue/components/courseware/unit/CoursewareUnitItemDialogLayout.vue @@ -5,7 +5,7 @@ confirmClass="accept" :closeText="$gettext('Schließen')" closeClass="cancel" - height="540" + height="560" width="870" @close="$emit('close')" @confirm="storeLayout" |
