aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/assets/app.scss2
-rw-r--r--src/assets/components/status.scss48
-rw-r--r--src/components/services/OctoPrint.vue108
3 files changed, 157 insertions, 1 deletions
diff --git a/src/assets/app.scss b/src/assets/app.scss
index d112482..4ce417a 100644
--- a/src/assets/app.scss
+++ b/src/assets/app.scss
@@ -1,8 +1,8 @@
1@charset "utf-8"; 1@charset "utf-8";
2 2
3@import "./webfonts/webfonts.scss"; 3@import "./webfonts/webfonts.scss";
4
5@import "../../node_modules/bulma/bulma"; 4@import "../../node_modules/bulma/bulma";
5@import "./components/status.scss";
6 6
7// Themes import 7// Themes import
8@import "./themes/sui.scss"; 8@import "./themes/sui.scss";
diff --git a/src/assets/components/status.scss b/src/assets/components/status.scss
new file mode 100644
index 0000000..b5fd20b
--- /dev/null
+++ b/src/assets/components/status.scss
@@ -0,0 +1,48 @@
1.status {
2 font-size: 0.8rem;
3 color: var(--text-title);
4
5 &.offline:before, &.error:before {
6 background-color: #d65c68;
7 box-shadow: 0 0 5px 1px #d65c68;
8 color: #d65c68;
9 }
10
11 &.pending:before {
12 background-color: #e8bb7d;
13 box-shadow: 0 0 5px 1px #e8bb7d;
14 }
15
16 &.online:before, &.ready:before {
17 background-color: #94e185;
18 box-shadow: 0 0 5px 1px #94e185;
19 }
20
21 &.in-progress:before {
22 background-color: #8fe87d;
23 box-shadow: 0 0 5px 1px #8fe87d;
24 animation: pulse 1s alternate infinite;
25 }
26
27 @keyframes pulse {
28 0% {
29 background: rgba(255, 255, 255, 0.2);
30 box-shadow: inset 0px 0px 10px 2px rgba(0, 255, 182, 0.3),
31 0px 0px 5px 2px rgba(0, 255, 135, 0.2);
32 }
33 100% {
34 background: rgba(255, 255, 255, 1);
35 box-shadow: inset 0px 0px 10px 2px rgba(0, 255, 182, 0.5),
36 0px 0px 15px 2px rgba(0, 255, 135, 1);
37 }
38 }
39
40 &:before {
41 content: " ";
42 display: inline-block;
43 width: 8px;
44 height: 8px;
45 margin-right: 10px;
46 border-radius: 8px;
47 }
48 } \ No newline at end of file
diff --git a/src/components/services/OctoPrint.vue b/src/components/services/OctoPrint.vue
new file mode 100644
index 0000000..c5da8d9
--- /dev/null
+++ b/src/components/services/OctoPrint.vue
@@ -0,0 +1,108 @@
1<template>
2 <Generic :item="item" :title="state">
3 <template #content>
4 <p class="title is-4">{{ item.name }}</p>
5 <p class="subtitle is-6">
6 <template v-if="item.subtitle && !state">
7 {{ item.subtitle }}
8 </template>
9 <template v-if="!error && display == 'text'">
10 <i class="fa-solid fa-gear mr-1"></i>
11 <b v-if="completion">{{ completion.toFixed() }}%</b>
12 <span class="separator mx-1"> | </span>
13 <span v-if="printTime" :title="`${toTime(printTimeLeft)} left`">
14 <i class="fa-solid fa-stopwatch mr-1"></i>
15 {{ toTime(printTime) }}
16 </span>
17 </template>
18 <template v-if="!error && display == 'bar'">
19 <progress
20 v-if="completion"
21 class="progress is-primary"
22 :value="completion"
23 max="100"
24 :title="`${state} - ${completion.toFixed()}%, ${toTime(
25 printTimeLeft
26 )} left`"
27 >
28 {{ completion }}%
29 </progress>
30 </template>
31 <span v-if="error" :title="error">{{ error }}</span>
32 </p>
33 </template>
34 <template #indicator>
35 <i :class="['status', statusClass]" :title="state"></i>
36 </template>
37 </Generic>
38</template>
39
40<script>
41import service from "@/mixins/service.js";
42import Generic from "./Generic.vue";
43
44export default {
45 name: "OctoPrint",
46 mixins: [service],
47 props: {
48 item: Object,
49 },
50 components: {
51 Generic,
52 },
53 data: () => ({
54 printTime: null,
55 printTimeLeft: null,
56 completion: null,
57 state: null,
58 error: null,
59 }),
60 computed: {
61 statusClass: function () {
62 switch (this.state) {
63 case "Operational":
64 return "ready";
65 case "Offline":
66 return "offline";
67 case "Printing":
68 return "in-progress";
69 default:
70 return "pending";
71 }
72 },
73 },
74 created() {
75 this.display = this.item.display == "bar" ? this.item.display : "text";
76 this.fetchStatus();
77 },
78 methods: {
79 fetchStatus: async function () {
80 try {
81 const response = await this.fetch(`api/job?apikey=${this.item.apikey}`);
82 this.printTime = response.progress.printTime;
83 this.printTimeLeft = response.progress.printTimeLeft;
84 this.completion = response.progress.completion;
85 this.state = response.state;
86 this.error = response.error;
87 } catch (e) {
88 this.error = `Fail to fetch octoprint data (${e.message})`;
89 console.error(e);
90 }
91 },
92 toTime: function (timastamp) {
93 return new Date(timastamp * 1000).toTimeString().substring(0, 5);
94 },
95 },
96};
97</script>
98
99<style scoped lang="scss">
100.fa-triangle-exclamation::before {
101 color: #d65c68;
102}
103
104.progress {
105 height: 8px;
106 width: 90%;
107}
108</style>