1
0
mirror of https://github.com/amir20/dozzle.git synced 2025-12-21 21:33:18 +01:00

Updates icons to use builtin SVGs instead for no external depend… (#354)

* Use iconmoon

* Adds icons

* Use go to update BASE

* Changes more icons

* Uses html inline

* Reverts css changes

* Fixes icons

* Fixes tests and icons

* Adds --rm to int tests

* Fixes unit tests
This commit is contained in:
Amir Raminfar
2020-04-09 11:06:04 -07:00
committed by GitHub
parent 6dc0c93588
commit 62ab55b1e4
21 changed files with 150 additions and 35 deletions

View File

@@ -5,3 +5,4 @@ dist
.git .git
static static
integration integration
demo.gif

3
.htmlnanorc.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = {
minifySvg: false,
};

3
.prettierrc.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = {
printWidth: 120,
};

View File

@@ -1,3 +0,0 @@
{
"printWidth": 120
}

View File

@@ -9,9 +9,13 @@ WORKDIR /build
COPY package*.json yarn.lock ./ COPY package*.json yarn.lock ./
RUN yarn install --network-timeout 1000000 RUN yarn install --network-timeout 1000000
# Copy config files
COPY .* ./
# Copy assets to build # Copy assets to build
COPY assets ./assets COPY assets ./assets
# Do the build # Do the build
RUN yarn build RUN yarn build

View File

@@ -8,7 +8,7 @@ const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
describe("<App />", () => { describe("<App />", () => {
const stubs = { RouterLink: RouterLinkStub, "router-view": true, "ion-icon": true }; const stubs = { RouterLink: RouterLinkStub, "router-view": true, icon: true };
let store; let store;
beforeEach(() => { beforeEach(() => {
@@ -17,18 +17,18 @@ describe("<App />", () => {
const state = { const state = {
containers: [ containers: [
{ id: "abc", name: "Test 1" }, { id: "abc", name: "Test 1" },
{ id: "xyz", name: "Test 2" } { id: "xyz", name: "Test 2" },
], ],
settings: { menuWidth: 15 } settings: { menuWidth: 15 },
}; };
const actions = { const actions = {
FETCH_CONTAINERS: () => Promise.resolve() FETCH_CONTAINERS: () => Promise.resolve(),
}; };
store = new Vuex.Store({ store = new Vuex.Store({
state, state,
actions actions,
}); });
}); });

View File

@@ -31,7 +31,7 @@
v-if="!isMobile" v-if="!isMobile"
> >
<span class="icon"> <span class="icon">
<ion-icon :name="collapseNav ? 'arrow-dropright' : 'arrow-dropleft'" size="large"></ion-icon> <icon :name="collapseNav ? 'chevron-right' : 'chevron-left'"></icon>
</span> </span>
</button> </button>
</main> </main>
@@ -47,10 +47,12 @@ import SideMenu from "./components/SideMenu";
import MobileMenu from "./components/MobileMenu"; import MobileMenu from "./components/MobileMenu";
import Search from "./components/Search"; import Search from "./components/Search";
import ContainerTitle from "./components/ContainerTitle"; import ContainerTitle from "./components/ContainerTitle";
import Icon from "./components/Icon";
export default { export default {
name: "App", name: "App",
components: { components: {
Icon,
LogViewerWithSource, LogViewerWithSource,
SideMenu, SideMenu,
MobileMenu, MobileMenu,

View File

@@ -45,9 +45,8 @@ exports[`<App /> renders correctly 1`] = `
<span <span
class="icon" class="icon"
> >
<ion-icon-stub <icon-stub
name="arrow-dropleft" name="chevron-left"
size="large"
/> />
</span> </span>
</button> </button>

View File

@@ -0,0 +1,33 @@
<template>
<svg class="icomoon" :class="['icon-' + name]">
<use :href="'#icon-' + name"></use>
</svg>
</template>
<script>
export default {
functional: true,
props: {
name: {
required: true,
type: String,
},
},
name: "Icon",
};
</script>
<style lang="scss" scoped>
.icomoon {
display: inline-block;
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
.icon:not(.keep-size) & {
width: 100%;
height: 100%;
}
}
</style>

View File

@@ -15,7 +15,7 @@
@click="scrollToBottom('instant')" @click="scrollToBottom('instant')"
v-show="paused" v-show="paused"
> >
<ion-icon name="download"></ion-icon> <icon name="download"></icon>
</button> </button>
</transition> </transition>
</div> </div>
@@ -23,6 +23,8 @@
</template> </template>
<script> <script>
import Icon from "./Icon";
export default { export default {
props: { props: {
scrollable: { scrollable: {
@@ -30,6 +32,9 @@ export default {
default: true, default: true,
}, },
}, },
components: {
Icon,
},
name: "ScrollableView", name: "ScrollableView",
data() { data() {
return { return {

View File

@@ -10,8 +10,8 @@
v-model="filter" v-model="filter"
@keyup.esc="resetSearch()" @keyup.esc="resetSearch()"
/> />
<span class="icon is-small is-left"> <span class="icon is-left">
<ion-icon name="search"></ion-icon> <icon name="search"></icon>
</span> </span>
</p> </p>
</div> </div>
@@ -24,10 +24,14 @@
<script> <script>
import { mapActions, mapState } from "vuex"; import { mapActions, mapState } from "vuex";
import hotkeys from "hotkeys-js"; import hotkeys from "hotkeys-js";
import Icon from "./Icon";
export default { export default {
props: [], props: [],
name: "Search", name: "Search",
components: {
Icon,
},
data() { data() {
return { return {
showSearch: false, showSearch: false,
@@ -80,4 +84,8 @@ export default {
.delete { .delete {
margin-left: 1em; margin-left: 1em;
} }
.icon {
padding: 10px 3px;
}
</style> </style>

View File

@@ -10,7 +10,9 @@
active-class="is-active" active-class="is-active"
class="button is-small is-rounded is-settings-control" class="button is-small is-rounded is-settings-control"
> >
<span class="icon"><ion-icon name="settings" size="large"></ion-icon></span> <span class="icon">
<icon name="cog"></icon>
</span>
</router-link> </router-link>
</div> </div>
</div> </div>
@@ -28,7 +30,7 @@
class="icon is-small will-append-container" class="icon is-small will-append-container"
:class="{ 'is-active': activeContainersById[item.id] }" :class="{ 'is-active': activeContainersById[item.id] }"
> >
<ion-icon name="ios-add-circle"></ion-icon> <icon name="pin"></icon>
</span> </span>
{{ item.name }} {{ item.name }}
</div> </div>
@@ -41,9 +43,14 @@
<script> <script>
import { mapActions, mapGetters, mapState } from "vuex"; import { mapActions, mapGetters, mapState } from "vuex";
import Icon from "./Icon";
export default { export default {
props: [], props: [],
name: "SideMenu", name: "SideMenu",
components: {
Icon,
},
data() { data() {
return {}; return {};
}, },

View File

@@ -12,11 +12,62 @@
window["BASE_PATH"] = "{{ .Base }}"; window["BASE_PATH"] = "{{ .Base }}";
window["VERSION"] = "{{ .Version }}"; window["VERSION"] = "{{ .Version }}";
</script> </script>
<script type="module" src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons/ionicons.esm.js"></script>
<script nomodule="" src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons/ionicons.js"></script>
</head> </head>
<body> <body>
<svg
aria-hidden="true"
style="position: absolute; width: 0; height: 0; overflow: hidden;"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<defs>
<symbol id="icon-check" viewBox="0 0 24 24">
<path
d="M19.293 5.293l-10.293 10.293-4.293-4.293c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414l5 5c0.391 0.391 1.024 0.391 1.414 0l11-11c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0z"
></path>
</symbol>
<symbol id="icon-chevron-down" viewBox="0 0 24 24">
<path
d="M5.293 9.707l6 6c0.391 0.391 1.024 0.391 1.414 0l6-6c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-5.293 5.293-5.293-5.293c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414z"
></path>
</symbol>
<symbol id="icon-chevron-left" viewBox="0 0 24 24">
<path
d="M15.707 17.293l-5.293-5.293 5.293-5.293c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-6 6c-0.391 0.391-0.391 1.024 0 1.414l6 6c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414z"
></path>
</symbol>
<symbol id="icon-chevron-right" viewBox="0 0 24 24">
<path
d="M9.707 18.707l6-6c0.391-0.391 0.391-1.024 0-1.414l-6-6c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414l5.293 5.293-5.293 5.293c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0z"
></path>
</symbol>
<symbol id="icon-chevrons-down" viewBox="0 0 24 24">
<path
d="M6.293 13.707l5 5c0.391 0.391 1.024 0.391 1.414 0l5-5c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-4.293 4.293-4.293-4.293c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414zM6.293 6.707l5 5c0.391 0.391 1.024 0.391 1.414 0l5-5c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-4.293 4.293-4.293-4.293c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414z"
></path>
</symbol>
<symbol id="icon-download" viewBox="0 0 24 24">
<path d="M15.6 9.6v-7.2h-7.2v7.2h-6l9.6 9.6 9.6-9.6h-6zM0 21.6h24v2.4h-24v-2.4z"></path>
</symbol>
<symbol id="icon-pin" viewBox="0 0 24 24">
<path
d="M13.2 14.4h7.2v-1.2l-3.6-1.2v-9.6l3.6-1.2v-1.2h-16.8v1.2l3.6 1.2v9.6l-3.6 1.2v1.2h7.2v8.4l1.2 1.2 1.2-1.2v-8.4z"
></path>
</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">
<path
d="M15.48 17.184c-1.608 1.259-3.66 2.019-5.889 2.019-5.302 0-9.6-4.298-9.6-9.6s4.298-9.6 9.6-9.6c5.302 0 9.6 4.298 9.6 9.6 0 2.229-0.76 4.281-2.035 5.91l0.016-0.021 6.42 6.396-1.704 1.704-6.396-6.408zM9.6 16.8c3.976 0 7.2-3.224 7.2-7.2s-3.224-7.2-7.2-7.2v0c-3.976 0-7.2 3.224-7.2 7.2s3.224 7.2 7.2 7.2v0z"
></path>
</symbol>
<symbol id="icon-cog" viewBox="0 0 24 24">
<path
d="M21.886 14.303c-1.259-2.181-0.502-4.976 1.691-6.246l-2.358-4.085c-0.674 0.395-1.457 0.622-2.293 0.622-2.52 0-4.563-2.057-4.563-4.594h-4.717c0.006 0.783-0.189 1.577-0.608 2.303-1.259 2.181-4.058 2.923-6.255 1.658l-2.358 4.085c0.679 0.386 1.267 0.951 1.685 1.675 1.257 2.178 0.504 4.967-1.681 6.24l2.358 4.085c0.671-0.391 1.451-0.615 2.283-0.615 2.512 0 4.55 2.044 4.563 4.569h4.717c-0.002-0.775 0.194-1.56 0.609-2.279 1.257-2.177 4.049-2.92 6.244-1.664l2.358-4.085c-0.675-0.386-1.258-0.949-1.674-1.669zM12 16.859c-2.684 0-4.859-2.176-4.859-4.859s2.176-4.859 4.859-4.859c2.684 0 4.859 2.176 4.859 4.859s-2.176 4.859-4.859 4.859z"
></path>
</symbol>
</defs>
</svg>
<div id="app"></div> <div id="app"></div>
<script src="main.js"></script> <script src="main.js"></script>
</body> </body>

View File

@@ -13,35 +13,33 @@ Vue.use(Meta);
Vue.use(Dropdown); Vue.use(Dropdown);
Vue.use(Switch); Vue.use(Switch);
Vue.config.ignoredElements = [/^ion-/];
const routes = [ const routes = [
{ {
path: "/", path: "/",
component: Index, component: Index,
name: "default" name: "default",
}, },
{ {
path: "/container/:id", path: "/container/:id",
component: Container, component: Container,
name: "container", name: "container",
props: true props: true,
}, },
{ {
path: "/settings", path: "/settings",
component: Settings, component: Settings,
name: "settings" name: "settings",
} },
]; ];
const router = new VueRouter({ const router = new VueRouter({
mode: "history", mode: "history",
base: BASE_PATH + "/", base: BASE_PATH + "/",
routes routes,
}); });
new Vue({ new Vue({
router, router,
store, store,
render: h => h(App) render: (h) => h(App),
}).$mount("#app"); }).$mount("#app");

View File

@@ -38,12 +38,12 @@
<b-dropdown v-model="size" aria-role="list" style="margin: -8px 10px 0;"> <b-dropdown v-model="size" aria-role="list" style="margin: -8px 10px 0;">
<button class="button is-primary" type="button" slot="trigger"> <button class="button is-primary" type="button" slot="trigger">
<span class="is-capitalized">{{ size }}</span> <span class="is-capitalized">{{ size }}</span>
<span class="icon"><ion-icon name="ios-arrow-down"></ion-icon></span> <span class="icon"><icon name="chevron-down"></icon></span>
</button> </button>
<b-dropdown-item :value="value" aria-role="listitem" v-for="value in ['small', 'medium', 'large']"> <b-dropdown-item :value="value" aria-role="listitem" v-for="value in ['small', 'medium', 'large']">
<div class="media"> <div class="media">
<span class="icon"> <span class="icon keep-size">
<ion-icon name="checkmark" v-if="value == size"></ion-icon> <icon name="check" v-if="value == size"></icon>
</span> </span>
<div class="media-content"> <div class="media-content">
<h3 class="is-capitalized">{{ value }}</h3> <h3 class="is-capitalized">{{ value }}</h3>
@@ -60,11 +60,14 @@
import gt from "semver/functions/gt"; import gt from "semver/functions/gt";
import valid from "semver/functions/valid"; import valid from "semver/functions/valid";
import { mapActions, mapState } from "vuex"; import { mapActions, mapState } from "vuex";
import Icon from "../components/Icon";
export default { export default {
props: [], props: [],
name: "Settings", name: "Settings",
components: {}, components: {
Icon,
},
data() { data() {
return { return {
currentVersion: VERSION, currentVersion: VERSION,

View File

@@ -72,3 +72,4 @@ html.has-custom-scrollbars {
border-color: transparent; border-color: transparent;
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -1,6 +1,6 @@
module.exports = { module.exports = {
launch: { launch: {
headless: true, headless: process.env.HEADLESS !== "false",
defaultViewport: { width: 1920, height: 1200 }, defaultViewport: { width: 1920, height: 1200 },
args: ["--no-sandbox", "--disable-setuid-sandbox"], args: ["--no-sandbox", "--disable-setuid-sandbox"],
executablePath: process.env.CHROME_EXE_PATH || "", executablePath: process.env.CHROME_EXE_PATH || "",

View File

@@ -12,7 +12,7 @@
"clean": "rm -rf static/ a_main-packr.go", "clean": "rm -rf static/ a_main-packr.go",
"release": "release-it", "release": "release-it",
"test": "jest", "test": "jest",
"integration": "docker-compose -f integration/docker-compose.test.yml run integration" "integration": "docker-compose -f integration/docker-compose.test.yml run --rm integration"
}, },
"repository": { "repository": {
"type": "git", "type": "git",