"lib/classes/JsonApi/git@gitlab.studip.de:marcus/studip.git" did not exist on "a3263e649322391bdd5f08dbf3a2fb28c3770bd9"
Select Git revision
ModulLanguage.php
Forked from
Stud.IP / Stud.IP
Source project has a limited visibility.
-
Jan-Hendrik Willms authoredJan-Hendrik Willms authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
CoursewareHeadlineBlock.vue 16.24 KiB
<template>
<div class="cw-block cw-block-headline">
<courseware-default-block
:block="block"
:canEdit="canEdit"
:isTeacher="isTeacher"
:preview="true"
@showEdit="initCurrentData"
@storeEdit="storeText"
@closeEdit="initCurrentData"
>
<template #content>
<div
class="cw-block-headline-content"
:class="[currentStyle, currentHeight === 'half' ? 'half' : 'full']"
:style="headlineStyle"
>
<div
class="icon-layer"
:class="['icon-' + currentIconColor + '-' + currentIcon, currentHeight === 'half' ? 'half' : 'full']"
>
</div>
<div class="cw-block-headline-textbox">
<div class="cw-block-headline-title">
<h1 :style="textStyle">{{ currentTitle }}</h1>
</div>
<div class="cw-block-headline-subtitle">
<h2 :style="textStyle">{{ currentSubtitle }}</h2>
</div>
</div>
</div>
</template>
<template v-if="canEdit" #edit>
<form class="default" @submit.prevent="">
<label>
<translate>Layout</translate>
<select v-model="currentStyle">
<option value="heavy"><translate>Große Schrift</translate></option>
<option value="ribbon"><translate>Band</translate></option>
<option value="bigicon_top"><translate>Großes Icon oben</translate></option>
<option value="bigicon_before"><translate>Großes Icon davor</translate></option>
</select>
</label>
<label>
<translate>Höhe</translate>
<select v-model="currentHeight">
<option value="full"><translate>Voll</translate></option>
<option value="half"><translate>Halb</translate></option>
</select>
</label>
<label>
<translate>Haupttitel</translate>
<input type="text" v-model="currentTitle" />
</label>
<label v-if="hasSubtitle">
<translate>Untertitel</translate>
<input type="text" v-model="currentSubtitle" />
</label>
<label>
<translate>Textfarbe</translate>
<studip-select
:options="colors"
label="hex"
:reduce="color => color.hex"
:clearable="false"
v-model="currentTextColor"
>
<template #open-indicator="selectAttributes">
<span v-bind="selectAttributes"><studip-icon shape="arr_1down" size="10"/></span>
</template>
<template #no-options>
<translate>Es steht keine Auswahl zur Verfügung.</translate>
</template>
<template #selected-option="{name, hex}">
<span class="vs__option-color" :style="{'background-color': hex}"></span><span>{{name}}</span>
</template>
<template #option="{name, hex}">
<span class="vs__option-color" :style="{'background-color': hex}"></span><span>{{name}}</span>
</template>
</studip-select>
</label>
<label>
<translate>Icon</translate>
<studip-select :clearable="false" :options="icons" v-model="currentIcon">
<template #open-indicator="selectAttributes">
<span v-bind="selectAttributes"><studip-icon shape="arr_1down" size="10"/></span>
</template>
<template #no-options>
<translate>Es steht keine Auswahl zur Verfügung.</translate>
</template>
<template #selected-option="option">
<studip-icon :shape="option.label"/> <span class="vs__option-with-icon">{{option.label}}</span>
</template>
<template #option="option">
<studip-icon :shape="option.label"/> <span class="vs__option-with-icon">{{option.label}}</span>
</template>
</studip-select>
</label>
<label>
<translate>Icon-Farbe</translate>
<studip-select
:options="iconColors"
label="name"
:reduce="iconColor => iconColor.class"
:clearable="false"
v-model="currentIconColor"
>
<template #open-indicator="selectAttributes">
<span v-bind="selectAttributes"><studip-icon shape="arr_1down" size="10"/></span>
</template>
<template #no-options>
<translate>Es steht keine Auswahl zur Verfügung.</translate>
</template>
<template #selected-option="{name, hex}">
<span class="vs__option-color" :style="{'background-color': hex}"></span><span>{{name}}</span>
</template>
<template #option="{name, hex}">
<span class="vs__option-color" :style="{'background-color': hex}"></span><span>{{name}}</span>
</template>
</studip-select>
</label>
<label>
<translate>Hintergrundtyp</translate>
<select v-model="currentBackgroundType">
<option value="color"><translate>Farbe</translate></option>
<option value="image"><translate>Bild</translate></option>
</select>
</label>
<label v-if="currentBackgroundType === 'color'">
<translate>Hintergrundfarbe</translate>
<studip-select
:options="colors"
label="hex"
:reduce="color => color.hex"
v-model="currentBackgroundColor"
:clearable="false"
>
<template #open-indicator="selectAttributes">
<span v-bind="selectAttributes"><studip-icon shape="arr_1down" size="10"/></span>
</template>
<template #no-options>
<translate>Es steht keine Auswahl zur Verfügung.</translate>
</template>
<template #selected-option="{name, hex}">
<span class="vs__option-color" :style="{'background-color': hex}"></span><span>{{name}}</span>
</template>
<template #option="{name, hex}">
<span class="vs__option-color" :style="{'background-color': hex}"></span><span>{{name}}</span>
</template>
</studip-select>
</label>
<label v-if="currentBackgroundType === 'image'">
<translate>Hintergrundbild</translate>
<courseware-file-chooser
v-model="currentBackgroundImageId"
:isImage="true"
@selectFile="updateCurrentBackgroundImage"
/>
</label>
</form>
</template>
<template #info><translate>Informationen zum Blickfang-Block</translate></template>
</courseware-default-block>
</div>
</template>
<script>
import CoursewareDefaultBlock from './CoursewareDefaultBlock.vue';
import CoursewareFileChooser from './CoursewareFileChooser.vue';
import { blockMixin } from './block-mixin.js';
import colorMixin from '@/vue/mixins/courseware/colors.js';
import { mapGetters, mapActions } from 'vuex';
import contentIcons from './content-icons.js';
export default {
name: 'courseware-headline-block',
mixins: [blockMixin, colorMixin],
components: {
CoursewareDefaultBlock,
CoursewareFileChooser,
},
props: {
block: Object,
canEdit: Boolean,
isTeacher: Boolean,
},
data() {
return {
currentTitle: '',
currentSubtitle: '',
currentStyle: '',
currentHeight: '',
currentBackgroundColor: '',
currentTextColor: '',
currentIcon: '',
currentIconColor: '',
currentBackgroundType: '',
currentBackgroundImageId: '',
currentBackgroundImage: {},
currentBackgroundURL: '',
};
},
computed: {
...mapGetters({
fileRefById: 'file-refs/byId',
urlHelper: 'urlHelper',
relatedTermOfUse: 'terms-of-use/related',
}),
title() {
return this.block?.attributes?.payload?.title;
},
subtitle() {
return this.block?.attributes?.payload?.subtitle;
},
style() {
return this.block?.attributes?.payload?.style;
},
height() {
return this.block?.attributes?.payload?.height;
},
backgroundColor() {
return this.block?.attributes?.payload?.background_color;
},
textColor() {
return this.block?.attributes?.payload?.text_color;
},
icon() {
return this.block?.attributes?.payload?.icon;
},
iconColor() {
return this.block?.attributes?.payload?.icon_color;
},
backgroundImageId() {
return this.block?.attributes?.payload?.background_image_id;
},
backgroundImage() {
return this.block?.attributes?.payload?.background_image;
},
backgroundType() {
return this.block?.attributes?.payload?.background_type;
},
complementBackgroundColor() {
return this.calcComplement(this.backgroundColor);
},
icons() {
return contentIcons;
},
colors() {
return this.mixinColors;
},
iconColors() {
return this.mixinColors.filter(color => color.icon && color.class !== 'studip-lightblue');
},
textStyle() {
let style = {};
style.color = this.currentTextColor;
return style;
},
headlineStyle() {
let style = {};
if (this.currentBackgroundType === 'color') {
style['background-color'] = this.currentBackgroundColor;
}
if (this.currentBackgroundType === 'image') {
style['background-color'] = this.currentBackgroundColor;
style['background-image'] = 'url(' + this.currentBackgroundURL + ')';
}
return style;
},
hasSubtitle() {
return !['bigicon_before'].includes(this.currentStyle);
}
},
mounted() {
this.initCurrentData();
},
methods: {
...mapActions({
loadFileRef: 'file-refs/loadById',
updateBlock: 'updateBlockInContainer',
}),
initCurrentData() {
this.currentTitle = this.title;
this.currentSubtitle = this.subtitle;
this.currentStyle = this.style;
this.currentHeight = this.height;
this.currentBackgroundColor = this.backgroundColor;
this.currentTextColor = this.textColor;
this.currentIcon = this.icon;
this.currentIconColor = this.iconColor;
this.currentBackgroundType = this.backgroundType;
this.currentBackgroundImageId = this.backgroundImageId;
if (this.currentBackgroundImageId !== '') {
this.loadFile();
}
},
async loadFile() {
const id = this.currentBackgroundImageId;
const options = { include: 'terms-of-use' };
await this.loadFileRef({ id: id, options });
const fileRef = this.fileRefById({ id: id });
if (fileRef && this.relatedTermOfUse({parent: fileRef, relationship: 'terms-of-use'}).attributes['download-condition'] === 0) {
this.updateCurrentBackgroundImage({
id: fileRef.id,
name: fileRef.attributes.name,
download_url: this.urlHelper.getURL(
'sendfile.php',
{ type: 0, file_id: fileRef.id, file_name: fileRef.attributes.name },
true
),
});
}
},
updateCurrentBackgroundImage(file) {
this.currentBackgroundImage = file;
this.currentBackgroundImageId = file.id;
this.currentBackgroundURL = file.download_url;
},
storeText() {
let attributes = {};
attributes.payload = {};
attributes.payload.title = this.currentTitle;
attributes.payload.subtitle = this.currentSubtitle;
attributes.payload.style = this.currentStyle;
attributes.payload.height = this.currentHeight;
attributes.payload.text_color = this.currentTextColor;
attributes.payload.icon = this.currentIcon;
attributes.payload.icon_color = this.currentIconColor;
attributes.payload.background_type = this.currentBackgroundType;
attributes.payload.background_color = '';
attributes.payload.background_image_id = '';
if (this.currentBackgroundType === 'color') {
attributes.payload.background_color = this.currentBackgroundColor;
}
if (this.currentBackgroundType === 'image') {
attributes.payload.background_image_id = this.currentBackgroundImageId;
}
this.updateBlock({
attributes: attributes,
blockId: this.block.id,
containerId: this.block.relationships.container.data.id,
});
},
calcComplement(color) {
let RGB = this.calcRGB(color);
return '#' + this.compToHex(255 - RGB.r) + this.compToHex(255 - RGB.g) + this.compToHex(255 - RGB.b);
},
calcIconColor(color) {
let RGB = this.calcRGB(color);
return (RGB.r + RGB.g + RGB.b) / 3 > 129 ? 'black' : 'white';
},
calcRGB(color) {
color = color.slice(1); // remove #
let val = parseInt(color, 16);
let r = val >> 16;
let g = (val >> 8) & 0x00ff;
let b = val & 0x0000ff;
if (g > 255) {
g = 255;
} else if (g < 0) {
g = 0;
}
if (b > 255) {
b = 255;
} else if (b < 0) {
b = 0;
}
return { r: r, g: g, b: b };
},
compToHex(comp) {
let hex = comp.toString(16);
return hex.length === 1 ? '0' + hex : hex;
},
},
};
</script>