cyca/resources/js/components/Highlights.vue
Richard Dern 400e3d01f1 Refresh
2022-01-12 00:35:37 +01:00

286 lines
11 KiB
Vue
Executable File

<template>
<div class="flex w-full h-screen">
<div class="w-1/2 h-screen flex flex-col">
<div class="h-2/3 overflow-auto">
<draggable
class="list vertical striped spaced items-rounded"
v-model="sortedHighlights"
group="myHighlights"
@start="drag = true"
@end="drag = false"
item-key="id"
v-bind:force-fallback="true"
v-bind:fallback-tolerance="10"
handle=".handle"
>
<template #item="{ element }">
<div
class="list-item select-none"
v-bind:class="{
selected:
selectedHighlight &&
selectedHighlight.id === element.id,
}"
>
<div class="handle">
<svg fill="currentColor" width="16" height="16">
<use v-bind:xlink:href="icon('move-v')" />
</svg>
</div>
<div class="icons">
<div
class="badge font-mono"
v-html="highlightText(element.color)"
></div>
</div>
<div class="list-item-text">
{{ element.expression }}
</div>
<div class="tools">
<button
class="info"
v-on:click="selectedHighlight = element"
>
<svg
fill="currentColor"
width="16"
height="16"
>
<use
v-bind:xlink:href="icon('update')"
/>
</svg>
<span>{{ __("Edit") }}</span>
</button>
</div>
</div>
</template>
</draggable>
</div>
<div class="h-1/3">
<article>
<header>
<h1>
{{
selectedHighlight
? selectedHighlight.expression
: __("Create highlight")
}}
</h1>
</header>
<div class="body">
<div class="flex items-center">
<div class="flex-none mr-2">
<div class="form-group">
<label for="color">{{ __("Color") }}</label>
<input
type="color"
id="color"
v-model="newColor"
/>
</div>
</div>
<div class="flex-grow">
<div class="form-group">
<label for="expression">{{
__("Expression")
}}</label>
<input
type="text"
id="expression"
v-model="newExpression"
/>
</div>
</div>
</div>
<div class="flex justify-between">
<button
type="submit"
class="success"
v-on:click="saveHighlight"
>
<svg fill="currentColor" width="16" height="16">
<use
v-bind:xlink:href="
icon(
!selectedHighlight
? 'add'
: 'update'
)
"
/>
</svg>
<span>
{{ __("Save") }}
</span>
</button>
<div class="flex items-center space-x-1">
<button
class="secondary"
v-on:click="resetForm"
>
<svg
fill="currentColor"
width="16"
height="16"
>
<use
v-bind:xlink:href="icon('cancel')"
/>
</svg>
<span>
{{ __("Cancel") }}
</span>
</button>
<button
class="danger"
v-on:click="onDestroy"
v-if="selectedHighlight"
>
<svg
fill="currentColor"
width="16"
height="16"
>
<use
v-bind:xlink:href="icon('trash')"
/>
</svg>
<span>
{{ __("Delete") }}
</span>
</button>
</div>
</div>
</div>
</article>
</div>
</div>
<div class="w-1/2 bg-gray-50 dark:bg-gray-850"></div>
</div>
</template>
<script>
import draggable from "vuedraggable";
import TEXTColor from "textcolor";
export default {
components: { draggable },
data: function () {
return {
positions: [],
highlights: highlights,
newExpression: null,
newColor: "#000000",
selectedHighlight: null,
};
},
computed: {
sortedHighlights: {
get() {
return collect(this.highlights).sortBy("position").all();
},
set(value) {
const self = this;
const collection = collect(value);
let positions = {};
collection.each(function (highlight, index) {
positions[highlight.id] = index;
});
self.updatePositions({ positions: positions });
},
},
},
watch: {
selectedHighlight: function (highlight) {
const self = this;
if (highlight) {
self.newExpression = highlight.expression;
self.newColor = highlight.color;
} else {
self.resetForm();
}
},
},
methods: {
resetForm: function () {
const self = this;
self.selectedHighlight = null;
self.newExpression = null;
self.newColor = "#000000";
},
saveHighlight: function () {
const self = this;
if (!self.newExpression) {
return;
}
if (self.selectedHighlight) {
api.put(route("highlight.update", self.selectedHighlight), {
expression: self.newExpression,
color: self.newColor,
}).then(function (response) {
self.highlights = response;
self.resetForm();
});
} else {
api.post(route("highlight.store"), {
expression: self.newExpression,
color: self.newColor,
}).then(function (response) {
self.highlights = response;
self.resetForm();
});
}
},
onDestroy: function () {
const self = this;
api.delete(route("highlight.destroy", self.selectedHighlight)).then(
function (response) {
self.highlights = response;
self.selectedHighlight = null;
}
);
},
updatePositions: function ({ positions }) {
const self = this;
for (var id in positions) {
const highlight = self.highlights.find((h) => h.id == id);
if (!highlight) {
console.warn("Highlight #" + id + " not found");
return;
}
highlight.position = positions[id];
}
api.post(route("highlight.update_positions"), {
positions: positions,
});
},
highlightText: function (color) {
let textColor = TEXTColor.findTextColor(color);
color =
'<span class="highlight" style="color: ' +
textColor +
"; background-color: " +
color +
'">' +
color +
"</span>";
return color;
},
},
};
</script>