285 lines
8.5 KiB
Vue
285 lines
8.5 KiB
Vue
<template>
|
|
<div
|
|
:class="`slider-component slider-${inputParameters.name}`"
|
|
ref="slider"
|
|
>
|
|
<div
|
|
v-if="itemParameters.list.length > 0"
|
|
>
|
|
<div
|
|
class="border rounded-3 p-3 mb-3"
|
|
v-for="(item, itemIndex) of itemParameters.list"
|
|
:key="itemIndex"
|
|
>
|
|
<div
|
|
class="d-flex justify-content-between align-items-center"
|
|
>
|
|
<legend class="w-fit me-2 mb-0">
|
|
Slide n°{{ itemIndex + 1 }}
|
|
</legend>
|
|
<div
|
|
v-if="buttonsDisplayParameters.remove"
|
|
class="align-bottom"
|
|
>
|
|
<button
|
|
@click.stop.prevent="removeLine(itemIndex)"
|
|
class="btn btn-sm btn-danger"
|
|
:title="trans.methods.__('Supprimer la ligne')"
|
|
data-bs-toggle="tooltip"
|
|
>
|
|
<i class="fa-solid fa-trash" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="row"
|
|
>
|
|
<div
|
|
class="col-6 mb-3"
|
|
v-for="(column, columnIndex) of itemParameters.columns"
|
|
:key="columnIndex"
|
|
>
|
|
<label class="py-2">
|
|
<b>{{ column.placeholder + (column.required ? '*' : '') }}</b>
|
|
</label>
|
|
<div
|
|
v-if="itemParameters.columns[columnIndex].type == 'wysiwyg'"
|
|
:class="(getErrorMessage(itemIndex, column.id) !== null) ? 'is-invalid' : ''"
|
|
>
|
|
<CkEditorComponent
|
|
:name="`data[${inputParameters.name}][value][${String(itemIndex)}][${column.id}]`"
|
|
:placeholder="itemParameters.columns[columnIndex].placeholder"
|
|
:dbtext="String(item[column.id as keyof typeof item] ?? '')"
|
|
:required="true"
|
|
:errors="allErrors"
|
|
:editor-config="itemParameters.wysiwygConfig"
|
|
/>
|
|
</div>
|
|
<div
|
|
v-else-if="itemParameters.columns[columnIndex].type == 'picture'"
|
|
:class="(getErrorMessage(itemIndex, column.id) !== null) ? 'is-invalid' : ''"
|
|
>
|
|
<ImageInputComponent
|
|
:id="'picture-input-' + inputParameters.name + '-' + column.id + '-' + itemIndex"
|
|
:required="itemParameters.columns[columnIndex].required"
|
|
:show-labels="true"
|
|
:name="`data[${inputParameters.name}][value][${String(itemIndex)}][${column.id}]`"
|
|
:helper="trans.methods.__('crud.minicrud.dimensions_must_be', {
|
|
widthpx: (itemParameters.imageSizes[0] ?? String(500)) + 'px',
|
|
heightpx: (itemParameters.imageSizes[1] ?? String(500)) + 'px',
|
|
})"
|
|
:width="itemParameters.imageSizes[0] ?? 500"
|
|
:height="itemParameters.imageSizes[1] ?? 500"
|
|
:value="item[column.id as keyof typeof item] ? String(item[column.id as keyof typeof item]) : undefined"
|
|
:preview="false"
|
|
:browse-event="false"
|
|
/>
|
|
</div>
|
|
|
|
<div
|
|
v-else
|
|
>
|
|
<WordCounter
|
|
:id="'text-input-' + inputParameters.name + '-' + column.id + '-' + itemIndex"
|
|
class="ck-word-count"
|
|
/>
|
|
<input
|
|
:id="'text-input-' + inputParameters.name + '-' + column.id + '-' + itemIndex"
|
|
:class="['form-control', (getErrorMessage(itemIndex, column.id) !== null) ? 'is-invalid' : '']"
|
|
:name="`data[${inputParameters.name}][value][${String(itemIndex)}][${column.id}]`"
|
|
:type="itemParameters.columns[columnIndex].type"
|
|
v-model="item[column.id as keyof typeof item]"
|
|
:placeholder="itemParameters.columns[columnIndex].placeholder"
|
|
:required="itemParameters.columns[columnIndex].required"
|
|
>
|
|
</div>
|
|
<small class="text-danger m-0">
|
|
{{ getErrorMessage(itemIndex, column.id) }}
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else>
|
|
<p>{{ trans.methods.__("Aucun élément renseigné(s).") }}</p>
|
|
</div>
|
|
<div
|
|
v-if="buttonsDisplayParameters.add"
|
|
class="text-center mt-1"
|
|
>
|
|
<button
|
|
@click.prevent="addLine"
|
|
class="btn btn-sm btn-primary"
|
|
type="button"
|
|
:title="trans.methods.__('Ajouter une ligne')"
|
|
data-bs-toggle="tooltip"
|
|
>
|
|
<i class="fa-solid fa-plus" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { computed, defineOptions, onMounted, reactive, ref, useAttrs } from "vue";
|
|
import parseLaravelErrorMessages from "./../../modules/parseLaravelErrorMessages";
|
|
import trans from "./../../modules/trans";
|
|
import { Tooltips } from "./../../modules/bsTooltips";
|
|
import CkEditorComponent from "./CkEditorComponent.vue";
|
|
import ImageInputComponent from "./ImageInputComponent.vue";
|
|
import WordCounter from "./WordCounterComponent.vue";
|
|
|
|
defineOptions({
|
|
name: "SliderComponent"
|
|
});
|
|
|
|
// * ATTRIBUTES
|
|
const attrs = useAttrs();
|
|
|
|
// * REFS
|
|
const slider = ref<HTMLDivElement|null>(null);
|
|
|
|
// * DATA
|
|
const tooltips = ref<Tooltips | null>(null);
|
|
const allErrors = ref<LaravelValidationErrors>({});
|
|
|
|
interface Column {
|
|
id: string;
|
|
type: "picture" | "text" | "wysiwyg";
|
|
placeholder: string;
|
|
validation: string;
|
|
required: boolean;
|
|
}
|
|
|
|
/** Input parameters. */
|
|
const inputParameters = reactive<{
|
|
id: string,
|
|
name: string,
|
|
}>({
|
|
id: "string",
|
|
name: "",
|
|
});
|
|
|
|
/** Item parameters. */
|
|
const itemParameters = reactive<{
|
|
list: Array<Object>,
|
|
columns: Array<Column>,
|
|
limits: Array<number>,
|
|
wysiwygConfig: string,
|
|
imageSizes: Array<number>,
|
|
}>({
|
|
list: [{}],
|
|
columns: [],
|
|
limits: [0, 0],
|
|
wysiwygConfig: "",
|
|
imageSizes: [500, 500],
|
|
});
|
|
|
|
/** Buttons parameters. */
|
|
const buttonsDisplayParameters = reactive<{
|
|
add: boolean,
|
|
remove: boolean,
|
|
}>({
|
|
add: true,
|
|
remove: true,
|
|
});
|
|
|
|
// * COMPUTED
|
|
const isUsedWithProps = computed<boolean>(() => attrs.json === undefined);
|
|
|
|
// * LIFECYCLE
|
|
onMounted(() => {
|
|
const json = String(attrs.json ?? "{}"),
|
|
data = JSON.parse(json);
|
|
if (!isUsedWithProps.value) {
|
|
/** Input parameters. */
|
|
inputParameters.name = data.inputName;
|
|
/** Item parameters. */
|
|
itemParameters.list = Array.isArray(data.itemList) ? data.itemList : [];
|
|
itemParameters.columns = data.columns;
|
|
itemParameters.limits = data.itemLimit;
|
|
itemParameters.wysiwygConfig = data.wysiwygConfig;
|
|
itemParameters.imageSizes = data.imageSizes;
|
|
/** Global parameters */
|
|
allErrors.value = data.errors;
|
|
}
|
|
setDefaultLines();
|
|
checkLengthList();
|
|
initTooltips();
|
|
});
|
|
|
|
// * METHODS
|
|
|
|
/**
|
|
* Set default line(s)
|
|
* according to the minimum limit defined.
|
|
*/
|
|
function setDefaultLines(): void {
|
|
while (itemParameters.list.length < itemParameters.limits[0]) {
|
|
addLine();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add a new line to the <table>,
|
|
* add a new element to the array,
|
|
* show remove line button.
|
|
*/
|
|
function addLine(): void {
|
|
itemParameters.list.push({});
|
|
if (buttonsDisplayParameters.remove == false) {
|
|
buttonsDisplayParameters.remove = true;
|
|
}
|
|
checkLengthList();
|
|
tooltips.value?.closeBootstrapTooltip();
|
|
initTooltips();
|
|
}
|
|
|
|
/**
|
|
* Remove a specific line from the <table>,
|
|
* remove a specific element to the array,
|
|
* show adding line button.
|
|
*/
|
|
function removeLine(itemIndex: number): void {
|
|
itemParameters.list.splice(itemIndex, 1);
|
|
if (buttonsDisplayParameters.add == false) {
|
|
buttonsDisplayParameters.add = true;
|
|
}
|
|
checkLengthList();
|
|
tooltips.value?.closeBootstrapTooltip();
|
|
initTooltips();
|
|
}
|
|
|
|
/**
|
|
* Check the length of the list,
|
|
* update variables accordingly.
|
|
*/
|
|
function checkLengthList(): void {
|
|
/** Length minimum */
|
|
if (itemParameters.list.length <= itemParameters.limits[0]) {
|
|
buttonsDisplayParameters.remove = false;
|
|
}
|
|
/** Length maximum */
|
|
if (itemParameters.list.length >= itemParameters.limits[1]) {
|
|
buttonsDisplayParameters.add = false;
|
|
}
|
|
}
|
|
|
|
/** Return error message or null. */
|
|
function getErrorMessage(itemIndex: number, column: string): string|null {
|
|
return parseLaravelErrorMessages.methods.parseValidationInput(
|
|
`${inputParameters.name}.${String(itemIndex)}.${column}`,
|
|
allErrors.value
|
|
);
|
|
}
|
|
|
|
/** Initialise all tooltips in the component. */
|
|
function initTooltips(): void {
|
|
setTimeout(() => {
|
|
tooltips.value = Tooltips.make({
|
|
type: "dom",
|
|
elements: slider.value!.querySelectorAll("[data-bs-toggle=\"tooltip\"]")
|
|
});
|
|
}, 500);
|
|
}
|
|
</script>
|