Skip to content
Snippets Groups Projects
Select Git revision
  • 9a9c85fe87f8f30e99f03e19a895f9f5fb7a425f
  • main default protected
  • 5.5 protected
  • atlantis
  • 5.3 protected
  • 5.0 protected
  • issue-23
  • issue8-seat-logging-and-export
  • ticket-216
  • tickets-215-216-241-242
10 results

CoursewareDialogCardsBlock.vue

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    CoursewareDialogCardsBlock.vue 11.44 KiB
    <template>
        <div class="cw-block cw-block-dialog-cards">
            <courseware-default-block
                :block="block"
                :canEdit="canEdit"
                :isTeacher="isTeacher"
                :preview="true"
                @showEdit="initCurrentData"
                @storeEdit="storeBlock"
                @closeEdit="initCurrentData"
            >
                <template #content>
                    <div class="cw-block-dialog-cards-content">
                        <button
                            class="cw-dialogcards-prev cw-dialogcards-navbutton"
                            :class="{'cw-dialogcards-prev-disabled': hasNoPerv}"
                            @click="prevCard"
                            :title="hasNoPerv ? $gettext('keine vorherige Karte') : $gettext('zur vorherigen Karte')"
                        >
                        </button>
                        <div class="cw-dialogcards">
                            <div
                                class="scene scene--card"
                                :class="[card.active ? 'active' : '']"
                                v-for="card in currentCards"
                                :key="card.index"
                            >
                                <div
                                    class="card"
                                    tabindex="0"
                                    :title="$gettext('Karte umdrehen')"
                                    @click="flipCard"
                                    @keydown.enter="flipCard"
                                    @keydown.space="flipCard"
                                >
                                    <div class="card__face card__face--front">
                                        <img v-if="card.front_file.length !== 0" :src="card.front_file.download_url" />
                                        <div v-else class="cw-dialogcards-front-no-image"></div>
                                        <p>{{ card.front_text }}</p>
                                    </div>
                                    <div class="card__face card__face--back">
                                        <img v-if="card.back_file.length !== 0" :src="card.back_file.download_url" />
                                        <div v-else class="cw-dialogcards-back-no-image"></div>
                                        <p>{{ card.back_text }}</p>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <button
                            class="cw-dialogcards-next cw-dialogcards-navbutton"
                            :class="{'cw-dialogcards-next-disabled': hasNoNext}"
                            @click="nextCard"
                            :title="hasNoNext ? $gettext('keine nächste Karte') : $gettext('zur nächsten Karte')"
                        >
                        </button>
                    </div>
                </template>
                <template v-if="canEdit" #edit>
                    <button class="button add" @click="addCard"><translate>Karte hinzufügen</translate></button>
                    <courseware-tabs
                        v-if="currentCards.length > 0"
                        :setSelected="setCardTab"
                        @selectTab="activateCard(parseInt($event.name.replace($gettext('Karte') +  ' ', '')) - 1)"
                    >
                        <courseware-tab
                            v-for="(card, index) in currentCards"
                            :key="index"
                            :index="index"
                            :name="$gettext('Karte') +  ' ' + (index + 1).toString()"
                            :selected="index === 0"
                            canBeEmpty
                        >
                            <form class="default" @submit.prevent="">
                                <label>
                                    <translate>Bild Vorderseite</translate>:
                                    <courseware-file-chooser
                                        v-model="card.front_file_id"
                                        :isImage="true"
                                        :canBeEmpty="true"
                                        @selectFile="updateFile(index, 'front', $event)"
                                    />
                                </label>
                                <label>
                                    <translate>Text Vorderseite</translate>:
                                    <input type="text" v-model="card.front_text" />
                                </label>
                                <label>
                                    <translate>Bild Rückseite</translate>:
                                    <courseware-file-chooser
                                        v-model="card.back_file_id"
                                        :isImage="true"
                                        :canBeEmpty="true"
                                        @selectFile="updateFile(index, 'back', $event)"
                                    />
                                </label>
                                <label>
                                    <translate>Text Rückseite</translate>:
                                    <input type="text" v-model="card.back_text" />
                                </label>
                                <label v-if="!onlyCard">
                                    <button class="button trash" @click="removeCard(index)">
                                        <translate>Karte entfernen</translate>
                                    </button>
                                </label>
                            </form>
                        </courseware-tab>
                    </courseware-tabs>
                </template>
                <template #info>
                    <p><translate>Informationen zum Lernkarten-Block</translate></p>
                </template>
            </courseware-default-block>
        </div>
    </template>
    
    <script>
    import CoursewareDefaultBlock from './CoursewareDefaultBlock.vue';
    import CoursewareFileChooser from './CoursewareFileChooser.vue';
    import CoursewareTabs from './CoursewareTabs.vue';
    import CoursewareTab from './CoursewareTab.vue';
    import { blockMixin } from './block-mixin.js';
    import { mapActions } from 'vuex';
    
    export default {
        name: 'courseware-dialog-cards-block',
        mixins: [blockMixin],
        components: {
            CoursewareDefaultBlock,
            CoursewareFileChooser,
            CoursewareTabs,
            CoursewareTab,
        },
        props: {
            block: Object,
            canEdit: Boolean,
            isTeacher: Boolean,
        },
        data() {
            return {
                currentCards: [],
                setCardTab: 0
            };
        },
        computed: {
            cards() {
                return this.block?.attributes?.payload?.cards;
            },
            onlyCard() {
                return this.currentCards.length === 1;
            },
            hasNoPerv() {
                if(this.currentCards[0] !== undefined) {
                    return this.currentCards[0].active;
                } else {
                    return true;
                }
            },
            hasNoNext() {
                if (this.currentCards[this.currentCards.length - 1] !== undefined) {
                    return this.currentCards[this.currentCards.length - 1].active;
                } else {
                    return true;
                }
            }
        },
        mounted() {
            this.initCurrentData();
        },
        methods: {
            ...mapActions({
                updateBlock: 'updateBlockInContainer',
            }),
            initCurrentData() {
                if (this.cards !== '') {
                    let cards = JSON.parse(JSON.stringify(this.cards));
                    cards.forEach((card, index) => {
                        card.active = false;
                        if (index === 0) {
                            card.active = true;
                        }
                    });
                    this.currentCards = cards;
                }
                this.setCardTab = 0;
            },
            storeBlock() {
                let cards = JSON.parse(JSON.stringify(this.currentCards));
                // don't store the file object
                cards.forEach((card) => {
                    delete card.front_file;
                    delete card.back_file;
                    delete card.active;
                });
                let attributes = {};
                attributes.payload = {};
                attributes.payload.cards = cards;
    
                this.updateBlock({
                    attributes: attributes,
                    blockId: this.block.id,
                    containerId: this.block.relationships.container.data.id,
                });
            },
            updateFile(cardIndex, side, file) {
                if (side === 'front') {
                    if (file) {
                        this.currentCards[cardIndex].front_file_id = file.id;
                        this.currentCards[cardIndex].front_file = file;
                    }
                    else {
                        this.currentCards[cardIndex].front_file_id = '';
                        this.currentCards[cardIndex].front_file = [];
                    }
                }
                if (side === 'back') {
                    if (file) {
                        this.currentCards[cardIndex].back_file_id = file.id;
                        this.currentCards[cardIndex].back_file = file;
                    } else {
                        this.currentCards[cardIndex].back_file_id = '';
                        this.currentCards[cardIndex].back_file = [];
                    }
                }
            },
            addCard() {
                this.currentCards.push({
                    index: this.currentCards.length,
                    front_file_id: '',
                    front_file: [],
                    front_text: '',
                    back_file_id: '',
                    back_text: '',
                    back_file: [],
                    active: false
                });
                const index = this.currentCards.length - 1;
                this.activateCard(index);
                this.$nextTick(() => { this.setCardTab = index; });
            },
            removeCard(cardIndex){
                this.currentCards = this.currentCards.filter((val, index) => {
                    return !(index === cardIndex);
                });
                this.$nextTick(() => { this.setCardTab = 0; });
            },
            flipCard(event) {
                event.currentTarget.classList.toggle('is-flipped');
            },
            nextCard() {
                let view = this;
                this.currentCards.every((card, index) => {
                    if (card.active) {
                        if (view.currentCards.length > index + 1) {
                            card.active = false;
                            view.currentCards[index + 1].active = true;
                            view.setCardTab = index + 1;
                        }
                        return false; // end every
                    } else {
                        return true; // continue every
                    }
                });
            },
            prevCard() {
                let view = this;
                this.currentCards.every((card, index) => {
                    if (card.active) {
                        if (index > 0) {
                            card.active = false;
                            view.currentCards[index - 1].active = true;
                            view.setCardTab = index - 1;
                        }
                        return false; // end every
                    } else {
                        return true; // continue every
                    }
                });
            },
            activateCard(selectedIndex) {
                selectedIndex = parseInt(selectedIndex);
                if (selectedIndex > this.currentCards.length - 1) {
                    console.log('can not select this card');
                    return false;
                }
                this.currentCards.forEach((card, index) => {
                    if (index === selectedIndex) {
                        card.active = true;
                    } else {
                        card.active = false;
                    }
                });
            },
        },
    };
    </script>