Initial import
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
},
|
||||
|
||||
mounted() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+90
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div :draggable="draggable" :class="dropclass" @dragover="drag_over" @dragstart="drag_start" @drop="drop" @dragenter="drag_enter" @dragleave="drag_leave">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
"draggable",
|
||||
"droppable",
|
||||
"object_id",
|
||||
"object_type",
|
||||
"callback",
|
||||
"extra_data",
|
||||
],
|
||||
|
||||
setup(props, context) {
|
||||
return {
|
||||
dropclass: ref(""),
|
||||
content: ref(""),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
},
|
||||
|
||||
drag_over(e) {
|
||||
e.preventDefault();
|
||||
},
|
||||
|
||||
drag_start(e) {
|
||||
if (this.draggable == "true") {
|
||||
e.dataTransfer.setData("object_id", this.object_id);
|
||||
e.dataTransfer.setData("object_type", this.object_type);
|
||||
e.dataTransfer.setData("extra_data", this.extra_data);
|
||||
}
|
||||
},
|
||||
|
||||
drop(e) {
|
||||
if (this.droppable == "true") {
|
||||
this.dropclass = "";
|
||||
e.preventDefault();
|
||||
console.log(e.dataTransfer.getData("object_id"));
|
||||
console.log(e.dataTransfer.getData("object_type"));
|
||||
console.log(e.dataTransfer.getData("extra_data"));
|
||||
console.log(this);
|
||||
|
||||
$.ajax({
|
||||
url: this.callback,
|
||||
method: 'POST',
|
||||
data: {
|
||||
dst_id: this.object_id,
|
||||
dst_type: this.object_type,
|
||||
dst_extra: this.extra_data,
|
||||
src_id: e.dataTransfer.getData("object_id"),
|
||||
src_type: e.dataTransfer.getData("object_type"),
|
||||
src_extra: e.dataTransfer.getData("extra_data"),
|
||||
copy: e.ctrlKey,
|
||||
}
|
||||
}).done(this.drop_complete);
|
||||
}
|
||||
},
|
||||
|
||||
drop_complete(data) {
|
||||
//console.log(data);
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
drag_enter(e) {
|
||||
if (this.droppable == "true") {
|
||||
this.dropclass = "bg-warning-subtle";
|
||||
}
|
||||
},
|
||||
|
||||
drag_leave(e) {
|
||||
if (this.droppable == "true") {
|
||||
this.dropclass = "";
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+195
@@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-primary" @click="edit" title="Edit Document"><i class='fa fa-pencil'></i></button>
|
||||
|
||||
<div id="docedit" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Edit Document</h5>
|
||||
<button @click="close" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div v-if="loading" class="text-center">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-12">
|
||||
<label for="internal_id">Order Number</label>
|
||||
<div class="input-group">
|
||||
<input @keyup.enter="save" @keyup.esc="close" @keyup="id_caps" type="text" class="form-control" name="internal_id" v-model="internal_id">
|
||||
<button @click="guess_docid" class="btn btn-secondary" title="Guess document ID"><i class="fa fa-wand-magic-sparkles"></i></button>
|
||||
</div>
|
||||
<label for="title">Title</label>
|
||||
<div class="input-group">
|
||||
<input ref="rtitle" @keyup.enter="save" @keyup.esc="close" type="text" class="form-control" name="title" v-model="title">
|
||||
<button @click="split_title" class="btn btn-secondary" title="Split down on cursor or selection"><i class="fa fa-i-cursor"></i></button>
|
||||
</div>
|
||||
<label for="subtitle">Subtitle</label>
|
||||
<div class="input-group">
|
||||
<input ref="rsubtitle" @keyup.enter="save" @keyup.esc="close" type="text" class="form-control" name="subtitle" v-model="subtitle">
|
||||
<button @click="split_subtitle" class="btn btn-secondary" title="Split down on cursor or selection"><i class="fa fa-i-cursor"></i></button>
|
||||
</div>
|
||||
<label for="subsubtitle">Sub-subtitle</label>
|
||||
<input @keyup.enter="save" @keyup.esc="close" type="text" class="form-control" name="subsubtitle" v-model="subsubtitle">
|
||||
</div>
|
||||
<div class="col-lg-6 col-12">
|
||||
<label for="overview">Overview <small>(Markdown supported)</small></label>
|
||||
<textarea @keyup.esc="close" name="overview" v-model="overview" class="form-control w-100" rows="5"></textarea>
|
||||
<label for="products">Products</label>
|
||||
<productselector v-model="products"></productselector>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button @click="close" type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button @click="save" type="button" class="btn btn-primary">Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
return {
|
||||
loading: ref(true),
|
||||
internal_id: ref(""),
|
||||
title: ref(""),
|
||||
subtitle: ref(""),
|
||||
subsubtitle: ref(""),
|
||||
overview: ref(""),
|
||||
products: ref(""),
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
},
|
||||
|
||||
methods: {
|
||||
edit() {
|
||||
this.loading = true;
|
||||
$('#docedit').show();
|
||||
$.ajax({
|
||||
url: "/api/document/" + this.docid,
|
||||
method: "GET"
|
||||
}).done(this.get_products);
|
||||
},
|
||||
|
||||
get_products(data) {
|
||||
this.internal_id = data.internal_id;
|
||||
this.title = data.title;
|
||||
this.subtitle = data.subtitle;
|
||||
this.subsubtitle = data.subsubtitle;
|
||||
this.overview = data.overview;
|
||||
$.ajax({
|
||||
url: "/api/document/" + this.docid + "/products",
|
||||
method: "GET"
|
||||
}).done(this.fill_products);
|
||||
},
|
||||
|
||||
fill_products(data) {
|
||||
this.products = "";
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (this.products != "") {
|
||||
this.products += ",";
|
||||
}
|
||||
this.products += data[i].id;
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
close() {
|
||||
$('#docedit').hide();
|
||||
},
|
||||
|
||||
save() {
|
||||
$.ajax({
|
||||
url: "/api/document/" + this.docid,
|
||||
method: "POST",
|
||||
data: {
|
||||
internal_id: this.internal_id,
|
||||
title: this.title,
|
||||
subtitle: this.subtitle,
|
||||
subsubtitle: this.subsubtitle,
|
||||
overview: this.overview,
|
||||
products: this.products,
|
||||
}
|
||||
}).done(this.refresh);
|
||||
},
|
||||
|
||||
refresh() {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
id_caps() {
|
||||
this.internal_id = this.internal_id.toUpperCase();
|
||||
this.internal_id = this.internal_id.replace("–", "-");
|
||||
},
|
||||
|
||||
get_caret_position(oField) {
|
||||
// Initialize
|
||||
var iCaretPos = 0;
|
||||
|
||||
if (document.selection) {
|
||||
|
||||
// Set focus on the element
|
||||
oField.focus();
|
||||
|
||||
// To get cursor position, get empty selection range
|
||||
var oSel = document.selection.createRange();
|
||||
|
||||
// Move selection start to 0 position
|
||||
oSel.moveStart('character', -oField.value.length);
|
||||
|
||||
// The caret position is selection length
|
||||
iCaretPos = oSel.text.length;
|
||||
} else if (oField.selectionStart || oField.selectionStart == '0') {
|
||||
iCaretPos = oField.selectionDirection=='backward' ? oField.selectionStart : oField.selectionEnd;
|
||||
}
|
||||
return iCaretPos;
|
||||
},
|
||||
|
||||
split_title() {
|
||||
var pos = this.get_caret_position(this.$refs.rtitle);
|
||||
var l = this.title.substring(0, pos);
|
||||
var r = this.title.substring(pos);
|
||||
this.title = l;
|
||||
this.subtitle = r;
|
||||
console.log(pos);
|
||||
},
|
||||
|
||||
split_subtitle() {
|
||||
var pos = this.get_caret_position(this.$refs.rsubtitle);
|
||||
var l = this.subtitle.substring(0, pos);
|
||||
var r = this.subtitle.substring(pos);
|
||||
this.subtitle = l;
|
||||
this.subsubtitle = r;
|
||||
console.log(pos);
|
||||
},
|
||||
|
||||
guess_docid() {
|
||||
$.ajax({
|
||||
url: "/api/docid/" + this.docid,
|
||||
method: "GET"
|
||||
}).done(this.guessed_docid);
|
||||
},
|
||||
|
||||
guessed_docid(d) {
|
||||
this.internal_id = d.docid;
|
||||
},
|
||||
},
|
||||
|
||||
props: [
|
||||
"docid",
|
||||
],
|
||||
}
|
||||
</script>
|
||||
Executable
+127
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="progress {{pstyle}}" role="progressbar" aria-label="Download progress" style="--bs-progress-bar-transition: 0.01s;">
|
||||
<div ref="pg" :class="pbstyle" :style="{'width': percent + '%'}">{{status}}</div>
|
||||
</div>
|
||||
<div class="text-truncate">
|
||||
<small>{{srcurl}}</small>
|
||||
</div>
|
||||
<div v-if="failed" class="alert alert-danger">
|
||||
The download has failed with error code <strong>{{errorcode}}</strong>. Please try again.
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler'
|
||||
|
||||
export default {
|
||||
emits: [
|
||||
'complete',
|
||||
'failure'
|
||||
],
|
||||
props: [
|
||||
'jobid',
|
||||
'url'
|
||||
],
|
||||
setup() {
|
||||
return {
|
||||
percent: ref(100),
|
||||
pbstyle: ref(""),
|
||||
pstyle: ref(""),
|
||||
outfile: ref(""),
|
||||
srcurl: ref(""),
|
||||
failed: ref(false),
|
||||
errorcode: ref(""),
|
||||
status: ref(""),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
get_status() {
|
||||
$.ajax({
|
||||
url: "/api/download/" + this.jobid,
|
||||
method: "get",
|
||||
}) .fail(this.get_status_fail)
|
||||
.done(this.got_status);
|
||||
},
|
||||
get_status_fail(data, status, xhr) {
|
||||
this.errorcode = xhr;
|
||||
this.failed = true;
|
||||
},
|
||||
|
||||
got_status(data, status, xhr) {
|
||||
this.update_bar(data);
|
||||
if (data.done != data.size) {
|
||||
setTimeout(this.get_status, 500);
|
||||
} else {
|
||||
if (data.size == 0) {
|
||||
setTimeout(this.get_status, 2000);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
submit(url) {
|
||||
$.ajax({
|
||||
url: "/api/download",
|
||||
method: "put",
|
||||
data: {
|
||||
url: this.url
|
||||
}
|
||||
}) .fail(this.submit_fail)
|
||||
.done(this.submitted);
|
||||
},
|
||||
|
||||
submit_fail(data, status, xhr) {
|
||||
this.errorcode = xhr;
|
||||
this.failed = true;
|
||||
this.$emit("failed");
|
||||
},
|
||||
|
||||
submitted(data, status, xhr) {
|
||||
this.update_bar(data);
|
||||
setTimeout(this.get_status, 500);
|
||||
},
|
||||
|
||||
update_bar(data) {
|
||||
this.outfile = data.file;
|
||||
this.srcurl = data.url;
|
||||
|
||||
if (data.started == 0) {
|
||||
this.status = "Queued";
|
||||
this.pbstyle = "progress-bar bg-secondary progress-bar-striped progress-bar-animated";
|
||||
this.percent = 100;
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.finished != 0) {
|
||||
this.status = "Completed";
|
||||
this.pbstyle = "progress-bar bg-success";
|
||||
this.percent = 100;
|
||||
this.$emit("complete");
|
||||
let event = new CustomEvent("complete", { bubbles: true, detail: data });
|
||||
document.dispatchEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.size == 0) {
|
||||
this.status = "Starting...";
|
||||
} else {
|
||||
this.percent = data.done / data.size * 100;
|
||||
this.pbstyle = "progress-bar bg-primary";
|
||||
this.status = Math.round(this.percent) + "%";
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.status = "Please wait...";
|
||||
this.pbstyle = "progress-bar bg-secondary progress-bar-striped progress-bar-animated";
|
||||
this.percent = 100;
|
||||
|
||||
if (this.jobid != "") {
|
||||
this.get_status();
|
||||
} else if (this.url != "") {
|
||||
this.submit(url);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Download PDF URL:</span>
|
||||
<input type="text" class="form-control" v-model="url">
|
||||
<button class="btn btn-primary" @click="add_download">Download</button>
|
||||
</div>
|
||||
|
||||
<ul v-for="download in downloads" class="list-group">
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-12 text-truncate">
|
||||
{{ download.url }}
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<download :jobid="download.id"></download>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
downloads: ref([]),
|
||||
busy: ref(false),
|
||||
url: ref(""),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
update() {
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: "/api/downloads",
|
||||
method: "GET"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
add_download() {
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: "/api/downloads",
|
||||
method: "PUT",
|
||||
data: {
|
||||
url: this.url
|
||||
}
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
got_update(data) {
|
||||
this.downloads = data;
|
||||
this.busy = false;
|
||||
|
||||
setTimeout(this.update, 10000);
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+249
@@ -0,0 +1,249 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Test String:</span>
|
||||
<input @keyup="refresh" class="form-control" type="text" v-model="teststring">
|
||||
<span class="input-group-text"><i class="fa fa-arrow-left mx-1"></i> Type here to test matches</span>
|
||||
<button class="btn btn-success" @click="addnew">Add New Match</button>
|
||||
</div>
|
||||
<table class="table table-hover w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Weight</th>
|
||||
<th>Regular Expression</th>
|
||||
<th>Example</th>
|
||||
<th>Test Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="match in matches" :class="matchtest(match.regex)" @click="edit_reg(match)">
|
||||
<td>{{ match.weight }}</td>
|
||||
<td>/^{{ match.regex }}$/</td>
|
||||
<td>{{ match.example }}</td>
|
||||
<td>{{ teststring != "" ? matchresult(match.regex, teststring) : matchresult(match.regex, match.example)}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<div id="newreg" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Add New ID Match</h5>
|
||||
<button @click="addclose" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" :disabled="saving"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<label for="example">Example ID</label>
|
||||
<input type="text" name="example" class="form-control" v-model="add_example" @keyup="do_add_test">
|
||||
|
||||
<label for="regex">Regular Expression</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">/^</span>
|
||||
<input type="text" name="regex" class="form-control" v-model="add_regex" @keyup="do_add_test">
|
||||
<span class="input-group-text">$/</span>
|
||||
</div>
|
||||
|
||||
<label for="weight">Weight (lower is higher priority)</label>
|
||||
<input type="text" name="weight" class="form-control" v-model="add_weight">
|
||||
|
||||
Test Result: {{ add_test }}
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button @click="addclose" type="button" class="btn btn-secondary" data-bs-dismiss="modal" :disabled="saving">Close</button>
|
||||
<button @click="addsave" type="button" class="btn btn-primary" :disabled="saving">
|
||||
<span v-if="!saving">Save changes</span>
|
||||
<span class="spinner-border spinner-border-sm" role="status" v-if="saving"></span>
|
||||
<span v-if="saving" class="mx-1">Saving...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="editreg" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Edit ID Match</h5>
|
||||
<button @click="edit_close" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" :disabled="saving"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<label for="example">Example ID</label>
|
||||
<input type="text" name="example" class="form-control" v-model="edit_example" @keyup="do_edit_test">
|
||||
|
||||
<label for="regex">Regular Expression</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">/^</span>
|
||||
<input type="text" name="regex" class="form-control" v-model="edit_regex" @keyup="do_edit_test">
|
||||
<span class="input-group-text">$/</span>
|
||||
</div>
|
||||
|
||||
<label for="weight">Weight (lower is higher priority)</label>
|
||||
<input type="text" name="weight" class="form-control" v-model="edit_weight">
|
||||
|
||||
Test Result: {{ edit_test }}
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button @click="edit_delete" type="button" class="btn btn-danger" :disabled="saving">Delete</button>
|
||||
<button @click="edit_close" type="button" class="btn btn-secondary" data-bs-dismiss="modal" :disabled="saving">Close</button>
|
||||
<button @click="edit_save" type="button" class="btn btn-primary" :disabled="saving">
|
||||
<span v-if="!saving">Save changes</span>
|
||||
<span class="spinner-border spinner-border-sm" role="status" v-if="saving"></span>
|
||||
<span v-if="saving" class="mx-1">Saving...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
matches: ref([]),
|
||||
teststring: ref(""),
|
||||
saving: ref(false),
|
||||
add_example: ref(""),
|
||||
add_regex: ref(""),
|
||||
add_weight: ref(0),
|
||||
add_test: ref(""),
|
||||
edit_example: ref(""),
|
||||
edit_regex: ref(""),
|
||||
edit_weight: ref(0),
|
||||
edit_test: ref(""),
|
||||
edit_id: ref(0),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
refresh() {
|
||||
var m = this.matches;
|
||||
this.matches = [];
|
||||
this.matches = m;
|
||||
},
|
||||
|
||||
update() {
|
||||
$.ajax({
|
||||
url: "/api/sys/idmatch",
|
||||
method: "GET"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
got_update(data) {
|
||||
this.matches = data;
|
||||
},
|
||||
|
||||
matchresult(regex, example) {
|
||||
try {
|
||||
const re = new RegExp("^" + regex + "$");
|
||||
var res = example.match(re);
|
||||
if (res == null) {
|
||||
return "FAILED";
|
||||
}
|
||||
return res[1];
|
||||
} catch (E) {
|
||||
return "Bad Syntax";
|
||||
}
|
||||
},
|
||||
|
||||
matchtest(regex) {
|
||||
var teststring = this.teststring.trim();
|
||||
if (teststring == "") return "";
|
||||
if (this.matchresult(regex, teststring) != "FAILED") {
|
||||
return "table-success";
|
||||
}
|
||||
return "table-danger";
|
||||
},
|
||||
|
||||
addnew() {
|
||||
this.add_example = "";
|
||||
this.add_regex = "";
|
||||
this.add_weight = 0;
|
||||
$('#newreg').show();
|
||||
},
|
||||
|
||||
|
||||
do_add_test() {
|
||||
this.add_test = this.matchresult(this.add_regex, this.add_example);
|
||||
},
|
||||
|
||||
addclose() {
|
||||
$('#newreg').hide();
|
||||
},
|
||||
|
||||
addsave() {
|
||||
$.ajax({
|
||||
url: "/api/sys/idmatch",
|
||||
method: "PUT",
|
||||
data: {
|
||||
example: this.add_example,
|
||||
regex: this.add_regex,
|
||||
weight: this.add_weight
|
||||
}
|
||||
}).done(this.got_update);
|
||||
$('#newreg').hide();
|
||||
},
|
||||
|
||||
|
||||
edit_reg(m) {
|
||||
this.edit_id = m.id;
|
||||
this.edit_example = m.example;
|
||||
this.edit_regex = m.regex;
|
||||
this.edit_weight = m.weight;
|
||||
$('#editreg').show();
|
||||
},
|
||||
|
||||
edit_close() {
|
||||
$('#editreg').hide();
|
||||
},
|
||||
|
||||
do_edit_test() {
|
||||
this.edit_test = this.matchresult(this.edit_regex, this.edit_example);
|
||||
},
|
||||
|
||||
edit_save() {
|
||||
$.ajax({
|
||||
url: "/api/sys/idmatch/" + this.edit_id,
|
||||
method: "POST",
|
||||
data: {
|
||||
example: this.edit_example,
|
||||
regex: this.edit_regex,
|
||||
weight: this.edit_weight
|
||||
}
|
||||
}).done(this.got_update);
|
||||
$('#editreg').hide();
|
||||
},
|
||||
|
||||
edit_delete() {
|
||||
$.ajax({
|
||||
url: "/api/sys/idmatch/" + this.edit_id,
|
||||
method: "DELETE",
|
||||
}).done(this.got_update);
|
||||
$('#editreg').hide();
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+550
@@ -0,0 +1,550 @@
|
||||
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<ul class="list-group">
|
||||
<li v-for="i in imports" :class="fancyrow(i)">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-1">
|
||||
<a v-if="i.revision != null" :href='"/cover/" + i.revision.id + "/cover.jpg"'><img class="w-100" :src='"/cover/" + i.revision.id + "/100/cover.jpg"'></a>
|
||||
</div>
|
||||
<div class="col-11">
|
||||
<div class="row">
|
||||
<div class="col-lg-2 col-6">
|
||||
<strong v-if="i.imported > 0">Imported</strong>
|
||||
<strong v-else-if="i.completed > 0 && i.revision">Completed</strong>
|
||||
<strong v-else-if="i.completed > 0 && (!i.revision)">Failed</strong>
|
||||
<strong v-else-if="i.started > 0">Processing</strong>
|
||||
<strong v-else>Queued</strong>
|
||||
</div>
|
||||
<div class="col-lg-2 col-6">
|
||||
<a v-if="i.revision != null" :href='"/revision/" + i.revision.id'>{{ i.revision.id }}</a>
|
||||
</div>
|
||||
<div class="col-lg-2 col-3">
|
||||
{{ i.guessed_id }}
|
||||
</div>
|
||||
<div class="col-lg-2 col-3">
|
||||
{{ i.guessed_revno }}
|
||||
</div>
|
||||
<div class="col-lg-2 col-6">
|
||||
{{ i.guessed_month }}/{{ i.guessed_year }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-9 text-truncate">
|
||||
{{ i.guessed_title }}
|
||||
</div>
|
||||
<div class="col-lg-3 col-12 btn-group">
|
||||
<button :disabled="busy" class="btn btn-danger" @click="del(i)"><i class="fa-solid fa-trash"></i></button>
|
||||
<button :disabled="busy || (i.revision == null)" class="btn btn-secondary" @click="download(i)"><i class="fa-solid fa-download"></i></button>
|
||||
<button :disabled="(i.started == 0) || busy" class="btn btn-primary" @click="restart(i)"><i class="fa-solid fa-rotate"></i></button>
|
||||
<button class="btn btn-success" :disabled="(i.completed == 0 || (!i.revision)) || busy" @click="import_rev(i)"><i class="fa-solid fa-file-import"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{{ i.origfile }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div id="docedit" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Create Document</h5>
|
||||
<button @click="close" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" :disabled="saving"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-12 alert alert-info">
|
||||
{{ i_origfile }}
|
||||
</div>
|
||||
</div>
|
||||
<pdf :rev="i_revision"></pdf>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-12">
|
||||
<label for="i_id">Order Number</label>
|
||||
<div class="input-group">
|
||||
<input @blur="upper_id" @keyup.enter="save" ref="orderno" @keyup.esc="close" type="text" @keyup="find_doc" :class="'form-control' + ((i_id.length <= 25) ? ' is-valid' : ' is-invalid')" name="i_id" v-model="i_id" :disabled="saving">
|
||||
<button class="btn btn-secondary" @click="paste_id"><i class="fa-solid fa-paste"></i></button>
|
||||
</div>
|
||||
|
||||
<div v-if="newdoc" class="alert alert-warning">
|
||||
A new document will be created with this order number.
|
||||
</div>
|
||||
|
||||
<div v-else class="alert alert-success">
|
||||
This PDF will be added to {{ existing_doc.title }} {{ existing_doc.subtitle }} {{ existing_doc.subsubtitle }} as a new revision.
|
||||
</div>
|
||||
|
||||
<div v-if="newdoc">
|
||||
<label for="i_title">Title</label>
|
||||
<div class="input-group">
|
||||
<input ref="rtitle" @keyup.enter="save" @keyup.esc="close" @keyup="try_title" type="text" :class="'form-control' + (i_title == '' ? ' is-invalid' : ' is-valid')" name="i_title" v-model="i_title" :disabled="saving">
|
||||
<button class="btn btn-secondary" @click="split_title" title="Split down on cursor position"><i class='fa fa-i-cursor'></i></button>
|
||||
</div>
|
||||
<label for="i_subtitle">Subtitle</label>
|
||||
<div class="input-group">
|
||||
<input ref="rsubtitle" @keyup.enter="save" @keyup.esc="close" @keyup="try_subtitle" type="text" class="form-control" name="i_subtitle" v-model="i_subtitle" :disabled="saving">
|
||||
<button class="btn btn-secondary" @click="split_subtitle" title="Split down on cursor position"><i class='fa fa-i-cursor'></i></button>
|
||||
</div>
|
||||
<label for="i_subsubtitle">Sub-subtitle</label>
|
||||
<input @keyup.enter="save" @keyup.esc="close" @keyup="try_subsubtitle" type="text" class="form-control" name="i_subsubtitle" v-model="i_subsubtitle" :disabled="saving">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-lg-6 col-12">
|
||||
|
||||
<label for="i_revno">Revision / Version Number</label>
|
||||
<input @keyup.enter="save" @keyup.esc="close" type="text" class="form-control" name="i_revno" v-model="i_revno" :disabled="saving">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label for="i_month">Month</label>
|
||||
<input @keyup.enter="save" @keyup.esc="close" type="text" class="form-control" name="i_month" v-model="i_month" :disabled="saving">
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label for="i_year">Year</label>
|
||||
<input @keyup.enter="save" @keyup.esc="close" type="text" class="form-control" name="i_year" v-model="i_year" :disabled="saving">
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="newdoc">
|
||||
<label for="i_overview">Overview <small>(Markdown supported)</small></label>
|
||||
<textarea @keyup.esc="close" name="i_overview" v-model="i_overview" class="form-control w-100" rows="5" :disabled="saving"></textarea>
|
||||
<label for="i_products">Products</label>
|
||||
<productselector id="ps" v-model="i_products"></productselector>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<textarea editable="false" v-model="i_covertext" class="form-control"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button @click="close" type="button" class="btn btn-secondary" data-bs-dismiss="modal" :disabled="saving">Close</button>
|
||||
<button @click="save" type="button" class="btn btn-primary" :disabled="saving || (newdoc && ((i_products == '') || (i_title == '')))">
|
||||
<span v-if="!saving">Save changes</span>
|
||||
<span class="spinner-border spinner-border-sm" role="status" v-if="saving"></span>
|
||||
<span v-if="saving" class="mx-1">Saving...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
imports: ref([]),
|
||||
busy: ref(false),
|
||||
i_products: ref(""),
|
||||
i_id: ref(""),
|
||||
i_title: ref(""),
|
||||
i_subtitle: ref(""),
|
||||
i_subsubtitle: ref(""),
|
||||
i_revno: ref(""),
|
||||
i_month: ref(0),
|
||||
i_year: ref(0),
|
||||
i_overview: ref(""),
|
||||
i_cover: ref(""),
|
||||
i_fullcover: ref(""),
|
||||
i_origfile: ref(""),
|
||||
i_covertext: ref(""),
|
||||
i_revision: ref(0),
|
||||
|
||||
triglock: ref(false),
|
||||
|
||||
saving: ref(false),
|
||||
|
||||
importing: ref({
|
||||
id: 0
|
||||
}),
|
||||
|
||||
newdoc: ref(true),
|
||||
existing_doc: ref({
|
||||
title: '',
|
||||
subtitle: '',
|
||||
subsubtitle: '',
|
||||
}),
|
||||
timer: ref(null),
|
||||
zoom: ref(null),
|
||||
|
||||
fsel_start: ref(0),
|
||||
fsel_end: ref(0),
|
||||
fsel_el: ref(null),
|
||||
keytimer : ref(false),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.update();
|
||||
var that = this;
|
||||
},
|
||||
|
||||
focus() {
|
||||
this.$refs.rtitle.focus();
|
||||
this.zoom = new ImageZoom(document.getElementById("cover"), {
|
||||
fillContainer: true,
|
||||
offset: { vertical: 0, horizontal: 10 },
|
||||
zoomStyle: "z-index: 10;",
|
||||
});
|
||||
},
|
||||
|
||||
update() {
|
||||
this.timer = false;
|
||||
$.ajax({
|
||||
url: "/api/imports",
|
||||
method: "GET"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
got_update(data) {
|
||||
this.imports = data;
|
||||
this.busy = false;
|
||||
|
||||
var r = 0;
|
||||
|
||||
for (var i = 0; i < this.imports.length; i++) {
|
||||
if (this.imports[i].completed == 0) {
|
||||
r = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (r) {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
this.timer=null;
|
||||
}
|
||||
this.timer = setTimeout(this.update, 1000);
|
||||
}
|
||||
},
|
||||
|
||||
del(rev) {
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: "/api/import/" + rev.id,
|
||||
method: "DELETE"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
restart(rev) {
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: "/api/import/" + rev.id,
|
||||
method: "POST",
|
||||
data: {
|
||||
started: 0,
|
||||
completed: 0,
|
||||
imported: 0,
|
||||
}
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
import_rev(rev) {
|
||||
this.importing = rev;
|
||||
this.i_id = rev.guessed_id;
|
||||
this.i_title = rev.guessed_title;
|
||||
this.i_revno = rev.guessed_revno;
|
||||
this.i_subtitle = "";
|
||||
this.i_subsubtitle = "";
|
||||
this.i_month = rev.guessed_month;
|
||||
this.i_year = rev.guessed_year;
|
||||
this.i_overview = rev.overview;
|
||||
this.i_products = "";
|
||||
this.i_cover = "/cover/" + rev.revision.id + "/cover.jpg";
|
||||
this.i_fullcover = "/cover/" + rev.revision.id + "/cover.jpg";
|
||||
this.i_origfile = rev.origfile;
|
||||
this.i_covertext = rev.covertext;
|
||||
this.i_revision = rev.revision.id;
|
||||
this.find_doc();
|
||||
|
||||
$(document).on('hide.bs.modal', '#docedit', function(e) {alert("doc"); });
|
||||
$('#docedit').on('hide.bs.modal', function(e) {alert("modal"); });
|
||||
|
||||
$('#docedit').show();
|
||||
setTimeout(this.focus, 10);
|
||||
},
|
||||
|
||||
test(e) {
|
||||
console.log(e);
|
||||
},
|
||||
|
||||
close() {
|
||||
$('#docedit').hide();
|
||||
},
|
||||
|
||||
save() {
|
||||
|
||||
if (this.busy) return;
|
||||
if (this.saving) return;
|
||||
if (this.newdoc && (this.i_products == '')) return;
|
||||
if (this.newdoc && (this.i_title == '')) return;
|
||||
|
||||
this.busy = true;
|
||||
this.saving = true;
|
||||
$.ajax({
|
||||
url: "/api/import/" + this.importing.id ,
|
||||
method: "PUT",
|
||||
data: {
|
||||
internal_id: this.i_id,
|
||||
title: this.i_title,
|
||||
subtitle: this.i_subtitle,
|
||||
subsubtitle: this.i_subsubtitle,
|
||||
month: this.i_month,
|
||||
year: this.i_year,
|
||||
overview: this.i_overview,
|
||||
products: this.i_products,
|
||||
revno: this.i_revno,
|
||||
}
|
||||
}).done(this.saved);
|
||||
},
|
||||
|
||||
saved(data) {
|
||||
this.got_update(data);
|
||||
this.saving = false;
|
||||
$('#docedit').hide();
|
||||
delete this.zoom;
|
||||
},
|
||||
|
||||
find_doc() {
|
||||
|
||||
var i_id = this.i_id.toUpperCase();
|
||||
|
||||
$.ajax({
|
||||
url: "/api/documentbyid/" + i_id,
|
||||
method: "GET"
|
||||
}).done(this.got_doc);
|
||||
},
|
||||
|
||||
got_doc(data) {
|
||||
if (data == false) {
|
||||
this.newdoc = true;
|
||||
} else {
|
||||
this.newdoc = false;
|
||||
this.existing_doc = data;
|
||||
}
|
||||
},
|
||||
|
||||
fancyrow(i) {
|
||||
if (i.completed > 0) {
|
||||
if (!i.revision) {
|
||||
return "list-group-item list-group-item-danger";
|
||||
} else {
|
||||
return "list-group-item list-group-item-success";
|
||||
}
|
||||
}
|
||||
if (i.started > 0) return "list-group-item list-group-item-warning";
|
||||
if (i.queued > 0) return "list-group-item list-group-item-primary";
|
||||
return "list-group-item";
|
||||
},
|
||||
|
||||
get_caret_position(oField) {
|
||||
// Initialize
|
||||
var iCaretPos = 0;
|
||||
|
||||
if (document.selection) {
|
||||
|
||||
// Set focus on the element
|
||||
oField.focus();
|
||||
|
||||
// To get cursor position, get empty selection range
|
||||
var oSel = document.selection.createRange();
|
||||
|
||||
// Move selection start to 0 position
|
||||
oSel.moveStart('character', -oField.value.length);
|
||||
|
||||
// The caret position is selection length
|
||||
iCaretPos = oSel.text.length;
|
||||
} else if (oField.selectionStart || oField.selectionStart == '0') {
|
||||
iCaretPos = oField.selectionDirection=='backward' ? oField.selectionStart : oField.selectionEnd;
|
||||
}
|
||||
return iCaretPos;
|
||||
},
|
||||
|
||||
select_to_end(oField, from) {
|
||||
if (document.selection) {
|
||||
oField.focus();
|
||||
var oSel = document.selection.createRange();
|
||||
oSel.moveStart('character', from);
|
||||
oSel.moveEnd('character', oField.value.length);
|
||||
} else {
|
||||
oField.setSelectionRange(from, oField.value.length);
|
||||
}
|
||||
},
|
||||
|
||||
split_title() {
|
||||
var pos = this.get_caret_position(this.$refs.rtitle);
|
||||
var l = this.i_title.substring(0, pos);
|
||||
var r = this.i_title.substring(pos);
|
||||
this.i_title = l;
|
||||
this.i_subtitle = r;
|
||||
},
|
||||
|
||||
split_subtitle() {
|
||||
var pos = this.get_caret_position(this.$refs.rsubtitle);
|
||||
var l = this.i_subtitle.substring(0, pos);
|
||||
var r = this.i_subtitle.substring(pos);
|
||||
this.i_subtitle = l;
|
||||
this.i_subsubtitle = r;
|
||||
},
|
||||
|
||||
upper_id() {
|
||||
this.i_id = this.i_id.toUpperCase();
|
||||
},
|
||||
|
||||
paste_id() {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.readText().then(this.do_set_id);
|
||||
}
|
||||
},
|
||||
|
||||
do_set_id(data) {
|
||||
this.i_id = data;
|
||||
this.find_doc();
|
||||
},
|
||||
|
||||
download(data) {
|
||||
document.location="/pdf/" + data.revision.id + "/download/doc.pdf";
|
||||
},
|
||||
|
||||
try_title(e) {
|
||||
if (e.key == "Shift") return;
|
||||
if (e.key == "ArrowLeft") return;
|
||||
if (e.key == "ArrowRight") return;
|
||||
if (e.key == "ArrowUp") return;
|
||||
if (e.key == "ArrowDown") return;
|
||||
if (e.key == "Backspace") return;
|
||||
if (this.triglock) return;
|
||||
|
||||
if (this.keytimer) {
|
||||
clearTimeout(this.keytimer);
|
||||
}
|
||||
this.keytimer = setTimeout(this.try_title2, 250);
|
||||
},
|
||||
|
||||
try_title2() {
|
||||
this.keytimer = false
|
||||
$.ajax({
|
||||
url: "/api/search/prefix",
|
||||
method: "POST",
|
||||
data: {
|
||||
title: this.i_title
|
||||
}
|
||||
}).done(this.fill_title);
|
||||
},
|
||||
|
||||
fill_title(data, status) {
|
||||
if (status == "success") {
|
||||
this.triglock = true;
|
||||
this.fsel_start = this.get_caret_position(this.$refs.rtitle);
|
||||
this.fsel_el = this.$refs.rtitle;
|
||||
this.i_title = data;
|
||||
this.triglock = false;
|
||||
setTimeout(this.fsel, 10);
|
||||
}
|
||||
},
|
||||
|
||||
try_subtitle(e) {
|
||||
if (e.key == "Shift") return;
|
||||
if (e.key == "ArrowLeft") return;
|
||||
if (e.key == "ArrowRight") return;
|
||||
if (e.key == "ArrowUp") return;
|
||||
if (e.key == "ArrowDown") return;
|
||||
if (e.key == "Backspace") return;
|
||||
if (this.triglock) return;
|
||||
|
||||
if (this.keytimer) {
|
||||
clearTimeout(this.keytimer);
|
||||
}
|
||||
this.keytimer = setTimeout(this.try_subtitle2, 250);
|
||||
},
|
||||
|
||||
try_subtitle2() {
|
||||
this.keytimer = false
|
||||
$.ajax({
|
||||
url: "/api/search/prefix",
|
||||
method: "POST",
|
||||
data: {
|
||||
title: this.i_subtitle
|
||||
}
|
||||
}).done(this.fill_subtitle);
|
||||
},
|
||||
|
||||
fill_subtitle(data, status) {
|
||||
if (status == "success") {
|
||||
this.triglock = true;
|
||||
this.fsel_start = this.get_caret_position(this.$refs.rsubtitle);
|
||||
this.fsel_el = this.$refs.rsubtitle;
|
||||
this.i_subtitle = data;
|
||||
this.triglock = false;
|
||||
setTimeout(this.fsel, 10);
|
||||
}
|
||||
},
|
||||
|
||||
try_subsubtitle(e) {
|
||||
if (e.key == "Shift") return;
|
||||
if (e.key == "ArrowLeft") return;
|
||||
if (e.key == "ArrowRight") return;
|
||||
if (e.key == "ArrowUp") return;
|
||||
if (e.key == "ArrowDown") return;
|
||||
if (e.key == "Backspace") return;
|
||||
if (this.triglock) return;
|
||||
|
||||
if (this.keytimer) {
|
||||
clearTimeout(this.keytimer);
|
||||
}
|
||||
this.keytimer = setTimeout(this.try_subsubtitle2, 250);
|
||||
},
|
||||
|
||||
try_subsubtitle2() {
|
||||
this.keytimer = false
|
||||
$.ajax({
|
||||
url: "/api/search/prefix",
|
||||
method: "POST",
|
||||
data: {
|
||||
title: this.i_subsubtitle
|
||||
}
|
||||
}).done(this.fill_subsubtitle);
|
||||
},
|
||||
|
||||
fill_subsubtitle(data, status) {
|
||||
if (status == "success") {
|
||||
this.triglock = true;
|
||||
this.fsel_start = this.get_caret_position(this.$refs.rsubsubtitle);
|
||||
this.fsel_el = this.$refs.rsubsubtitle;
|
||||
this.i_subsubtitle = data;
|
||||
this.triglock = false;
|
||||
setTimeout(this.fsel, 10);
|
||||
}
|
||||
},
|
||||
|
||||
fsel() {
|
||||
this.select_to_end(this.fsel_el, this.fsel_start);
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="editing" class="input-group">
|
||||
|
||||
<input
|
||||
ref="edval"
|
||||
class="form-control"
|
||||
type="text"
|
||||
v-model="text"
|
||||
@keyup.enter="submit_edit"
|
||||
@keyup.esc="cancel_edit"
|
||||
>
|
||||
|
||||
<button @click="cancel_edit" class="btn btn-danger px-1 py-0">
|
||||
<i class="fa fa-close"></i>
|
||||
</button>
|
||||
<button @click="submit_edit" class="btn btn-success px-1 py-0">
|
||||
<i class="fa fa-check"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else class="d-flex justify-content-between align-middle">
|
||||
<span class="align-middle my-auto">{{ text }}</span>
|
||||
<button @click="enable_edit" class="btn btn-secondary px-1 py-0">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
|
||||
export default {
|
||||
props: [
|
||||
"value",
|
||||
"url",
|
||||
"field",
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
editing: ref(false),
|
||||
text: ref(""),
|
||||
saved: ref(""),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
enable_edit() {
|
||||
this.editing = true;
|
||||
this.saved = this.text;
|
||||
var that = this;
|
||||
setTimeout(function() { $(that.$refs.edval).focus() }, 100);
|
||||
},
|
||||
|
||||
cancel_edit() {
|
||||
this.text = this.saved;
|
||||
this.editing = false;
|
||||
},
|
||||
|
||||
submit_edit() {
|
||||
|
||||
var data = {};
|
||||
data[this.field] = this.text;
|
||||
|
||||
console.log(data);
|
||||
|
||||
$.ajax({
|
||||
url: this.url,
|
||||
method: "POST",
|
||||
data: data
|
||||
});
|
||||
this.editing = false;
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.text = this.value;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+114
@@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="editing">
|
||||
|
||||
<textarea
|
||||
ref="edval"
|
||||
class="form-control w-100"
|
||||
rows="5"
|
||||
type="text"
|
||||
v-model="text"
|
||||
@keyup.esc="cancel_edit"
|
||||
></textarea>
|
||||
|
||||
<button @click="cancel_edit" class="btn btn-danger">
|
||||
<i class="fa fa-close"></i>
|
||||
</button>
|
||||
<button @click="submit_edit" class="btn btn-success">
|
||||
<i class="fa fa-check"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="align-middle my-auto" v-html="md()"></div>
|
||||
<button @click="enable_edit" class="btn btn-secondary">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div ref="slotData" class="visually-hidden">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useSlots, ref } from 'vue/dist/vue.esm-bundler';
|
||||
import { marked } from 'marked';
|
||||
|
||||
|
||||
export default {
|
||||
props: [
|
||||
"url",
|
||||
"field",
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
editing: ref(false),
|
||||
text: ref(""),
|
||||
saved: ref(""),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
init() {
|
||||
this.load();
|
||||
},
|
||||
|
||||
enable_edit() {
|
||||
this.editing = true;
|
||||
this.saved = this.text;
|
||||
var that = this;
|
||||
setTimeout(function() { $(that.$refs.edval).focus() }, 100);
|
||||
},
|
||||
|
||||
cancel_edit() {
|
||||
this.text = this.saved;
|
||||
this.editing = false;
|
||||
},
|
||||
|
||||
submit_edit() {
|
||||
|
||||
var data = {};
|
||||
data[this.field] = this.text;
|
||||
|
||||
$.ajax({
|
||||
url: this.url,
|
||||
method: "POST",
|
||||
data: data
|
||||
});
|
||||
this.editing = false;
|
||||
},
|
||||
|
||||
load() {
|
||||
$.ajax({
|
||||
url: this.url,
|
||||
method: "GET"
|
||||
}).done(this.loaded);
|
||||
},
|
||||
|
||||
loaded(data) {
|
||||
this.text = data[0][this.field];
|
||||
},
|
||||
|
||||
md() {
|
||||
var text = this.text;
|
||||
if (text == null) {
|
||||
text = "Loading...";
|
||||
}
|
||||
var txt = marked.parse(text);
|
||||
return txt;
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// var div = document.createElement("div");
|
||||
// div.innerHTML = this.$slots.default()[0].children;
|
||||
// this.text = div.textContent;
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="editing" class="input-group">
|
||||
|
||||
<select class="form-control" v-model="sel">
|
||||
<option v-for='i in items' :value='i.key'>{{ i.value }}</option>
|
||||
</select>
|
||||
|
||||
<button @click="cancel_edit" class="btn btn-danger">
|
||||
<i class="fa fa-close"></i>
|
||||
</button>
|
||||
<button @click="submit_edit" class="btn btn-success">
|
||||
<i class="fa fa-check"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<button @click="enable_edit" class="btn btn-secondary">
|
||||
<i class="fa fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
|
||||
export default {
|
||||
props: [
|
||||
"list",
|
||||
"target",
|
||||
"method",
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
editing: ref(false),
|
||||
sel: ref(""),
|
||||
items: ref([]),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
enable_edit() {
|
||||
$.ajax({
|
||||
url: this.list,
|
||||
method: "GET"
|
||||
}).done(this.start_edit);
|
||||
},
|
||||
|
||||
start_edit(d) {
|
||||
this.items = d;
|
||||
this.editing = true;
|
||||
var that = this;
|
||||
},
|
||||
|
||||
cancel_edit() {
|
||||
this.text = this.saved;
|
||||
this.editing = false;
|
||||
},
|
||||
|
||||
submit_edit() {
|
||||
|
||||
var data = {};
|
||||
data["item_id"] = this.sel;
|
||||
|
||||
$.ajax({
|
||||
url: this.target,
|
||||
method: this.method,
|
||||
data: data
|
||||
}).done(this.fin);
|
||||
this.editing = false;
|
||||
},
|
||||
|
||||
fin() {
|
||||
location.reload();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.text = this.value;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div>
|
||||
<ul class="list-group">
|
||||
<li v-for="job in jobs" :class="'d-flex justify-content-between list-group-item ' + get_group_color(job)">
|
||||
<span>
|
||||
{{ job.id }} - {{ job.class }} - {{ job.status }}
|
||||
</span>
|
||||
<small v-if='(job.finished + job.failed) > 0'><button @click='delete_job(job)' class='px-1 py-0 btn btn-danger'><i class='fa fa-close'></i></button></small>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
"source"
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
jobs: ref([]),
|
||||
speed: ref(1000),
|
||||
timeout: ref(null),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
update() {
|
||||
$.ajax({
|
||||
url: "/api/jobs/" + this.source,
|
||||
method: "GET"
|
||||
}).done(this.updated);
|
||||
},
|
||||
|
||||
updated(d) {
|
||||
this.refresh(d);
|
||||
setTimeout(this.update, this.speed);
|
||||
},
|
||||
|
||||
refresh(d) {
|
||||
this.jobs = d;
|
||||
|
||||
this.speed = 10000;
|
||||
for (var i = 0; i < this.jobs.length; i++) {
|
||||
if ((this.jobs[i].finished == 0) && (this.jobs[i].failed == 0)) {
|
||||
this.speed = 1000;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get_group_color(j) {
|
||||
if (j.failed > 0) {
|
||||
return "list-group-item-danger";
|
||||
}
|
||||
if (j.finished > 0) {
|
||||
return "list-group-item-success";
|
||||
}
|
||||
if (j.started > 0) {
|
||||
return "list-group-item-warning";
|
||||
}
|
||||
return "list-group-item-info";
|
||||
},
|
||||
|
||||
delete_job(j) {
|
||||
$.ajax({
|
||||
url: "/api/jobs/" + j.id,
|
||||
method: "DELETE"
|
||||
}).done(this.refresh);
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div style="display: none;">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
|
||||
export default {
|
||||
props: [
|
||||
"keyname",
|
||||
"target",
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handler(e) {
|
||||
console.log(e.key);
|
||||
if (e.key == this.keyname) {
|
||||
document.location=this.target;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
window.addEventListener('keypress', this.handler);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+89
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row m-3 bg-white">
|
||||
<div class="col-6 m-0 p-0">
|
||||
<img @click="nav_left" :class="leftclass()" :src="left">
|
||||
</div>
|
||||
<div class="col-6 m-0 p-0">
|
||||
<img @click="nav_right" :class="rightclass()" :src="right">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
rev: ref(""),
|
||||
pages: ref(0)
|
||||
},
|
||||
|
||||
setup(props, emit) {
|
||||
return {
|
||||
left: ref(""),
|
||||
right: ref(""),
|
||||
leftpage : ref(0),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.leftpage = 0;
|
||||
this.update();
|
||||
this.$watch('rev', this.show);
|
||||
},
|
||||
|
||||
update() {
|
||||
this.left = "/page/" + this.rev + "/" + this.leftpage + "/page.jpg";
|
||||
this.right = "/page/" + this.rev + "/" + (this.leftpage + 1) + "/page.jpg";
|
||||
},
|
||||
|
||||
leftclass() {
|
||||
if (this.leftpage > 0) {
|
||||
return 'page-left w-100 m-0 p-0';
|
||||
} else {
|
||||
return 'page-end w-100 m-0 p-0';
|
||||
}
|
||||
},
|
||||
|
||||
rightclass() {
|
||||
if ((this.leftpage + 1) >= this.pages) {
|
||||
return "invisible w-100 m-0 p-0";
|
||||
}
|
||||
if (this.leftpage < this.pages - 2) {
|
||||
return 'page-right w-100 m-0 p-0';
|
||||
} else {
|
||||
return 'page-end w-100 m-0 p-0';
|
||||
}
|
||||
},
|
||||
|
||||
show() {
|
||||
this.left = '';
|
||||
this.right = '';
|
||||
this.leftpage = 0;
|
||||
this.update();
|
||||
},
|
||||
|
||||
nav_right() {
|
||||
if (this.leftpage < this.pages - 2) {
|
||||
this.leftpage += 2;
|
||||
}
|
||||
this.update();
|
||||
},
|
||||
|
||||
nav_left() {
|
||||
this.leftpage -= 2;
|
||||
if (this.leftpage < 0) {
|
||||
this.leftpage = 0;
|
||||
}
|
||||
this.update();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+123
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<div>
|
||||
<ul class="list-group">
|
||||
<li v-for="pdf in pdfs" class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-lg-11 col-12">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
{{ pdf.title }}
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<a class="btn w-100 text-start" :href="pdf.url" target="_blank">{{ pdf.url }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group col-lg-1 col-12 text-center">
|
||||
<button :disabled="busy" @click="reject(pdf)" class="btn btn-danger"><i class="fa fa-close"></i></button>
|
||||
<button :disabled="busy" @click="accept(pdf)" class="btn btn-success"><i class="fa fa-check"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-lg-11 col-12 text-center">
|
||||
<a class="btn w-100" target="_blank">Entire List</a>
|
||||
</div>
|
||||
<div class="btn-group col-lg-1 col-12">
|
||||
<button :disabled="busy" @click="reject_all" class="btn btn-danger"><i class="fa fa-close"></i></button>
|
||||
<button :disabled="busy" @click="accept_all" class="btn btn-success"><i class="fa fa-check"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
pdfs: ref([]),
|
||||
busy: ref(false),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
update() {
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: "/api/spider/pdfs",
|
||||
method: "GET"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
got_update(data) {
|
||||
this.pdfs = data;
|
||||
this.busy = false;
|
||||
},
|
||||
|
||||
accept(pdf) {
|
||||
if (this.busy) return;
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: '/api/spider/pdf/' + pdf.id,
|
||||
method: "PUT"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
reject(pdf) {
|
||||
if (this.busy) return;
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: '/api/spider/pdf/' + pdf.id,
|
||||
method: "DELETE"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
accept_all() {
|
||||
if (this.busy) return;
|
||||
this.busy = true;
|
||||
|
||||
var l = [];
|
||||
for (var i = 0; i < this.pdfs.length; i++) {
|
||||
l.push(this.pdfs[i].id);
|
||||
}
|
||||
$.ajax({
|
||||
url: '/api/spider/pdf/' + l.join(","),
|
||||
method: "PUT"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
reject_all() {
|
||||
if (this.busy) return;
|
||||
this.busy = true;
|
||||
|
||||
var l = [];
|
||||
for (var i = 0; i < this.pdfs.length; i++) {
|
||||
l.push(this.pdfs[i].id);
|
||||
}
|
||||
$.ajax({
|
||||
url: '/api/spider/pdf/' + l.join(","),
|
||||
method: "DELETE"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+188
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<nav class="d-flex justify-content-end">
|
||||
<itemadder :list="'/api/product/' + pid + '/available_metadata'" :target="'/api/product/' + pid + '/metadata'" method="PUT"></itemadder>
|
||||
<div ref="ddcreate_child" class="dropdown ms-1">
|
||||
<button class="btn btn-success dropdown-toggle" title="Add" data-bs-toggle="dropdown"><i class="fa fa-plus-circle"></i></button>
|
||||
<ul class="dropdown-menu" style="min-width: 300px;">
|
||||
<li class="p-2">
|
||||
<strong>Create new child product</strong>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Name</span>
|
||||
<input @keyup.enter="create_child" ref="increate_child" class="form-control" name="title" v-model="newtitle">
|
||||
<button class="btn btn-primary" @click="create_child">Create</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div ref="ddrename" class="dropdown ms-1">
|
||||
<button class="btn btn-success dropdown-toggle" title="Rename" data-bs-toggle="dropdown" @click="set_edittitle"><i class="fa fa-pencil"></i></button>
|
||||
<ul class="dropdown-menu" style="min-width: 300px;">
|
||||
<li class="p-2">
|
||||
<strong>Rename product</strong>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Name</span>
|
||||
<input ref="inrename" class="form-control" name="title" v-model="edittitle">
|
||||
<button class="btn btn-primary" @click="rename">Rename</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-success ms-1" @click="gemini_all"><i class="fa-solid fa-wand-magic"></i></button>
|
||||
<button class="btn btn-success ms-1" @click="gemini_all_move"><i class="fa-solid fa-wand-magic-sparkles"></i></button>
|
||||
|
||||
<button :class="'btn ms-1 ' + dp_class" @click="delete_product"><i class="fa fa-trash"></i></button>
|
||||
|
||||
<button @click="empty_trash" class="ms-1 btn btn-danger" v-if="prod.title=='Trash'"><i class="fa fa-recycle"></i></button>
|
||||
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
"pid",
|
||||
],
|
||||
setup() {
|
||||
return {
|
||||
newtitle: ref(""),
|
||||
edittitle: ref(""),
|
||||
dp_class: ref("btn-danger"),
|
||||
dp_clicks: ref(0),
|
||||
prod: ref({}),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
$(this.$refs.ddcreate_child).on("show.bs.dropdown", this.add_child_show);
|
||||
$(this.$refs.ddcreate_child).on("shown.bs.dropdown", this.add_child_shown);
|
||||
|
||||
$(this.$refs.ddrename).on("show.bs.dropdown", this.rename_show);
|
||||
$(this.$refs.ddrename).on("shown.bs.dropdown", this.rename_shown);
|
||||
this.get_product();
|
||||
},
|
||||
|
||||
get_product() {
|
||||
$.ajax({
|
||||
url: "/api/product/" + this.pid,
|
||||
method: "GET"
|
||||
}).done(this.got_product);
|
||||
},
|
||||
|
||||
add_child_show(e) {
|
||||
this.newtitle = "";
|
||||
},
|
||||
|
||||
add_child_shown(e) {
|
||||
$(this.$refs.increate_child).focus();
|
||||
},
|
||||
|
||||
rename_show(e) {
|
||||
this.edittitle = this.prod.title;
|
||||
},
|
||||
|
||||
set_edittitle() {
|
||||
this.edittitle = this.prod.title;
|
||||
},
|
||||
|
||||
got_product(data) {
|
||||
this.prod = data[0];
|
||||
},
|
||||
|
||||
rename_shown(e) {
|
||||
},
|
||||
|
||||
create_child() {
|
||||
console.log("Adding child");
|
||||
$.ajax({
|
||||
url: "/api/product/" + this.pid,
|
||||
method: "PUT",
|
||||
data: {
|
||||
title: this.newtitle
|
||||
}
|
||||
}).done(this.created_child);
|
||||
},
|
||||
|
||||
rename() {
|
||||
$.ajax({
|
||||
url: "/api/product/" + this.pid,
|
||||
method: "POST",
|
||||
data: {
|
||||
title: this.edittitle
|
||||
}
|
||||
}).done(this.renamed);
|
||||
},
|
||||
|
||||
renamed() {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
created_child(data) {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
delete_product() {
|
||||
this.dp_clicks++;
|
||||
console.log("clicked " + this.dp_clicks);
|
||||
if (this.dp_clicks >= 2) {
|
||||
$.ajax({
|
||||
url: "/api/product/" + this.pid,
|
||||
method: "DELETE",
|
||||
}).done(this.done_delete);
|
||||
return;
|
||||
}
|
||||
this.dp_class = "btn-warning";
|
||||
setTimeout(this.undo_delete, 1000);
|
||||
},
|
||||
|
||||
undo_delete() {
|
||||
console.log("Undo delete");
|
||||
this.dp_class = "btn-danger";
|
||||
this.dp_clicks = 0;
|
||||
},
|
||||
|
||||
|
||||
done_delete(data) {
|
||||
document.location="/documents/" + data.id;
|
||||
},
|
||||
|
||||
empty_trash() {
|
||||
$.ajax({
|
||||
url: "/api/product/trash/" + this.prod.id,
|
||||
method: "DELETE"
|
||||
}).done(this.trash_emptied);
|
||||
},
|
||||
|
||||
trash_emptied() {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
gemini_all() {
|
||||
$.ajax({
|
||||
url: "/api/product/gemini_all/" + this.prod.id + "/keep",
|
||||
method: "GET"
|
||||
}).done(this.gemini_all_queued);
|
||||
},
|
||||
|
||||
gemini_all_move() {
|
||||
$.ajax({
|
||||
url: "/api/product/gemini_all/" + this.prod.id + "/move",
|
||||
method: "GET"
|
||||
}).done(this.gemini_all_queued);
|
||||
},
|
||||
|
||||
gemini_all_queued(d) {
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
|
||||
</script>
|
||||
Executable
+172
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-for="p in products" class="btn-group m-1">
|
||||
<button class="btn btn-secondary p-1" :title="p.full_path"><small>{{ p.title }}</small></button>
|
||||
<button :pid="p.id" @click.stop="remove(p.id)" class="btn btn-secondary p-1" title="Remove"><small><i class="fa fa-close"></i></small></button>
|
||||
</div>
|
||||
<div ref="dropdown" class="dropdown" @show.bs.dropdown="add_show">
|
||||
<button class="btn btn-success p-1 dropdown-toggle" title="Add" data-bs-toggle="dropdown" @click="add_show"><small><i class="fa fa-plus"></i></small></button>
|
||||
<ul class="dropdown-menu" @show.bs.dropdown="add_show">
|
||||
<li v-for="p in mru"><a href='#' @click="add_pid(p)" class="dropdown-item">{{ p.full_path }}</a></li>
|
||||
<hr>
|
||||
<li><input ref="searchinput" @input="do_search" class='form-control' name='search' v-model="search" autocomplete="off"></li>
|
||||
<li v-for="p in searchres"><a href='#' @click="add_pid(p)" class="dropdown-item">{{ p.full_path }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button @click="set_default_pids" class="btn btn-primary">Set Default</button>
|
||||
<button @click="clear_default_pids" class="btn btn-primary">Clear Default</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, computed } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
modelValue: ref(""),
|
||||
},
|
||||
setup(props, {emit}) {
|
||||
return {
|
||||
products: ref([]),
|
||||
mru: ref([]),
|
||||
search: ref(""),
|
||||
searchres: ref([]),
|
||||
pids: computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => emit('update:modelValue', value)
|
||||
}),
|
||||
was_mod: ref(false),
|
||||
req: ref(null),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
$(document).on("show.bs.dropdown", '.dropdown', this.add_show);
|
||||
$(document).on("shown.bs.dropdown", $(this.$refs.dropdown), this.add_shown);
|
||||
$(this.$refs.dropdown).on("show.bs.dropdown", this.add_show);
|
||||
$(this.$refs.dropdown).on("shown.bs.dropdown", this.add_shown);
|
||||
this.get_products();
|
||||
|
||||
this.$watch('modelValue', this.get_products);
|
||||
|
||||
},
|
||||
|
||||
get_products() {
|
||||
if (this.pids!= "") {
|
||||
$.ajax({
|
||||
url: "/api/product/" + this.pids,
|
||||
method: "GET"
|
||||
}).done(this.got_products);
|
||||
} else {
|
||||
this.products = [];
|
||||
}
|
||||
|
||||
var m = this.was_mod;
|
||||
this.was_mod = false;
|
||||
|
||||
if (!m) {
|
||||
if (this.pids == "") {
|
||||
// Get default if available
|
||||
var p = localStorage.getItem("default_pids");
|
||||
if ((p != null) && (p != "")) {
|
||||
this.was_mod = true;
|
||||
this.pids = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
got_products(data) {
|
||||
this.products = data;
|
||||
},
|
||||
|
||||
remove(e) {
|
||||
this.was_mod = true;
|
||||
var tmp = [];
|
||||
var pidarray = [];
|
||||
for (var i = 0; i < this.products.length; i++) {
|
||||
if (this.products[i].id != e) {
|
||||
tmp.push(this.products[i]);
|
||||
pidarray.push(this.products[i].id);
|
||||
}
|
||||
}
|
||||
this.products = tmp;
|
||||
this.pids = pidarray.join(",");
|
||||
},
|
||||
|
||||
add_show(e) {
|
||||
this.search = "";
|
||||
this.searchres = []
|
||||
$.ajax({
|
||||
url: "/api/productmru",
|
||||
method: "GET"
|
||||
}).done(this.fill_mru);
|
||||
},
|
||||
|
||||
add_shown(e) {
|
||||
this.$refs.searchinput.focus();
|
||||
},
|
||||
|
||||
fill_mru(data) {
|
||||
this.mru = data;
|
||||
},
|
||||
|
||||
do_search(e) {
|
||||
if (this.search.length >= 3) {
|
||||
if (this.req != null) {
|
||||
this.req.abort();
|
||||
this.req = null;
|
||||
}
|
||||
this.req=$.ajax({
|
||||
url: "/api/search/product",
|
||||
method: "POST",
|
||||
data: {
|
||||
search: this.search
|
||||
}
|
||||
}).done(this.search_done);
|
||||
}
|
||||
},
|
||||
|
||||
search_done(data) {
|
||||
this.searchres = data;
|
||||
},
|
||||
|
||||
add_pid(prod) {
|
||||
this.was_mod = true;
|
||||
var pidarray;
|
||||
if (this.pids == "") {
|
||||
pidarray = [];
|
||||
} else {
|
||||
pidarray = this.pids.split(",");
|
||||
}
|
||||
if (pidarray.includes(prod.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pidarray.push(prod.id);
|
||||
|
||||
this.pids = pidarray.join(",");
|
||||
this.products.push(prod);
|
||||
$.ajax({
|
||||
url: "/api/productmru/" + prod.id,
|
||||
method: "POST",
|
||||
data: {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
set_default_pids() {
|
||||
localStorage.setItem("default_pids", this.pids);
|
||||
},
|
||||
|
||||
clear_default_pids() {
|
||||
localStorage.setItem("default_pids", "");
|
||||
},
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div tabindex=0 @blur.capture="click_close">
|
||||
<form action="/search" method="POST">
|
||||
<div class="input-group">
|
||||
<input name="search" ref="sb" @focus="key_search" @keyup="key_search" class="form-control" v-model="search">
|
||||
<input type="submit" class="btn btn-success" value="Search">
|
||||
</div>
|
||||
<div v-if="results.length > 0" class="z-3 position-absolute bg-light">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item" v-for="r in results"><a :href="'/document/' + r.id"><strong>{{ r.title }}</strong> {{ r.subtitle }} <small>{{ r.subsubtitle }}</small></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
search: ref(""),
|
||||
searchTimer: ref(null),
|
||||
results: ref([]),
|
||||
req: ref(null),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
click_close(event) {
|
||||
if (!event.currentTarget.contains(event.relatedTarget)) {
|
||||
this.results = [];
|
||||
}
|
||||
},
|
||||
|
||||
key_search() {
|
||||
if (this.searchTimer != null) {
|
||||
window.clearTimeout(this.searchTimer);
|
||||
this.searchTimer = null;
|
||||
}
|
||||
this.searchTimer = setTimeout(this.do_key_search, 100);
|
||||
},
|
||||
|
||||
do_key_search() {
|
||||
if (this.search.length < 3) {
|
||||
this.results = [];
|
||||
} else {
|
||||
this.searchTimer = null;
|
||||
if (this.req != null) {
|
||||
this.req.abort();
|
||||
this.req = null;
|
||||
}
|
||||
this.req = $.ajax({
|
||||
url: "/api/search/title",
|
||||
method: "POST",
|
||||
data: {
|
||||
search: this.search
|
||||
}
|
||||
}).done(this.got_results);
|
||||
}
|
||||
},
|
||||
|
||||
got_results(data) {
|
||||
this.results = data;
|
||||
},
|
||||
shortcut(e) {
|
||||
if (e.target.tagName == "INPUT") return;
|
||||
if (e.target.tagName == "TEXTAREA") return;
|
||||
if (e.key == "/") {
|
||||
e.preventDefault();
|
||||
$(this.$refs.sb).focus();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
$(document).on("keydown", this.shortcut);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+79
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
|
||||
<div>
|
||||
<ul class="list-group">
|
||||
<li v-for="page in pages" class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-lg-11 col-12 text-center">
|
||||
<a class="btn text-left w-100" :href="page.url" target="_blank">
|
||||
<h6>{{ page.title }}</h6>
|
||||
{{ page.url }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group col-lg-1 col-12">
|
||||
<button :disabled="busy" @click="reject(page)" class="btn btn-danger"><i class="fa fa-close"></i></button>
|
||||
<button :disabled="busy" @click="accept(page)" class="btn btn-success"><i class="fa fa-check"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
pages: ref([]),
|
||||
busy: ref(false),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
update() {
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: "/api/spider/pages",
|
||||
method: "GET"
|
||||
}).done(this.got_update);
|
||||
},
|
||||
|
||||
got_update(data) {
|
||||
this.pages = data;
|
||||
this.busy = false;
|
||||
},
|
||||
|
||||
accept(page) {
|
||||
if (this.busy) return;
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: "/api/spider/page/" + page.id,
|
||||
method: "PUT"
|
||||
}).done(this.got_update)
|
||||
},
|
||||
|
||||
reject(page) {
|
||||
if (this.busy) return;
|
||||
this.busy = true;
|
||||
$.ajax({
|
||||
url: "/api/spider/page/" + page.id,
|
||||
method: "DELETE"
|
||||
}).done(this.got_update)
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+73
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div @click="confirm_rating()" @mouseleave.prevent="reset">
|
||||
<span v-if="current_rating<3" @mouseenter.prevent="set_rating(10)"><i class="fa-regular fa-star"></i></span>
|
||||
<span v-else-if="current_rating<8" @mouseenter.prevent="set_rating(10)"><i class="fa-solid fa-star-half-stroke"></i></span>
|
||||
<span v-else @mouseenter.prevent="set_rating(10)"><i class="fa-solid fa-star"></i></span>
|
||||
|
||||
<span v-if="current_rating<13" @mouseenter.prevent="set_rating(20)"><i class="fa-regular fa-star"></i></span>
|
||||
<span v-else-if="current_rating<18" @mouseenter.prevent="set_rating(20)"><i class="fa-solid fa-star-half-stroke"></i></span>
|
||||
<span v-else @mouseenter.prevent="set_rating(20)"><i class="fa-solid fa-star"></i></span>
|
||||
|
||||
<span v-if="current_rating<23" @mouseenter.prevent="set_rating(30)"><i class="fa-regular fa-star"></i></span>
|
||||
<span v-else-if="current_rating<28" @mouseenter.prevent="set_rating(30)"><i class="fa-solid fa-star-half-stroke"></i></span>
|
||||
<span v-else @mouseenter.prevent="set_rating(30)"><i class="fa-solid fa-star"></i></span>
|
||||
|
||||
<span v-if="current_rating<33" @mouseenter.prevent="set_rating(40)"><i class="fa-regular fa-star"></i></span>
|
||||
<span v-else-if="current_rating<38" @mouseenter.prevent="set_rating(40)"><i class="fa-solid fa-star-half-stroke"></i></span>
|
||||
<span v-else @mouseenter.prevent="set_rating(40)"><i class="fa-solid fa-star"></i></span>
|
||||
|
||||
<span v-if="current_rating<43" @mouseenter.prevent="set_rating(50)"><i class="fa-regular fa-star"></i></span>
|
||||
<span v-else-if="current_rating<48" @mouseenter.prevent="set_rating(50)"><i class="fa-solid fa-star-half-stroke"></i></span>
|
||||
<span v-else @mouseenter.prevent="set_rating(50)"><i class="fa-solid fa-star"></i></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
rev: ref(""),
|
||||
rating: ref("")
|
||||
},
|
||||
|
||||
setup() {
|
||||
return {
|
||||
current_rating: ref(""),
|
||||
orig_rating: ref("")
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.current_rating = this.rating;
|
||||
this.orig_rating = this.rating;
|
||||
},
|
||||
|
||||
reset() {
|
||||
this.current_rating = this.orig_rating;
|
||||
},
|
||||
|
||||
set_rating(v) {
|
||||
this.current_rating = v;
|
||||
},
|
||||
|
||||
confirm_rating() {
|
||||
this.orig_rating = this.current_rating;
|
||||
$.ajax({
|
||||
url: "/api/revision/rate/" + this.rev + "/" + this.current_rating,
|
||||
method: "PUT"
|
||||
}).done(this.updated);
|
||||
},
|
||||
|
||||
updated(d) {
|
||||
this.orig_rating = d.rating;
|
||||
this.current_rating = d.rating;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
},
|
||||
|
||||
mounted() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
.table td.fit,
|
||||
.table th.fit {
|
||||
white-space: nowrap;
|
||||
width: 1%
|
||||
}
|
||||
|
||||
a[title]:hover::after {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.ocrtext {
|
||||
overflow: auto;
|
||||
max-height: 400px;
|
||||
|
||||
}
|
||||
|
||||
.page-right {
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.page-left {
|
||||
cursor: w-resize;
|
||||
}
|
||||
|
||||
.page-end {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
|
||||
import 'jquery';
|
||||
import 'jquery-simple-websocket';
|
||||
import 'bootstrap';
|
||||
import '@fortawesome/fontawesome-free/js/fontawesome';
|
||||
import '@fortawesome/fontawesome-free/js/solid';
|
||||
import '@fortawesome/fontawesome-free/js/regular';
|
||||
import '@fortawesome/fontawesome-free/js/brands';
|
||||
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
import { createApp } from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
import Download from './Download.vue';
|
||||
import DocumentEdit from './DocumentEdit.vue';
|
||||
import ProductSelector from './ProductSelector.vue';
|
||||
import ProductControls from './ProductControls.vue';
|
||||
import InlineEdit from './InlineEdit.vue';
|
||||
import InlineEditText from './InlineEditText.vue';
|
||||
import Search from './Search.vue';
|
||||
import PDFList from './PDFList.vue';
|
||||
import SpiderPages from './SpiderPages.vue';
|
||||
import DownloadManager from './DownloadManager.vue';
|
||||
import Imports from './Imports.vue';
|
||||
import IDMatch from './IDMatch.vue';
|
||||
import DDDiv from './DDDiv.vue';
|
||||
import PDF from './PDF.vue';
|
||||
import ItemAdder from './ItemAdder.vue';
|
||||
import KeyboardInteraction from './KeyboardInteraction.vue';
|
||||
import JobDisplay from './JobDisplay.vue';
|
||||
import StarRating from './StarRating.vue';
|
||||
|
||||
const app = createApp({ });
|
||||
|
||||
app.component("download", Download);
|
||||
app.component("documentedit", DocumentEdit);
|
||||
app.component("productselector", ProductSelector);
|
||||
app.component("productcontrols", ProductControls);
|
||||
app.component("inlineedit", InlineEdit);
|
||||
app.component("inlineedittext", InlineEditText);
|
||||
app.component("search", Search);
|
||||
app.component("pdflist", PDFList);
|
||||
app.component("spiderpages", SpiderPages);
|
||||
app.component("downloadmanager", DownloadManager);
|
||||
app.component("imports", Imports);
|
||||
app.component("idmatch", IDMatch);
|
||||
app.component("dddiv", DDDiv);
|
||||
app.component("pdf", PDF);
|
||||
app.component("itemadder", ItemAdder);
|
||||
app.component("keyboardinteraction", KeyboardInteraction);
|
||||
app.component("jobdisplay", JobDisplay);
|
||||
app.component("starrating", StarRating);
|
||||
|
||||
$(window).on("load", function() { app.mount('#app') });
|
||||
Executable
Reference in New Issue
Block a user