Introduced ActionButton component as a replacement for HTML's button.
This commit is contained in:
parent
d159e22c50
commit
215f70db26
|
@ -41,34 +41,4 @@ a {
|
|||
outline: 0.1em solid $link-hover-color;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
padding: $button-padding;
|
||||
border-radius: $button-border-radius;
|
||||
border-width: $button-border-width;
|
||||
border-style: $button-border-style;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
@each $variant, $color in $variant-colors {
|
||||
&.#{$variant} {
|
||||
background-color: map-get($variant-text-colors, $variant);
|
||||
border-color: $color;
|
||||
color: $color;
|
||||
|
||||
&:hover, &:active {
|
||||
background-color: $color;
|
||||
border-color: $color;
|
||||
color: map-get($variant-text-colors, $variant);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background-color: $color;
|
||||
border-color: $page-background-color;
|
||||
color: map-get($variant-text-colors, $variant);
|
||||
outline: 0.1em solid $color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import {computed, defineProps} from "vue";
|
||||
import type {NodesFilter} from "@/types";
|
||||
import type {ComponentVariant, NodesFilter} from "@/types";
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
icon: string;
|
||||
variant: string;
|
||||
variant: ComponentVariant;
|
||||
value: number;
|
||||
link: string;
|
||||
filter?: NodesFilter;
|
||||
|
@ -29,7 +29,7 @@ const linkTarget = computed(() => {
|
|||
|
||||
<template>
|
||||
<RouterLink :to="linkTarget" :class="['statistics-card', 'statistics-card-' + variant]">
|
||||
<i :class="['fa', 'fa-' + icon]" aria-hidden="true" />
|
||||
<i :class="['fa', 'fa-' + icon]" aria-hidden="true"/>
|
||||
<dl>
|
||||
<dt>{{ title }}</dt>
|
||||
<dd>{{ value }}</dd>
|
||||
|
|
70
frontend/src/components/form/ActionButton.vue
Normal file
70
frontend/src/components/form/ActionButton.vue
Normal file
|
@ -0,0 +1,70 @@
|
|||
<script setup lang="ts">
|
||||
import type {ButtonSize, ComponentVariant} from "@/types";
|
||||
|
||||
interface Props {
|
||||
variant: ComponentVariant;
|
||||
size: ButtonSize;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "click"): void,
|
||||
}>();
|
||||
|
||||
function onClick() {
|
||||
emit("click");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button :class="[size, variant]" @click="onClick">
|
||||
<i :class="['fa', `fa-${icon}`]" aria-hidden="true"/>
|
||||
<slot></slot>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "../../scss/variables";
|
||||
|
||||
button {
|
||||
margin: 0.3em;
|
||||
|
||||
padding: $button-padding;
|
||||
border-radius: $button-border-radius;
|
||||
border-width: $button-border-width;
|
||||
border-style: $button-border-style;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
font-weight: 600;
|
||||
|
||||
@each $variant, $color in $variant-colors {
|
||||
&.#{$variant} {
|
||||
background-color: $color;
|
||||
border-color: $color;
|
||||
color: map-get($variant-text-colors, $variant);
|
||||
|
||||
&:hover, &:active {
|
||||
background-color: $page-background-color;
|
||||
border-color: $color;
|
||||
color: $color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background-color: $color;
|
||||
border-color: $page-background-color;
|
||||
color: map-get($variant-text-colors, $variant);
|
||||
outline: $color solid $button-outline-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@each $size, $font-size in $button-sizes {
|
||||
&.#{$size} {
|
||||
font-size: $font-size;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -17,11 +17,11 @@ $variant-colors: (
|
|||
info: #0097c4,
|
||||
);
|
||||
$variant-text-colors: (
|
||||
// primary: do not use, contrast too low
|
||||
success: $gray-darkest,
|
||||
warning: $gray-darkest,
|
||||
danger: $gray-darkest,
|
||||
info: $gray-darkest,
|
||||
primary: $black,
|
||||
success: $black,
|
||||
warning: $black,
|
||||
danger: $black,
|
||||
info: $black,
|
||||
);
|
||||
|
||||
$variant-color-primary: map-get($variant-colors, primary);
|
||||
|
@ -48,10 +48,17 @@ $input-border: 0.1em solid $page-background-color;
|
|||
$input-border-radius: 0.5em;
|
||||
$input-focus-outline: 0.1em solid $variant-color-info;
|
||||
|
||||
$button-margin: 0.3em;
|
||||
$button-padding: 0.25em 0.5em;
|
||||
$button-border-radius: $input-border-radius;
|
||||
$button-border-width: 0.1em;
|
||||
$button-border-width: 0.15em;
|
||||
$button-border-style: solid;
|
||||
$button-outline-width: 0.15em;
|
||||
$button-sizes: (
|
||||
small: 0.8em,
|
||||
medium: 1em,
|
||||
large: 1.15em,
|
||||
);
|
||||
|
||||
// Navigation
|
||||
$nav-bar-background-color: $gray-dark;
|
||||
|
|
|
@ -1 +1,15 @@
|
|||
export * from "./shared";
|
||||
|
||||
export enum ButtonSize {
|
||||
SMALL = "small",
|
||||
MEDIUM = "medium",
|
||||
LARGE = "large",
|
||||
}
|
||||
|
||||
export enum ComponentVariant {
|
||||
PRIMARY = "primary",
|
||||
SUCCESS = "success",
|
||||
WARNING = "warning",
|
||||
DANGER = "danger",
|
||||
INFO = "info",
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import StatisticsCard from "@/components/admin/StatisticsCard.vue";
|
||||
import {useStatisticsStore} from "@/stores/statistics";
|
||||
import {MonitoringState} from "@/types";
|
||||
import {ComponentVariant, MonitoringState} from "@/types";
|
||||
|
||||
const statistics = useStatisticsStore();
|
||||
|
||||
|
@ -20,14 +20,14 @@ refresh();
|
|||
<StatisticsCard
|
||||
title="Registrierte Knoten"
|
||||
icon="circle-o"
|
||||
variant="info"
|
||||
:variant="ComponentVariant.INFO"
|
||||
:value="statistics.getStatistics.nodes.registered"
|
||||
link="/admin/nodes"
|
||||
/>
|
||||
<StatisticsCard
|
||||
title="Mit hinterlegtem fastd-Key"
|
||||
icon="lock"
|
||||
variant="warning"
|
||||
:variant="ComponentVariant.WARNING"
|
||||
:value="statistics.getStatistics.nodes.withVPN"
|
||||
link="/admin/nodes"
|
||||
:filter="{hasKey: true}"
|
||||
|
@ -35,7 +35,7 @@ refresh();
|
|||
<StatisticsCard
|
||||
title="Mit Koordinaten"
|
||||
icon="map-marker"
|
||||
variant="success"
|
||||
:variant="ComponentVariant.SUCCESS"
|
||||
:value="statistics.getStatistics.nodes.withCoords"
|
||||
link="/admin/nodes"
|
||||
:filter="{hasCoords: true}"
|
||||
|
@ -43,7 +43,7 @@ refresh();
|
|||
<StatisticsCard
|
||||
title="Monitoring aktiv"
|
||||
icon="heartbeat"
|
||||
variant="success"
|
||||
:variant="ComponentVariant.SUCCESS"
|
||||
:value="statistics.getStatistics.nodes.monitoring.active"
|
||||
link="/admin/nodes"
|
||||
:filter="{monitoringState: MonitoringState.ACTIVE}"
|
||||
|
@ -51,7 +51,7 @@ refresh();
|
|||
<StatisticsCard
|
||||
title="Monitoring noch nicht bestätigt"
|
||||
icon="envelope"
|
||||
variant="danger"
|
||||
:variant="ComponentVariant.DANGER"
|
||||
:value="statistics.getStatistics.nodes.monitoring.pending"
|
||||
link="/admin/nodes"
|
||||
:filter="{monitoringState: MonitoringState.PENDING}"
|
||||
|
|
|
@ -2,28 +2,14 @@
|
|||
import {useNodesStore} from "@/stores/nodes";
|
||||
import {onMounted, type PropType, ref, watch} from "vue";
|
||||
import type {DomainSpecificNodeResponse, MAC, NodesFilter, SearchTerm} from "@/types";
|
||||
import {NodeSortField, SortDirection} from "@/types";
|
||||
import {ButtonSize, ComponentVariant, NodeSortField, SortDirection} from "@/types";
|
||||
import Pager from "@/components/Pager.vue";
|
||||
import ActionButton from "@/components/form/ActionButton.vue";
|
||||
import LoadingContainer from "@/components/LoadingContainer.vue";
|
||||
import NodesFilterPanel from "@/components/nodes/NodesFilterPanel.vue";
|
||||
import {SortTH} from "@/components/table/SortTH.vue";
|
||||
import router from "@/router";
|
||||
|
||||
function debug(...args: any[]): void {
|
||||
console.debug("==================================================================");
|
||||
console.debug("AdminNodesVue:", ...args);
|
||||
console.table({
|
||||
filter: JSON.stringify(props.filter),
|
||||
searchTerm: props.searchTerm,
|
||||
sortDirection: props.sortDirection,
|
||||
sortField: props.sortField,
|
||||
});
|
||||
console.debug("==================================================================");
|
||||
console.debug();
|
||||
}
|
||||
|
||||
debug("init page");
|
||||
|
||||
const NODE_PER_PAGE = 50;
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
@ -145,18 +131,22 @@ watch(props, async () => {
|
|||
@changePage="refresh"/>
|
||||
|
||||
<div class="actions">
|
||||
<button
|
||||
<ActionButton
|
||||
v-if="redactFieldsByDefault"
|
||||
class="warning"
|
||||
:variant="ComponentVariant.WARNING"
|
||||
:size="ButtonSize.SMALL"
|
||||
icon="eye"
|
||||
@click="redactAllFields(false)">
|
||||
Sensible Daten einblenden
|
||||
</button>
|
||||
<button
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
v-if="!redactFieldsByDefault"
|
||||
class="success"
|
||||
:variant="ComponentVariant.SUCCESS"
|
||||
:size="ButtonSize.SMALL"
|
||||
icon="eye-slash"
|
||||
@click="redactAllFields(true)">
|
||||
Sensible Daten ausblenden
|
||||
</button>
|
||||
</ActionButton>
|
||||
</div>
|
||||
|
||||
<LoadingContainer :loading="loading">
|
||||
|
|
|
@ -1,12 +1,38 @@
|
|||
<script setup lang="ts">
|
||||
import ActionButton from "@/components/form/ActionButton.vue";
|
||||
import {ButtonSize, ComponentVariant} from "@/types";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h2>Willkommen!</h2>
|
||||
|
||||
<p>Du hast einen neuen Freifunk Hamburg Router (Knoten), den Du in Betrieb nehmen möchtest? Du hast schon einen Knoten in Betrieb und möchtest seine Daten ändern? Oder Du möchtest einen Knoten, der nicht mehr in Betrieb ist löschen? Dann bist Du hier richtig!</p>
|
||||
<p>Du hast einen neuen Freifunk Hamburg Router (Knoten), den Du in Betrieb nehmen möchtest? Du hast schon einen
|
||||
Knoten in Betrieb und möchtest seine Daten ändern? Oder Du möchtest einen Knoten, der nicht mehr in Betrieb
|
||||
ist löschen? Dann bist Du hier richtig!</p>
|
||||
|
||||
<div class="actions">
|
||||
<ActionButton
|
||||
:variant="ComponentVariant.INFO"
|
||||
:size="ButtonSize.LARGE"
|
||||
icon="dot-circle-o">
|
||||
Neuen Knoten anmelden
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
:variant="ComponentVariant.PRIMARY"
|
||||
:size="ButtonSize.LARGE"
|
||||
icon="pencil">
|
||||
Knotendaten ändern
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
:variant="ComponentVariant.WARNING"
|
||||
:size="ButtonSize.LARGE"
|
||||
icon="trash">
|
||||
Knoten löschen
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue