{"version":3,"file":"stylesheets/4801.css?h=e482c31a1b1ad191f9c7","mappings":"AACA,2FACI,mBAGA,kDACI,YACA,eACA,6BACA,YACA,sDACI,sBC6OZ,wBACA,qBACA,CCzPA,2CACI,qDACA,qGACA,aACA,eACA,2EACI,aACA,YACA,gBACA,0BACA,4BACA,wBACA,yCAGJ,6EACI,aACA,oBACA,gBACA,aACA,qBACA,4BACA,oFACI,eACA,eACA,iBAEJ,+EACI,SACA,mBAMJ,2EACI,mBACA,gBAMJ,0EACI,mBCcZ,2DACA,mDACA,oBACA,CACA,wDACA,oDACA,oBACA,CACA,sDACA,qDACA,oBACA,CCmJA,kDAGA,YACA,eAHA,eACA,aAGA","sources":["webpack://@studip/core/./resources/vue/components/courseware/structural-element/CoursewareTreeItemAdder.vue","webpack://@studip/core/./resources/vue/components/StudipIdentImage.vue","webpack://@studip/core/./resources/vue/components/courseware/structural-element/CoursewareToolsContents.vue","webpack://@studip/core/./resources/vue/components/courseware/widgets/CoursewareTasksActionWidget.vue","webpack://@studip/core/./resources/vue/components/courseware/tasks/PagesTaskGroupsShow.vue"],"sourcesContent":["\n.cw-tree-root-list > .cw-tree-item.cw-tree-item-adder > .cw-tree-item-wrapper {\n    border-bottom: none;\n}\n.cw-tree-item-adder {\n    .add-element {\n        border: none;\n        cursor: pointer;\n        background-color: transparent;\n        height: 28px;\n        img {\n            vertical-align: middle;\n        }\n    }\n}\n","<template>\n    <canvas v-show=\"showCanvas\" ref=\"canvas\"></canvas>\n</template>\n\n<script>\nexport default {\n    name: 'studip-ident-image',\n    props: {\n        value: {\n            type: String,\n        },\n        showCanvas: {\n            type: Boolean,\n            default: false,\n        },\n        baseColor: {\n            type: String, // hex color\n        },\n        pattern: {\n            type: String,\n            required: true,\n        },\n        width: {\n            type: Number,\n            default: 1080,\n        },\n        height: {\n            type: Number,\n            default: 720,\n        },\n        shapesMin: {\n            type: Number,\n            default: 5,\n        },\n        shapesMax: {\n            type: Number,\n            default: 8,\n        },\n    },\n    data() {\n        return {\n            random: null,\n            ellipse: null,\n        };\n    },\n    methods: {\n        randint(min, max) {\n            return Math.floor(this.random() * (max - min) + min);\n        },\n        renderIdentimage() {\n            let canvas = this.$refs.canvas;\n            canvas.width = this.width;\n            canvas.height = this.height;\n\n            const minSize = Math.min(this.width, this.height) * 0.2;\n            const ctx = canvas.getContext('2d');\n            const backgroundHSL = this.hexToHSL(this.baseColor);\n            const numShape = this.randint(this.shapesMin, this.shapesMax);\n            const shapeSizes = [];\n\n            ctx.fillStyle = this.hexToRgbA(this.baseColor, 0.8);\n            ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n            const curveStart = this.randint(10, 70)/100 * this.height;\n            const curveEnd = this.randint(10, 70)/100 * this.height;\n            ctx.strokeStyle = `rgba(255, 255, 255, ${this.randint(50, 70) / 100})`;\n            const curvedistance = this.randint(20, 40);\n            const xFactor = this.randint(10, 45) / 100;\n            const yFactor = this.randint(10, 45) / 100;\n            for (let c = 0; c < numShape * 2; c++) {\n                ctx.beginPath();\n                ctx.moveTo(0, curveStart + curvedistance * c);\n                ctx.bezierCurveTo(this.width * xFactor, this.height * yFactor, this.width * (xFactor + 0.5), this.height * (yFactor + 0.5), this.width, curveEnd + curvedistance * c);\n                ctx.stroke();\n            }\n\n            for (let i = 0; i < numShape; i++) {\n                shapeSizes.push(this.randint(minSize*0.2, minSize*2) + minSize);\n            }\n\n            shapeSizes.sort((a, b) => {\n                return a < b ? 1 : a > b ? -1 : 0;\n            });\n\n            shapeSizes.forEach((shapeSizes, index) => {\n                const radius = shapeSizes / 2;\n                const [x, y] = this.createPointInEllipse(ctx);\n                const x_center = x * (this.width + radius / 2) - radius / 4;\n                const y_center = y * (this.height + radius / 2) - radius / 4;\n\n                ctx.fillStyle = `rgba(255, 255, 255, ${this.randint(10, 80) / 100})`;\n\n                ctx.beginPath();\n\n                if (index % 2 === 0) {\n                    ctx.arc(x_center, y_center, radius, 0, 2 * Math.PI);\n                } else {\n                    const size = radius;\n                    ctx.moveTo(x_center + size * Math.cos(0), y_center + size * Math.sin(0));\n\n                    for (let side = 0; side < 7; side++) {\n                        ctx.lineTo(\n                            x_center + size * Math.cos((side * 2 * Math.PI) / 6),\n                            y_center + size * Math.sin((side * 2 * Math.PI) / 6)\n                        );\n                    }\n                }\n\n                ctx.fill();\n            });\n\n            this.$emit('input', canvas.toDataURL());\n        },\n        createPointInEllipse(ctx) {\n            const x = this.random();\n            const y = this.random();\n\n            if (ctx.isPointInPath(this.ellipse, x, y)) {\n                return [x, y];\n            }\n\n            return this.createPointInEllipse(...arguments);\n        },\n\n        cyrb128(value) {\n            let h1 = 1779033703,\n                h2 = 3144134277,\n                h3 = 1013904242,\n                h4 = 2773480762;\n\n            for (let i = 0, k; i < value.length; i++) {\n                k = value.charCodeAt(i);\n                h1 = h2 ^ Math.imul(h1 ^ k, 597399067);\n                h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);\n                h3 = h4 ^ Math.imul(h3 ^ k, 951274213);\n                h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);\n            }\n\n            h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067);\n            h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233);\n            h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213);\n            h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179);\n\n            return [(h1 ^ h2 ^ h3 ^ h4) >>> 0, (h2 ^ h1) >>> 0, (h3 ^ h1) >>> 0, (h4 ^ h1) >>> 0];\n        },\n        sfc32(a, b, c, d) {\n            return function () {\n                a >>>= 0;\n                b >>>= 0;\n                c >>>= 0;\n                d >>>= 0;\n                var t = (a + b) | 0;\n                a = b ^ (b >>> 9);\n                b = (c + (c << 3)) | 0;\n                c = (c << 21) | (c >>> 11);\n                d = (d + 1) | 0;\n                t = (t + d) | 0;\n                c = (c + t) | 0;\n\n                return (t >>> 0) / 4294967296;\n            };\n        },\n\n        hexToRGB(color) {\n            color = color.slice(1); // remove #\n            let val = parseInt(color, 16);\n            let r = val >> 16;\n            let g = (val >> 8) & 0x00ff;\n            let b = val & 0x0000ff;\n\n            if (g > 255) {\n                g = 255;\n            } else if (g < 0) {\n                g = 0;\n            }\n            if (b > 255) {\n                b = 255;\n            } else if (b < 0) {\n                b = 0;\n            }\n\n            return { r: r, g: g, b: b };\n        },\n        RGBToHSL(r, g, b) {\n            r /= 255;\n            g /= 255;\n            b /= 255;\n\n            let cmin = Math.min(r, g, b),\n                cmax = Math.max(r, g, b),\n                delta = cmax - cmin,\n                h = 0,\n                s = 0,\n                l = 0;\n            if (delta == 0) h = 0;\n            // Red is max\n            else if (cmax == r) h = ((g - b) / delta) % 6;\n            // Green is max\n            else if (cmax == g) h = (b - r) / delta + 2;\n            // Blue is max\n            else h = (r - g) / delta + 4;\n\n            h = Math.round(h * 60);\n\n            if (h < 0) h += 360;\n            l = (cmax + cmin) / 2;\n\n            s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));\n\n            s = +(s * 100).toFixed(1);\n            l = +(l * 100).toFixed(1);\n\n            return { h: h, s: s, l: l };\n            // return 'hsl(' + h + ',' + s + '%,' + l + '%)';\n        },\n        hexToHSL(color) {\n            const RGB = this.hexToRGB(color);\n            return this.RGBToHSL(RGB.r, RGB.g, RGB.b);\n        },\n        hexToRgbA(hex, a){\n            const RGB = this.hexToRGB(hex);\n\n            return 'rgba(' + RGB.r + ',' + RGB.g + ',' + RGB.b + ',' + a +')';\n        },\n        init() {\n            const seed = this.cyrb128(this.pattern);\n            this.random = this.sfc32(...seed);\n            this.ellipse = new Path2D();\n            this.ellipse.ellipse(0.5, 0.5, 0.5, 0.5, 0, 0, Math.PI * 2);\n            this.renderIdentimage();\n        }\n    },\n    mounted() {\n        this.init();\n    },\n    watch: {\n        baseColor() {\n            this.init();\n        },\n    },\n};\n</script>\n<style scoped>\n  canvas {\n    background-color: #fff;\n  }\n</style>\n","\n.cw-tools-contents-header {\n    display: flex;\n    flex-direction: row;\n    height: 100px;\n    margin-top: 8px;\n    .cw-tools-contents-header-image {\n        height: 100px;\n        width: 150px;\n        min-width: 150px;\n        background-size: 100% auto;\n        background-repeat: no-repeat;\n        background-position: center;\n        background-color: var(--content-color-20);\n    }\n\n    .cw-tools-contents-header-details {\n        margin: 0 8px;\n        display: -webkit-box;\n        overflow: hidden;\n        height: 100px;\n        -webkit-line-clamp: 5;\n        -webkit-box-orient: vertical;\n        header {\n            margin: 0 0 6px 0;\n            font-size: 16px;\n            line-height: 16px;\n        }\n        p {\n            margin: 0;\n            color: var(--black);\n        }\n    }\n}\n.root-is-current {\n    .cw-tools-contents-header-details {\n        header {\n            color: var(--black);\n            font-weight: 600;\n        }\n    }\n}\n.root-is-hidden {\n    .cw-tools-contents-header-details {\n        header {\n            color: var(--black);\n        }\n    }\n}\n","<template>\n    <sidebar-widget id=\"courseware-action-widget\" :title=\"$gettext('Aktionen')\">\n        <template #content>\n            <ul class=\"widget-list widget-links cw-action-widget\">\n                <template v-if=\"taskGroup\">\n                    <li v-if=\"isBeforeEndDate\" class=\"cw-action-widget-task-groups-deadline\">\n                        <button @click=\"modifyDeadline(taskGroup)\">\n                            {{ $gettext('Bearbeitungszeit verlängern') }}\n                        </button>\n                    </li>\n                    <li v-if=\"isBeforeEndDate\" class=\"cw-action-widget-task-groups-add-solvers\">\n                        <button @click=\"addSolvers(taskGroup)\">\n                            {{ $gettext('Teilnehmende hinzufügen') }}\n                        </button>\n                    </li>\n                    <li class=\"cw-action-widget-task-groups-delete\">\n                        <button @click=\"deleteTaskGroup(taskGroup)\">\n                            {{ $gettext('Aufgabe löschen') }}\n                        </button>\n                    </li>\n                </template>\n                <li v-else class=\"cw-action-widget-add\">\n                    <button @click=\"setShowTasksDistributeDialog(true)\">\n                        {{ $gettext('Aufgabe verteilen') }}\n                    </button>\n                </li>\n            </ul>\n        </template>\n    </sidebar-widget>\n</template>\n\n<script>\nimport SidebarWidget from '../../SidebarWidget.vue';\n\nimport { mapActions } from 'vuex';\n\nexport default {\n    name: 'courseware-tasks-action-widget',\n    components: {\n        SidebarWidget,\n    },\n    props: ['taskGroup'],\n    computed: {\n        isBeforeEndDate() {\n            return this.taskGroup && new Date() < new Date(this.taskGroup.attributes['end-date']);\n        },\n    },\n    methods: {\n        ...mapActions({\n            addSolvers: 'tasks/setShowTaskGroupsAddSolversDialog',\n            deleteTaskGroup: 'tasks/setShowTaskGroupsDeleteDialog',\n            modifyDeadline: 'tasks/setShowTaskGroupsModifyDeadlineDialog',\n            setShowTasksDistributeDialog: 'tasks/setShowTasksDistributeDialog',\n        }),\n    },\n};\n</script>\n\n<style scoped>\n.cw-action-widget-task-groups-add-solvers {\n    background-image: url('../images/icons/blue/add.svg');\n    background-size: 16px;\n}\n.cw-action-widget-task-groups-deadline {\n    background-image: url('../images/icons/blue/date.svg');\n    background-size: 16px;\n}\n.cw-action-widget-task-groups-delete {\n    background-image: url('../images/icons/blue/trash.svg');\n    background-size: 16px;\n}\n</style>\n","<template>\n    <div class=\"cw-tasks-wrapper\">\n        <MountingPortal mountTo=\"#courseware-action-widget\" name=\"sidebar-actions\" v-if=\"userIsTeacher\">\n            <CoursewareTasksActionWidget :taskGroup=\"taskGroup\" />\n        </MountingPortal>\n\n        <div v-if=\"taskGroup\" class=\"cw-tasks-list\">\n            <CoursewareRibbon :isContentBar=\"true\" :showToolbarButton=\"false\">\n                <template #buttons>\n                    <router-link :to=\"{ name: 'task-groups-index' }\">\n                        <StudipIcon shape=\"category-task\" :size=\"24\" />\n                    </router-link>\n                </template>\n                <template #breadcrumbList>\n                    <li>\n                        <router-link :to=\"{ name: 'task-groups-index' }\">\n                            {{ $gettext('Aufgaben') }}\n                        </router-link>\n                    </li>\n                    <li>{{ taskGroup.attributes['title'] }}</li>\n                </template>\n            </CoursewareRibbon>\n\n            <TaskGroup\n                :taskGroup=\"taskGroup\"\n                :tasks=\"tasksByGroup[taskGroup.id]\"\n                @add-feedback=\"onShowAddFeedback\"\n                @edit-feedback=\"onShowEditFeedback\"\n                @solve-renewal=\"onShowSolveRenewal\"\n            />\n        </div>\n        <CompanionBox\n            v-else-if=\"!tasksLoading\"\n            :msgCompanion=\"$gettext('Diese Courseware-Aufgabe konnte nicht gefunden werden.')\"\n        />\n\n        <AddFeedbackDialog\n            v-if=\"showAddFeedbackDialog\"\n            :content=\"currentDialogFeedback.attributes.content\"\n            @create=\"createFeedback\"\n            @close=\"closeDialogs\"\n        />\n\n        <EditFeedbackDialog\n            v-if=\"showEditFeedbackDialog\"\n            :content=\"currentDialogFeedback.attributes.content\"\n            @update=\"updateFeedback\"\n            @close=\"closeDialogs\"\n        />\n\n        <RenewalDialog\n            v-if=\"renewalTask\"\n            :renewalDate=\"renewalDate\"\n            :renewalState=\"renewalTask.attributes.renewal\"\n            @update=\"updateRenewal\"\n            @close=\"closeDialogs\"\n        />\n\n        <TaskGroupsAddSolversDialog v-if=\"showTaskGroupsAddSolversDialog\" :taskGroup=\"taskGroup\" @newtask=\"reloadTasks\" />\n        <TaskGroupsDeleteDialog v-if=\"showTaskGroupsDeleteDialog\" :taskGroup=\"taskGroup\" />\n        <TaskGroupsModifyDeadlineDialog v-if=\"showTaskGroupsModifyDeadlineDialog\" :taskGroup=\"taskGroup\" />\n        <CoursewareTasksDialogDistribute v-if=\"showTasksDistributeDialog\" @newtask=\"reloadTasks\" />\n    </div>\n</template>\n\n<script>\nimport { mapActions, mapGetters } from 'vuex';\nimport AddFeedbackDialog from './AddFeedbackDialog.vue';\nimport CompanionBox from '../layouts/CoursewareCompanionBox.vue';\nimport CoursewareRibbon from '../structural-element/CoursewareRibbon.vue';\nimport CoursewareTasksActionWidget from '../widgets/CoursewareTasksActionWidget.vue';\nimport CoursewareTasksDialogDistribute from './CoursewareTasksDialogDistribute.vue';\nimport EditFeedbackDialog from './EditFeedbackDialog.vue';\nimport RenewalDialog from './RenewalDialog.vue';\nimport TaskGroup from './TaskGroup.vue';\nimport TaskGroupsAddSolversDialog from './TaskGroupsAddSolversDialog.vue';\nimport TaskGroupsDeleteDialog from './TaskGroupsDeleteDialog.vue';\nimport TaskGroupsModifyDeadlineDialog from './TaskGroupsModifyDeadlineDialog.vue';\n\nexport default {\n    components: {\n        AddFeedbackDialog,\n        CompanionBox,\n        CoursewareRibbon,\n        CoursewareTasksActionWidget,\n        CoursewareTasksDialogDistribute,\n        EditFeedbackDialog,\n        RenewalDialog,\n        TaskGroup,\n        TaskGroupsAddSolversDialog,\n        TaskGroupsDeleteDialog,\n        TaskGroupsModifyDeadlineDialog,\n    },\n    props: ['id'],\n    data() {\n        return {\n            currentDialogFeedback: {},\n            renewalTask: null,\n            showAddFeedbackDialog: false,\n            showEditFeedbackDialog: false,\n        };\n    },\n    computed: {\n        ...mapGetters({\n            context: 'context',\n            getTaskGroup: 'courseware-task-groups/byId',\n            showTaskGroupsAddSolversDialog: 'tasks/showTaskGroupsAddSolversDialog',\n            showTaskGroupsDeleteDialog: 'tasks/showTaskGroupsDeleteDialog',\n            showTaskGroupsModifyDeadlineDialog: 'tasks/showTaskGroupsModifyDeadlineDialog',\n            showTasksDistributeDialog: 'tasks/showTasksDistributeDialog',\n            tasksByCid: 'tasks/tasksByCid',\n            tasksLoading: 'courseware-tasks/isLoading',\n            userIsTeacher: 'userIsTeacher',\n        }),\n        renewalDate() {\n            return this.renewalTask ? new Date(this.renewalTask.attributes['renewal-date']) : new Date();\n        },\n        taskGroup() {\n            return this.getTaskGroup({ id: this.id });\n        },\n        tasksByGroup() {\n            return this.tasksByCid(this.context.id).reduce((memo, task) => {\n                const key = task.relationships['task-group'].data.id;\n                (memo[key] || (memo[key] = [])).push(task);\n\n                return memo;\n            }, {});\n        },\n    },\n    methods: {\n        ...mapActions({\n            companionError: 'companionError',\n            companionSuccess: 'companionSuccess',\n            createTaskFeedback: 'createTaskFeedback',\n            deleteTaskFeedback: 'deleteTaskFeedback',\n            loadAllTasks: 'courseware-tasks/loadAll',\n            loadTaskGroup: 'tasks/loadTaskGroup',\n            updateTask: 'updateTask',\n            updateTaskFeedback: 'updateTaskFeedback',\n        }),\n        closeDialogs() {\n            this.showAddFeedbackDialog = false;\n            this.showEditFeedbackDialog = false;\n\n            this.currentDialogFeedback = {};\n            this.renewalTask = null;\n        },\n        createFeedback({ content }) {\n            if (content === '') {\n                this.companionError({\n                    info: this.$gettext('Bitte schreiben Sie ein Feedback.'),\n                });\n                return false;\n            }\n            this.currentDialogFeedback.attributes.content = content;\n            this.createTaskFeedback({ taskFeedback: this.currentDialogFeedback });\n            this.closeDialogs();\n        },\n        onShowAddFeedback(task) {\n            this.currentDialogFeedback = {\n                attributes: { content: '' },\n                relationships: {\n                    task: {\n                        data: {\n                            id: task.id,\n                            type: task.type,\n                        },\n                    },\n                },\n            };\n            this.showAddFeedbackDialog = true;\n        },\n        onShowEditFeedback(feedback) {\n            this.currentDialogFeedback = _.cloneDeep(feedback);\n            this.showEditFeedbackDialog = true;\n        },\n        onShowSolveRenewal(task) {\n            this.renewalTask = _.cloneDeep(task);\n            this.renewalTask.attributes['renewal-date'] = new Date().toISOString();\n        },\n        reloadTasks() {\n            this.loadAllTasks({\n                options: {\n                    'filter[cid]': this.context.id,\n                    include: 'solver, structural-element, task-feedback, task-group, task-group.lecturer',\n                },\n            });\n        },\n        updateRenewal({ state, date }) {\n            const attributes = { renewal: state };\n            if (date) {\n                attributes['renewal-date'] = date.toISOString();\n            }\n\n            this.updateTask({ attributes, taskId: this.renewalTask.id });\n            this.closeDialogs();\n        },\n        async updateFeedback({ content }) {\n            if (content === '') {\n                await this.deleteTaskFeedback({ taskFeedbackId: this.currentDialogFeedback.id });\n                this.companionSuccess({ info: this.$gettext('Feedback wurde gelöscht.') });\n            } else {\n                await this.updateTaskFeedback({\n                    attributes: { content },\n                    taskFeedbackId: this.currentDialogFeedback.id,\n                });\n                this.companionSuccess({\n                    info: this.$gettext('Feedback wurde gespeichert.'),\n                });\n            }\n            this.closeDialogs();\n        },\n    },\n};\n</script>\n\n<style scoped>\n.cw-tasks-wrapper >>> .cw-ribbon-nav {\n    min-width: 24px;\n    padding: 0 1em;\n    height: 24px;\n    margin-top: 2px;\n}\n</style>\n"],"names":[],"sourceRoot":""}