258 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			258 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Vue
		
	
	
	
<template>
 | 
						|
    <div>
 | 
						|
        <div class="flex flex-col group" :for="id" :class="sizeClass(size)">
 | 
						|
            <f-label v-if="label" :required="required" :value="label"></f-label>
 | 
						|
            <div class="relative w-full h-full">
 | 
						|
                <div :id="id" :class="[fieldAppearance, paddingX, paddingY]"></div>
 | 
						|
                <f-hint v-if="hint" :value="hint"></f-hint>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
 | 
						|
        <ui-popup
 | 
						|
            v-if="condition !== null"
 | 
						|
            heading="Bedingungen"
 | 
						|
            @close="
 | 
						|
                condition.resolve(condition.data);
 | 
						|
                condition = null;
 | 
						|
            "
 | 
						|
        >
 | 
						|
            <slot name="conditions" :data="condition.data" :resolve="condition.resolve" :reject="condition.reject"></slot>
 | 
						|
        </ui-popup>
 | 
						|
    </div>
 | 
						|
</template>
 | 
						|
 | 
						|
<script setup>
 | 
						|
import {debounce} from 'lodash';
 | 
						|
import {onMounted, ref} from 'vue';
 | 
						|
import EditorJS from '@editorjs/editorjs';
 | 
						|
import Header from '@editorjs/header';
 | 
						|
import Paragraph from '@editorjs/paragraph';
 | 
						|
import NestedList from '@editorjs/nested-list';
 | 
						|
import Alert from 'editorjs-alert';
 | 
						|
import useFieldSize from '../../composables/useFieldSize.js';
 | 
						|
const emit = defineEmits(['update:modelValue']);
 | 
						|
 | 
						|
const {fieldAppearance, paddingX, paddingY, sizeClass} = useFieldSize();
 | 
						|
 | 
						|
const props = defineProps({
 | 
						|
    required: {
 | 
						|
        type: Boolean,
 | 
						|
        default: false,
 | 
						|
    },
 | 
						|
    size: {
 | 
						|
        type: String,
 | 
						|
        default: () => 'base',
 | 
						|
    },
 | 
						|
    rows: {
 | 
						|
        type: Number,
 | 
						|
        default: () => 4,
 | 
						|
    },
 | 
						|
    id: {
 | 
						|
        type: String,
 | 
						|
        required: true,
 | 
						|
    },
 | 
						|
    conditions: {
 | 
						|
        required: false,
 | 
						|
        type: Boolean,
 | 
						|
        default: () => false,
 | 
						|
    },
 | 
						|
    hint: {
 | 
						|
        type: String,
 | 
						|
        default: () => '',
 | 
						|
    },
 | 
						|
    modelValue: {
 | 
						|
        default: undefined,
 | 
						|
    },
 | 
						|
    label: {
 | 
						|
        type: String,
 | 
						|
        default: () => '',
 | 
						|
    },
 | 
						|
});
 | 
						|
 | 
						|
const editor = ref(null);
 | 
						|
const condition = ref(null);
 | 
						|
 | 
						|
