]>
Commit | Line | Data |
---|---|---|
b9c5fcf0 BW |
1 | <template> |
2 | <div | |
3 | id="app" | |
4 | v-if="config" | |
5 | :class="[ | |
6 | `theme-${config.theme}`, | |
7 | isDark ? 'is-dark' : 'is-light', | |
9814a037 | 8 | !config.footer ? 'no-footer' : '', |
b9c5fcf0 BW |
9 | ]" |
10 | > | |
11 | <DynamicTheme :themes="config.colors" /> | |
12 | <div id="bighead"> | |
e0a72b7d | 13 | <section v-if="config.header" class="first-line is-hidden-touch"> |
b9c5fcf0 BW |
14 | <div v-cloak class="container"> |
15 | <div class="logo"> | |
3bf0edcf | 16 | <img v-if="config.logo" :src="config.logo" alt="dashboard logo" /> |
b9c5fcf0 BW |
17 | <i v-if="config.icon" :class="config.icon"></i> |
18 | </div> | |
19 | <div class="dashboard-title"> | |
20 | <span class="headline">{{ config.subtitle }}</span> | |
21 | <h1>{{ config.title }}</h1> | |
22 | </div> | |
23 | </div> | |
24 | </section> | |
25 | ||
26 | <Navbar | |
27 | :open="showMenu" | |
28 | :links="config.links" | |
29 | @navbar:toggle="showMenu = !showMenu" | |
e0a72b7d IB |
30 | :navigateToFirstService="navigateToFirstService" |
31 | :filterServices="filterServices" | |
b9c5fcf0 BW |
32 | > |
33 | <DarkMode @updated="isDark = $event" /> | |
b9c5fcf0 BW |
34 | </Navbar> |
35 | </div> | |
36 | ||
37 | <section id="main-section" class="section"> | |
38 | <div v-cloak class="container"> | |
e9113b48 BW |
39 | <ConnectivityChecker |
40 | v-if="config.connectivityCheck" | |
41 | @network:status-update="offline = $event" | |
42 | /> | |
b9c5fcf0 BW |
43 | <div v-if="!offline"> |
44 | <!-- Optional messages --> | |
45 | <Message :item="config.message" /> | |
46 | ||
f1202e1a | 47 | <div class="columns is-multiline"> |
b9c5fcf0 BW |
48 | <template v-for="group in services"> |
49 | <h2 v-if="group.name" class="column is-full group-title"> | |
50 | <i v-if="group.icon" :class="group.icon"></i> | |
51 | {{ group.name }} | |
52 | </h2> | |
53 | <Service | |
54 | v-for="item in group.items" | |
1a42e30a | 55 | :key="item.name" |
b9c5fcf0 | 56 | v-bind:item="item" |
e0a72b7d | 57 | class="column is-half-tablet is-one-third-widescreen is-half-desktop" |
b9c5fcf0 BW |
58 | /> |
59 | </template> | |
60 | </div> | |
b9c5fcf0 BW |
61 | </div> |
62 | </div> | |
63 | </section> | |
64 | ||
65 | <footer class="footer"> | |
66 | <div class="container"> | |
67 | <div | |
68 | class="content has-text-centered" | |
69 | v-if="config.footer" | |
70 | v-html="config.footer" | |
71 | ></div> | |
72 | </div> | |
73 | </footer> | |
74 | </div> | |
75 | </template> | |
76 | ||
77 | <script> | |
78 | const jsyaml = require("js-yaml"); | |
79 | const merge = require("lodash.merge"); | |
80 | ||
81 | import Navbar from "./components/Navbar.vue"; | |
82 | import ConnectivityChecker from "./components/ConnectivityChecker.vue"; | |
83 | import Service from "./components/Service.vue"; | |
84 | import Message from "./components/Message.vue"; | |
b9c5fcf0 BW |
85 | import DarkMode from "./components/DarkMode.vue"; |
86 | import DynamicTheme from "./components/DynamicTheme.vue"; | |
87 | ||
88 | import defaultConfig from "./assets/defaults.yml"; | |
89 | ||
90 | export default { | |
91 | name: "App", | |
92 | components: { | |
93 | Navbar, | |
94 | ConnectivityChecker, | |
95 | Service, | |
96 | Message, | |
b9c5fcf0 | 97 | DarkMode, |
9814a037 | 98 | DynamicTheme, |
b9c5fcf0 BW |
99 | }, |
100 | data: function () { | |
101 | return { | |
102 | config: null, | |
103 | services: null, | |
104 | offline: false, | |
105 | filter: "", | |
b9c5fcf0 | 106 | isDark: null, |
9814a037 | 107 | showMenu: false, |
b9c5fcf0 BW |
108 | }; |
109 | }, | |
110 | created: async function () { | |
bd910942 BW |
111 | const defaults = jsyaml.load(defaultConfig); |
112 | let config = await this.getConfig(); | |
113 | this.config = merge(defaults, config); | |
114 | this.services = this.config.services; | |
115 | document.title = `${this.config.title} | ${this.config.subtitle}`; | |
b9c5fcf0 BW |
116 | }, |
117 | methods: { | |
1a42e30a BW |
118 | getConfig: function (path = "config.yml") { |
119 | return fetch(path).then((response) => { | |
120 | if (!response.ok) { | |
121 | throw Error(response.statusText); | |
122 | } | |
123 | ||
124 | const that = this; | |
125 | return response | |
126 | .text() | |
127 | .then((body) => { | |
bd910942 | 128 | return jsyaml.load(body); |
1a42e30a BW |
129 | }) |
130 | .then(function (config) { | |
131 | if (config.externalConfig) { | |
132 | return that.getConfig(config.externalConfig); | |
133 | } | |
134 | return config; | |
135 | }) | |
136 | .catch((error) => { | |
137 | return this.handleErrors("⚠️ Error loading configuration", error); | |
bd910942 | 138 | }); |
1a42e30a | 139 | }); |
b9c5fcf0 BW |
140 | }, |
141 | matchesFilter: function (item) { | |
142 | return ( | |
143 | item.name.toLowerCase().includes(this.filter) || | |
144 | (item.tag && item.tag.toLowerCase().includes(this.filter)) | |
145 | ); | |
146 | }, | |
147 | navigateToFirstService: function (target) { | |
148 | try { | |
149 | const service = this.services[0].items[0]; | |
150 | window.open(service.url, target || service.target || "_self"); | |
151 | } catch (error) { | |
152 | console.warning("fail to open service"); | |
153 | } | |
154 | }, | |
155 | filterServices: function (filter) { | |
156 | this.filter = filter; | |
157 | ||
158 | if (!filter) { | |
159 | this.services = this.config.services; | |
160 | return; | |
161 | } | |
162 | ||
163 | const searchResultItems = []; | |
164 | for (const group of this.config.services) { | |
165 | for (const item of group.items) { | |
166 | if (this.matchesFilter(item)) { | |
167 | searchResultItems.push(item); | |
168 | } | |
169 | } | |
170 | } | |
171 | ||
172 | this.services = [ | |
173 | { | |
174 | name: filter, | |
175 | icon: "fas fa-search", | |
9814a037 BW |
176 | items: searchResultItems, |
177 | }, | |
b9c5fcf0 | 178 | ]; |
9814a037 | 179 | }, |
bd910942 BW |
180 | handleErrors: function (title, content) { |
181 | return { | |
182 | message: { | |
183 | title: title, | |
184 | style: "is-danger", | |
185 | content: content, | |
186 | }, | |
187 | }; | |
188 | }, | |
9814a037 | 189 | }, |
b9c5fcf0 BW |
190 | }; |
191 | </script> |