diff --git a/assets/App.vue b/assets/App.vue index f5c13664..52e29b64 100644 --- a/assets/App.vue +++ b/assets/App.vue @@ -19,8 +19,9 @@ -
- +
+ +
@@ -35,6 +36,11 @@ export default { showNav: false }; }, + metaInfo() { + return { + title: this.title + }; + }, async created() { await this.fetchContainerList(); this.title = `${this.containers.length} containers - Dozzle`; @@ -80,6 +86,7 @@ aside { overflow: auto; } } + @media screen and (max-width: 768px) { & { position: sticky; diff --git a/assets/components/ScrollbarNotification.vue b/assets/components/ScrollbarNotification.vue index b863941a..1debe0cc 100644 --- a/assets/components/ScrollbarNotification.vue +++ b/assets/components/ScrollbarNotification.vue @@ -44,7 +44,7 @@ export default { } }, watch: { - messages(newValue, oldValue) { + messages() { if (this.visible) { this.hasNew = true; } else { diff --git a/assets/main.js b/assets/main.js index 6ac8eb13..506353c8 100644 --- a/assets/main.js +++ b/assets/main.js @@ -1,12 +1,12 @@ import Vue from "vue"; import VueRouter from "vue-router"; -import vueHeadful from "vue-headful"; +import Meta from "vue-meta"; import App from "./App.vue"; import Container from "./pages/Container.vue"; import Index from "./pages/Index.vue"; Vue.use(VueRouter); -Vue.component("vue-headful", vueHeadful); +Vue.use(Meta); const routes = [ { diff --git a/assets/pages/Container.vue b/assets/pages/Container.vue index c1ad8fa3..9a9d6854 100644 --- a/assets/pages/Container.vue +++ b/assets/pages/Container.vue @@ -1,12 +1,15 @@ @@ -38,9 +41,23 @@ export default { data() { return { messages: [], - title: "" + showHelp: false, + title: "", + filter: "" }; }, + metaInfo() { + return { + title: this.title, + titleTemplate: "%s - Dozzle" + }; + }, + mounted() { + window.addEventListener("keydown", this.onKeyDown); + }, + destroyed() { + window.removeEventListener("keydown", this.onKeyDown); + }, created() { this.loadLogs(this.id); }, @@ -67,6 +84,34 @@ export default { es = new EventSource(`${BASE_PATH}/api/logs/stream?id=${id}`); es.onmessage = e => this.messages.push(parseMessage(e.data)); this.title = `${this.name} - Dozzle`; + }, + onKeyDown(e) { + if ((e.metaKey || e.ctrlKey) && e.key === "f") { + this.showHelp = true; + this.$nextTick(() => this.$refs.filter.focus()); + e.preventDefault(); + } else if ((e.metaKey || e.ctrlKey) && e.key === "k") { + this.messages = []; + } else if (e.key === "Escape") { + this.showHelp = false; + this.filter = ""; + } + } + }, + computed: { + filtered() { + if (this.filter) { + return this.messages + .filter(d => d.message.includes(this.filter)) + .map(d => { + return { + ...d, + message: d.message.replace(this.filter, text => `${text}`) + }; + }); + } else { + return this.messages; + } } } }; @@ -95,4 +140,16 @@ export default { .text { white-space: pre-wrap; } + +.search { + width: 300px; + position: fixed; + right: 1em; + top: 1em; +} + +/deep/ mark { + border-radius: 2px; + background-color: #ffdd57; +} diff --git a/package-lock.json b/package-lock.json index d4f442e4..df66f948 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,17 +14,17 @@ } }, "@babel/core": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.0.tgz", - "integrity": "sha512-Dzl7U0/T69DFOTwqz/FJdnOSWS57NpjNfCwMKHABr589Lg8uX1RrlBIJ7L5Dubt/xkLsx0xH5EBFzlBVes1ayA==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.3.tgz", + "integrity": "sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "@babel/generator": "^7.4.0", - "@babel/helpers": "^7.4.0", - "@babel/parser": "^7.4.0", + "@babel/helpers": "^7.4.3", + "@babel/parser": "^7.4.3", "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.0", + "@babel/traverse": "^7.4.3", "@babel/types": "^7.4.0", "convert-source-map": "^1.1.0", "debug": "^4.1.0", @@ -35,6 +35,40 @@ "source-map": "^0.5.0" }, "dependencies": { + "@babel/helpers": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.3.tgz", + "integrity": "sha512-BMh7X0oZqb36CfyhvtbSmcWc3GXocfxv3yNsAEuM0l+fAqSO22rQrUpijr3oE/10jCTrB6/0b9kzmG4VetCj8Q==", + "dev": true, + "requires": { + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0" + } + }, + "@babel/parser": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", + "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==", + "dev": true + }, + "@babel/traverse": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.3.tgz", + "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/types": "^7.4.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -643,9 +677,9 @@ } }, "@babel/plugin-transform-runtime": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.4.0.tgz", - "integrity": "sha512-1uv2h9wnRj98XX3g0l4q+O3jFM6HfayKup7aIu4pnnlzGz0H+cYckGBC74FZIWJXJSXAmeJ9Yu5Gg2RQpS4hWg==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.4.3.tgz", + "integrity": "sha512-7Q61bU+uEI7bCUFReT1NKn7/X6sDQsZ7wL1sJ9IYMAO7cI+eg6x9re1cEw2fCRMbbTVyoeUKWSV1M6azEfKCfg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -933,9 +967,9 @@ "dev": true }, "@vue/component-compiler-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz", - "integrity": "sha512-IHjxt7LsOFYc0DkTncB7OXJL7UzwOLPPQCfEUNyxL2qt+tF12THV+EO33O1G2Uk4feMSWua3iD39Itszx0f0bw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.0.0.tgz", + "integrity": "sha512-am+04/0UX7ektcmvhYmrf84BDVAD8afFOf4asZjN84q8xzxFclbk5x0MtxuKGfp+zjN5WWPJn3fjFAWtDdIGSw==", "dev": true, "requires": { "consolidate": "^0.15.1", @@ -949,17 +983,6 @@ "vue-template-es2015-compiler": "^1.9.0" }, "dependencies": { - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "dev": true, - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, "prettier": { "version": "1.16.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.3.tgz", @@ -1377,9 +1400,9 @@ "dev": true }, "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", + "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==", "dev": true }, "bn.js": { @@ -2517,6 +2540,11 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "deepmerge": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.2.0.tgz", + "integrity": "sha512-6+LuZGU7QCNUnAJyX8cIrlzoEgggTM6B7mm+znKOX4t5ltluT9KLjN6g61ECMS0LTsLW7yDpNoxhix5FZcrIow==" + }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -4039,11 +4067,6 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "headful": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/headful/-/headful-1.0.3.tgz", - "integrity": "sha512-vF9Vfddn1QWmziliht2mji6ayI78+hUuSC+Kt0GEqLw/51zWgi1KF7oLtIQf3nlkg8sQQOlznkkIaF4W9lIt9w==" - }, "hex-color-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", @@ -5018,6 +5041,11 @@ "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", "dev": true }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -5036,6 +5064,11 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, + "lodash.uniqueid": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.uniqueid/-/lodash.uniqueid-4.0.1.tgz", + "integrity": "sha1-MmjyanyI5PSxdY1nknGBTjH6WyY=" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -5093,9 +5126,9 @@ } }, "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -5515,8 +5548,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -6703,9 +6735,9 @@ "dev": true }, "prettier": { - "version": "1.16.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", - "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.17.0.tgz", + "integrity": "sha512-sXe5lSt2WQlCbydGETgfm1YBShgOX4HxQkFPvbxkcwgDvGDeqVau8h+12+lmSVlP3rHPz0oavfddSZg/q+Szjw==", "dev": true }, "private": { @@ -6853,7 +6885,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -7170,9 +7202,9 @@ } }, "sass": { - "version": "1.17.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.17.3.tgz", - "integrity": "sha512-S4vJawbrNUxJUBiHLXPYUKZCoO6cvq3/3ZFBV66a+PafTxcDEFJB+FHLDFl0P+rUfha/703ajEXMuGTYhJESkQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.18.0.tgz", + "integrity": "sha512-Mc579V+BhH693tqt+lvph+gmRqmC6BjtsEVsjkW1944DEA5a0wPuCi781hL3fY4EDuqZnEVPbu42CZRywwE97g==", "dev": true, "requires": { "chokidar": "^2.0.0" @@ -8339,24 +8371,27 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz", "integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==" }, - "vue-headful": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/vue-headful/-/vue-headful-2.0.1.tgz", - "integrity": "sha512-h2G/jXCi2hAx6O3gwWN8uTj1eQlSKNHgvkCVZcokZneGczWCRghAUCFYrOvZQM+F+SyFB3YXqoI62rE0Sc8QsA==", - "requires": { - "headful": "^1.0.3" - } - }, "vue-hot-reload-api": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz", "integrity": "sha512-KmvZVtmM26BQOMK1rwUZsrqxEGeKiYSZGA7SNWE6uExx8UX/cj9hq2MRV/wWC3Cq6AoeDGk57rL9YMFRel/q+g==", "dev": true }, + "vue-meta": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vue-meta/-/vue-meta-1.6.0.tgz", + "integrity": "sha512-LLHejsOYbJiSEDSgZvjHB3fFY7lUxsDFLkuSqf5eBohEvhhddBTOHa3heoFTcI5sxsZSZt26uUzoLVe4CT6Y4A==", + "requires": { + "deepmerge": "^3.2.0", + "lodash.isplainobject": "^4.0.6", + "lodash.uniqueid": "^4.0.1", + "object-assign": "^4.1.1" + } + }, "vue-router": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.2.tgz", - "integrity": "sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg==" + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.4.tgz", + "integrity": "sha512-wjirAFeMR53FFTRIM2ofLKH5BJte6Q9+MUiOj6fLzqhgerjVyQVeMmvgiQDslPJJHSqFfQ559EDvIi0lA1Lr6g==" }, "vue-template-compiler": { "version": "2.6.10", diff --git a/package.json b/package.json index dc277c1d..1a4217e3 100644 --- a/package.json +++ b/package.json @@ -27,19 +27,19 @@ "bulma": "^0.7.4", "date-fns": "^2.0.0-alpha.25", "vue": "^2.6.10", - "vue-headful": "^2.0.1", - "vue-router": "^3.0.2" + "vue-meta": "^1.6.0", + "vue-router": "^3.0.4" }, "devDependencies": { - "@babel/core": "^7.4.0", - "@babel/plugin-transform-runtime": "^7.4.0", - "@vue/component-compiler-utils": "^2.6.0", + "@babel/core": "^7.4.3", + "@babel/plugin-transform-runtime": "^7.4.3", + "@vue/component-compiler-utils": "^3.0.0", "concurrently": "^4.1.0", "husky": "^1.3.1", "lint-staged": "^8.1.5", "parcel-bundler": "^1.12.3", - "prettier": "^1.16.4", - "sass": "^1.17.3", + "prettier": "^1.17.0", + "sass": "^1.18.0", "vue-hot-reload-api": "^2.3.3", "vue-template-compiler": "^2.6.10" },