218 lines
6.3 KiB
Vue
Executable File
218 lines
6.3 KiB
Vue
Executable File
<template>
|
|
<a
|
|
class="list-item"
|
|
v-bind:class="{ selected: is_selected }"
|
|
v-bind:draggable="true"
|
|
v-bind:href="url"
|
|
v-on:click.meta.left.exact.prevent.stop="onAddToSelection"
|
|
v-on:click.left.exact.prevent.stop="onClicked"
|
|
v-on:click.middle.exact="
|
|
incrementVisits({ document: document, folder: selectedFolder })
|
|
"
|
|
v-on:dblclick="
|
|
openDocument({ document: document, folder: selectedFolder })
|
|
"
|
|
v-on:dragstart="onDragStart"
|
|
v-on:dragend="onDragEnd"
|
|
rel="noopener noreferrer"
|
|
>
|
|
<div class="icons">
|
|
<img v-bind:src="document.favicon" class="favicon-lg" />
|
|
</div>
|
|
<div class="list-item-text">
|
|
{{ document.title }}
|
|
<div class="text-sm">{{ document.url }}</div>
|
|
</div>
|
|
<div class="badges">
|
|
<div
|
|
v-if="
|
|
document.http_status_code < 200 ||
|
|
document.http_status_code > 299
|
|
"
|
|
v-bind:class="statusClass"
|
|
v-bind:title="document.http_status_text"
|
|
>
|
|
<svg fill="currentColor" width="16" height="16">
|
|
<use v-bind:xlink:href="icon(statusIcon)" />
|
|
</svg>
|
|
</div>
|
|
<div
|
|
class="badge default"
|
|
v-if="document.feed_item_states_count > 0"
|
|
>
|
|
<span v-if="document.has_new_unread_items">
|
|
<svg
|
|
fill="currentColor"
|
|
width="16"
|
|
height="16"
|
|
class="text-blue-300"
|
|
>
|
|
<use v-bind:xlink:href="icon('update')" />
|
|
</svg>
|
|
</span>
|
|
{{ document.feed_item_states_count }}
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters, mapActions } from "vuex";
|
|
|
|
export default {
|
|
props: ["document"],
|
|
data: function () {
|
|
return {
|
|
enableEnsureVisible: false,
|
|
};
|
|
},
|
|
computed: {
|
|
...mapGetters({
|
|
selectedDocuments: "documents/selectedDocuments",
|
|
selectedFolder: "folders/selectedFolder",
|
|
}),
|
|
|
|
/**
|
|
* Return a boolean value indicating if this document belongs to
|
|
* currently selected documents
|
|
*/
|
|
is_selected: function () {
|
|
const self = this;
|
|
|
|
return (
|
|
self.selectedDocuments &&
|
|
self.selectedDocuments.find((d) => d.id === self.document.id)
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Return document's initial URL instead of the real URL, unless there
|
|
* is not attached bookmark
|
|
*/
|
|
url: function () {
|
|
const self = this;
|
|
|
|
if (self.document.bookmark.initial_url) {
|
|
return self.document.bookmark.initial_url;
|
|
}
|
|
|
|
return self.document.url;
|
|
},
|
|
|
|
statusClass: function () {
|
|
const code = this.document.http_status_code;
|
|
let className = null;
|
|
|
|
if (code === 0) {
|
|
className = "http-status-general-error";
|
|
} else if (code >= 100 && code <= 199) {
|
|
className = "http-status-info";
|
|
} else if (code >= 200 && code <= 299) {
|
|
className = "http-status-success";
|
|
} else if (code >= 300 && code <= 399) {
|
|
className = "http-status-redirection";
|
|
} else if (code >= 400 && code <= 499) {
|
|
className = "http-status-client-error";
|
|
} else if (code >= 500 && code <= 599) {
|
|
className = "http-status-server-error";
|
|
}
|
|
|
|
return className;
|
|
},
|
|
|
|
statusIcon: function () {
|
|
const code = this.document.http_status_code;
|
|
let icon = null;
|
|
|
|
if (code === 0) {
|
|
icon = "error";
|
|
} else if (code >= 100 && code <= 199) {
|
|
icon = "info";
|
|
} else if (code >= 200 && code <= 299) {
|
|
icon = "success";
|
|
} else if (code >= 300 && code <= 399) {
|
|
icon = "redirect";
|
|
} else if (code >= 400 && code <= 499) {
|
|
icon = "warning";
|
|
} else if (code >= 500 && code <= 599) {
|
|
icon = "error";
|
|
}
|
|
|
|
return icon;
|
|
},
|
|
},
|
|
methods: {
|
|
...mapActions({
|
|
startDraggingDocuments: "documents/startDraggingDocuments",
|
|
stopDraggingDocuments: "documents/stopDraggingDocuments",
|
|
incrementVisits: "documents/incrementVisits",
|
|
openDocument: "documents/openDocument",
|
|
}),
|
|
|
|
/**
|
|
* Document has been clicked
|
|
*/
|
|
onClicked: function () {
|
|
const self = this;
|
|
|
|
self.$emit("selected-documents-changed", [self.document]);
|
|
},
|
|
|
|
/**
|
|
* Add this document to selection
|
|
*/
|
|
onAddToSelection: function () {
|
|
const self = this;
|
|
|
|
let selectedDocuments = [...self.selectedDocuments];
|
|
|
|
const index = selectedDocuments.findIndex(
|
|
(doc) => doc.id === self.document.id
|
|
);
|
|
|
|
if (index === -1) {
|
|
selectedDocuments.push(self.document);
|
|
} else {
|
|
selectedDocuments.splice(index, 1);
|
|
}
|
|
|
|
self.$emit("selected-documents-changed", selectedDocuments);
|
|
},
|
|
|
|
/**
|
|
* Begin drag'n'drop
|
|
*/
|
|
onDragStart: function () {
|
|
const self = this;
|
|
|
|
var documents = [self.document];
|
|
|
|
if (self.selectedDocuments && self.selectedDocuments.length > 0) {
|
|
documents = self.selectedDocuments;
|
|
}
|
|
|
|
self.startDraggingDocuments(documents);
|
|
},
|
|
|
|
/**
|
|
* Stop drag'n'drop
|
|
*/
|
|
onDragEnd: function () {
|
|
const self = this;
|
|
|
|
self.stopDraggingDocuments();
|
|
},
|
|
|
|
ensureVisible: function () {
|
|
const self = this;
|
|
|
|
if (self.enableEnsureVisible) {
|
|
self.$el.scrollIntoView({
|
|
block: "center",
|
|
});
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</script>
|