async function openPopup(data) {
 | 
						|
    return new Promise((resolve, reject) => {
 | 
						|
        new Promise((innerResolve, innerReject) => {
 | 
						|
            condition.value = {
 | 
						|
                resolve: innerResolve,
 | 
						|
                reject: innerReject,
 | 
						|
                data: data,
 | 
						|
            };
 | 
						|
        }).then((data) => {
 | 
						|
            resolve(data);
 | 
						|
            condition.value = null;
 | 
						|
        });
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
class ConditionTune {
 | 
						|
    constructor({api, data, config, block}) {
 | 
						|
        this.api = api;
 | 
						|
        this.data = data || {
 | 
						|
            mode: 'all',
 | 
						|
            ifs: [],
 | 
						|
        };
 | 
						|
        this.config = config;
 | 
						|
        this.block = block;
 | 
						|
        this.wrapper = null;
 | 
						|
    }
 | 
						|
 | 
						|
    static get isTune() {
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    wrap(blockContent) {
 | 
						|
        this.wrapper = document.createElement('div');
 | 
						|
 | 
						|
        var tooltip = document.createElement('div');
 | 
						|
        tooltip.setAttribute('data-tooltip', '');
 | 
						|
 | 
						|
        var content = document.createElement('div');
 | 
						|
        content.setAttribute('data-content', '');
 | 
						|
 | 
						|
        content.appendChild(blockContent);
 | 
						|
 | 
						|
        this.wrapper.appendChild(tooltip);
 | 
						|
        this.wrapper.appendChild(content);
 | 
						|
 | 
						|
        this.styleWrapper();
 | 
						|
 | 
						|
        return this.wrapper;
 | 
						|
    }
 | 
						|
 | 
						|
    hasData() {
 | 
						|
        return this.data.ifs.length > 0;
 | 
						|
    }
 | 
						|
 | 
						|
    styleWrapper() {
 | 
						|
        if (this.hasData()) {
 | 
						|
            this.wrapper.querySelector('[data-content]').className = 'p-1 border border-blue-100 rounded';
 | 
						|
            this.wrapper.querySelector('[data-tooltip]').className =
 | 
						|
                'mt-1 inline-block tracking-wider font-semibold ml-2 mr-2 px-2 py-1 items-center text-xs leading-none bg-blue-100 text-blue-900 rounded-t-lg';
 | 
						|
            this.wrapper.querySelector('[data-tooltip]').innerHTML = this.descriptionName();
 | 
						|
        } else {
 | 
						|
            this.wrapper.querySelector('[data-content]').className = '';
 | 
						|
            this.wrapper.querySelector('[data-tooltip]').className = '';
 | 
						|
            this.wrapper.querySelector('[data-tooltip]').innerHTML = '';
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    descriptionName() {
 | 
						|
        return (
 | 
						|
            'Bedingung ' +
 | 
						|
            this.data.ifs
 | 
						|
                .map((i) => {
 | 
						|
                    var parts = [i.field];
 | 
						|
 | 
						|
                    if (i.comparator === 'isEqual' || i.comparator === 'isIn') {
 | 
						|
                        parts.push('=');
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (i.comparator === 'isNotEqual' || i.comparator === 'isNotIn') {
 | 
						|
                        parts.push('≠');
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (typeof i.value === 'string') {
 | 
						|
                        parts.push(i.value);
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (Array.isArray(i.value)) {
 | 
						|
                        parts.push(i.value.join(', '));
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (typeof i.value === 'boolean') {
 | 
						|
                        parts.push(i.value ? 'An' : 'Aus');
 | 
						|
                    }
 | 
						|
 | 
						|
                    return parts.join(' ');
 | 
						|
                })
 | 
						|
                .join(', ')
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    render() {
 | 
						|
        return {
 | 
						|
            label: 'Bedingungen',
 | 
						|
            closeOnActivate: true,
 | 
						|
            toggle: true,
 | 
						|
            onActivate: async () => {
 | 
						|
                this.data = await openPopup(this.data);
 | 
						|
                this.styleWrapper();
 | 
						|
                this.block.dispatchChange();
 | 
						|
            },
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    save() {
 | 
						|
        return this.data;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
onMounted(async () => {
 | 
						|
    var tools = {
 | 
						|
        paragraph: {
 | 
						|
            class: Paragraph,
 | 
						|
            shortcut: 'CTRL+P',
 | 
						|
            inlineToolbar: true,
 | 
						|
            config: {
 | 
						|
                preserveBlank: true,
 | 
						|
                placeholder: 'Absatz',
 | 
						|
            },
 | 
						|
        },
 | 
						|
        alert: {
 | 
						|
            class: Alert,
 | 
						|
            inlineToolbar: true,
 | 
						|
            config: {
 | 
						|
                defaultType: 'primary',
 | 
						|
            },
 | 
						|
        },
 | 
						|
        heading: {
 | 
						|
            class: Header,
 | 
						|
            shortcut: 'CTRL+H',
 | 
						|
            inlineToolbar: true,
 | 
						|
            config: {
 | 
						|
                placeholder: 'Überschrift',
 | 
						|
                levels: [2, 3, 4],
 | 
						|
                defaultLevel: 2,
 | 
						|
            },
 | 
						|
        },
 | 
						|
        list: {
 | 
						|
            class: NestedList,
 | 
						|
            shortcut: 'CTRL+L',
 | 
						|
            inlineToolbar: true,
 | 
						|
        },
 | 
						|
    };
 | 
						|
 | 
						|
    var tunes = [];
 | 
						|
 | 
						|
    if (props.conditions) {
 | 
						|
        tools.condition = {
 | 
						|
            class: ConditionTune,
 | 
						|
        };
 | 
						|
        tunes.push('condition');
 | 
						|
    }
 | 
						|
 | 
						|
    editor.value = new EditorJS({
 | 
						|
        placeholder: props.placeholder,
 | 
						|
        holder: props.id,
 | 
						|
        minHeight: 0,
 | 
						|
        defaultBlock: 'paragraph',
 | 
						|
        data: JSON.parse(JSON.stringify(props.modelValue)),
 | 
						|
        tunes: tunes,
 | 
						|
        tools: tools,
 | 
						|
        onChange: debounce(async (api, event) => {
 | 
						|
            const data = await editor.value.save();
 | 
						|
            console.log(data);
 | 
						|
            emit('update:modelValue', data);
 | 
						|
        }, 200),
 | 
						|
        onPopup: () => {
 | 
						|
            console.log('opened');
 | 
						|
        },
 | 
						|
    });
 | 
						|
    await editor.value.isReady;
 | 
						|
    console.log('Editor is ready');
 | 
						|
});
 | 
						|
</script>
 |