chore(lite): use injection keys (#6898)

Using injection keys for `provide`/`inject` to prevent errors and code
repetition.
This commit is contained in:
Thierry Goettelmann 2023-07-11 14:56:03 +02:00 committed by GitHub
parent ce2b918a29
commit c705051a89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 321 additions and 149 deletions

View File

@ -11,7 +11,8 @@
</template>
<script lang="ts" setup>
import { type ComputedRef, computed, inject } from "vue";
import { IK_TAB_BAR_DISABLED } from "@/types/injection-keys";
import { computed, inject } from "vue";
import type { RouteLocationRaw } from "vue-router";
import UiTab from "@/components/ui/UiTab.vue";
@ -20,8 +21,8 @@ defineProps<{
disabled?: boolean;
}>();
const isTabBarDisabled = inject<ComputedRef<boolean>>(
"isTabBarDisabled",
const isTabBarDisabled = inject(
IK_TAB_BAR_DISABLED,
computed(() => false)
);
</script>

View File

@ -21,7 +21,8 @@
<script lang="ts" setup>
import { percent } from "@/libs/utils";
import { computed, type ComputedRef, inject } from "vue";
import { IK_CHART_VALUE_FORMATTER } from "@/types/injection-keys";
import { computed, inject } from "vue";
const props = defineProps<{
total: number;
@ -34,9 +35,10 @@ const freePercent = computed(() =>
percent(props.total - props.used, props.total)
);
const valueFormatter = inject("valueFormatter") as ComputedRef<
(value: number) => string
>;
const valueFormatter = inject(
IK_CHART_VALUE_FORMATTER,
computed(() => (value) => value.toString())
);
</script>
<style lang="postcss" scoped>

View File

@ -6,11 +6,11 @@
</template>
<script lang="ts" setup>
import UiCard from "@/components/ui/UiCard.vue";
import type { LinearChartData, ValueFormatter } from "@/types/chart";
import { IK_CHART_VALUE_FORMATTER } from "@/types/injection-keys";
import { utcFormat } from "d3-time-format";
import type { EChartsOption } from "echarts";
import { computed, provide } from "vue";
import VueCharts from "vue-echarts";
import type { LinearChartData } from "@/types/chart";
import { LineChart } from "echarts/charts";
import {
GridComponent,
@ -20,8 +20,8 @@ import {
} from "echarts/components";
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import type { OptionDataValue } from "echarts/types/src/util/types";
import UiCard from "@/components/ui/UiCard.vue";
import { computed, provide } from "vue";
import VueCharts from "vue-echarts";
const Y_AXIS_MAX_VALUE = 200;
@ -29,23 +29,23 @@ const props = defineProps<{
title?: string;
subtitle?: string;
data: LinearChartData;
valueFormatter?: (value: number) => string;
valueFormatter?: ValueFormatter;
maxValue?: number;
}>();
const valueFormatter = computed(() => {
const valueFormatter = computed<ValueFormatter>(() => {
const formatter = props.valueFormatter;
return (value: OptionDataValue | OptionDataValue[]) => {
if (formatter) {
return formatter(value as number);
return (value) => {
if (formatter === undefined) {
return value.toString();
}
return value.toString();
return formatter(value);
};
});
provide("valueFormatter", valueFormatter);
provide(IK_CHART_VALUE_FORMATTER, valueFormatter);
use([
CanvasRenderer,
@ -65,7 +65,7 @@ const option = computed<EChartsOption>(() => ({
data: props.data.map((series) => series.label),
},
tooltip: {
valueFormatter: valueFormatter.value,
valueFormatter: (v) => valueFormatter.value(v as number),
},
xAxis: {
type: "time",

View File

@ -19,7 +19,12 @@
</template>
<script lang="ts" setup>
import { type HTMLAttributes, computed, inject, ref } from "vue";
import {
IK_FORM_HAS_LABEL,
IK_FORM_LABEL_DISABLED,
IK_CHECKBOX_TYPE,
} from "@/types/injection-keys";
import { type HTMLAttributes, computed, inject } from "vue";
import { faCheck, faCircle, faMinus } from "@fortawesome/free-solid-svg-icons";
import { useVModel } from "@vueuse/core";
import UiIcon from "@/components/ui/icon/UiIcon.vue";
@ -37,9 +42,15 @@ const emit = defineEmits<{
}>();
const value = useVModel(props, "modelValue", emit);
const type = inject<"checkbox" | "radio" | "toggle">("inputType", "checkbox");
const hasLabel = inject("hasLabel", false);
const isLabelDisabled = inject("isLabelDisabled", ref(false));
const type = inject(IK_CHECKBOX_TYPE, "checkbox");
const hasLabel = inject(
IK_FORM_HAS_LABEL,
computed(() => false)
);
const isLabelDisabled = inject(
IK_FORM_LABEL_DISABLED,
computed(() => false)
);
const icon = computed(() => {
if (type !== "checkbox") {
return faCircle;

View File

@ -48,19 +48,24 @@
</template>
<script lang="ts" setup>
import UiIcon from "@/components/ui/icon/UiIcon.vue";
import type { Color } from "@/types";
import {
IK_FORM_INPUT_COLOR,
IK_FORM_LABEL_DISABLED,
IK_INPUT_TYPE,
} from "@/types/injection-keys";
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
import { faAngleDown } from "@fortawesome/free-solid-svg-icons";
import { useTextareaAutosize, useVModel } from "@vueuse/core";
import {
type HTMLAttributes,
computed,
type HTMLAttributes,
inject,
nextTick,
ref,
watch,
} from "vue";
import type { Color } from "@/types";
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
import { faAngleDown } from "@fortawesome/free-solid-svg-icons";
import { useTextareaAutosize, useVModel } from "@vueuse/core";
import UiIcon from "@/components/ui/icon/UiIcon.vue";
defineOptions({ inheritAttrs: false });
@ -90,17 +95,20 @@ const value = useVModel(props, "modelValue", emit);
const isEmpty = computed(
() => props.modelValue == null || String(props.modelValue).trim() === ""
);
const inputType = inject("inputType", "input");
const isLabelDisabled = inject("isLabelDisabled", ref(false));
const inputType = inject(IK_INPUT_TYPE, "input");
const isLabelDisabled = inject(
IK_FORM_LABEL_DISABLED,
computed(() => false)
);
const parentColor = inject(
"color",
IK_FORM_INPUT_COLOR,
computed(() => undefined)
);
const wrapperClass = computed(() => [
`form-${inputType}`,
{
disabled: props.disabled || isLabelDisabled.value,
disabled: props.disabled === true || isLabelDisabled.value,
empty: isEmpty.value,
},
]);

View File

@ -17,9 +17,14 @@
</template>
<script lang="ts" setup>
import { computed, provide, useSlots } from "vue";
import { faCircleExclamation } from "@fortawesome/free-solid-svg-icons";
import UiIcon from "@/components/ui/icon/UiIcon.vue";
import {
IK_FORM_HAS_LABEL,
IK_FORM_INPUT_COLOR,
IK_FORM_LABEL_DISABLED,
} from "@/types/injection-keys";
import { faCircleExclamation } from "@fortawesome/free-solid-svg-icons";
import { computed, provide, useSlots } from "vue";
const slots = useSlots();
@ -29,10 +34,14 @@ const props = defineProps<{
warning?: string;
}>();
provide("hasLabel", slots.label !== undefined);
provide(
"isLabelDisabled",
computed(() => props.disabled)
IK_FORM_HAS_LABEL,
computed(() => slots.label !== undefined)
);
provide(
IK_FORM_LABEL_DISABLED,
computed(() => props.disabled ?? false)
);
const hasError = computed(
@ -43,7 +52,7 @@ const hasWarning = computed(
);
provide(
"color",
IK_FORM_INPUT_COLOR,
computed(() =>
hasError.value ? "error" : hasWarning.value ? "warning" : undefined
)

View File

@ -3,8 +3,9 @@
</template>
<script lang="ts" setup>
import { provide } from "vue";
import FormCheckbox from "@/components/form/FormCheckbox.vue";
import { IK_CHECKBOX_TYPE } from "@/types/injection-keys";
import { provide } from "vue";
provide("inputType", "radio");
provide(IK_CHECKBOX_TYPE, "radio");
</script>

View File

@ -5,10 +5,11 @@
</template>
<script lang="ts" setup>
import { provide } from "vue";
import FormInput from "@/components/form/FormInput.vue";
import { IK_INPUT_TYPE } from "@/types/injection-keys";
import { provide } from "vue";
provide("inputType", "select");
provide(IK_INPUT_TYPE, "select");
</script>
<style lang="postcss" scoped></style>

View File

@ -3,10 +3,11 @@
</template>
<script lang="ts" setup>
import { provide } from "vue";
import FormInput from "@/components/form/FormInput.vue";
import { IK_INPUT_TYPE } from "@/types/injection-keys";
import { provide } from "vue";
provide("inputType", "textarea");
provide(IK_INPUT_TYPE, "textarea");
</script>
<style lang="postcss" scoped></style>

View File

@ -3,8 +3,9 @@
</template>
<script lang="ts" setup>
import { provide } from "vue";
import FormCheckbox from "@/components/form/FormCheckbox.vue";
import { IK_CHECKBOX_TYPE } from "@/types/injection-keys";
import { provide } from "vue";
provide("inputType", "toggle");
provide(IK_CHECKBOX_TYPE, "toggle");
</script>

View File

@ -14,9 +14,14 @@
</template>
<script lang="ts" setup>
import { IK_MENU_TELEPORTED } from "@/types/injection-keys";
import {
IK_CLOSE_MENU,
IK_MENU_DISABLED,
IK_MENU_HORIZONTAL,
IK_MENU_TELEPORTED,
} from "@/types/injection-keys";
import placementJs, { type Options } from "placement.js";
import { inject, nextTick, provide, ref, toRef, unref, useSlots } from "vue";
import { computed, inject, nextTick, provide, ref, useSlots } from "vue";
import { onClickOutside, unrefElement, whenever } from "@vueuse/core";
const props = defineProps<{
@ -33,9 +38,18 @@ defineOptions({
const slots = useSlots();
const isOpen = ref(false);
const menu = ref();
const isParentHorizontal = inject("isMenuHorizontal", undefined);
provide("isMenuHorizontal", toRef(props, "horizontal"));
provide("isMenuDisabled", toRef(props, "disabled"));
const isParentHorizontal = inject(
IK_MENU_HORIZONTAL,
computed(() => false)
);
provide(
IK_MENU_HORIZONTAL,
computed(() => props.horizontal ?? false)
);
provide(
IK_MENU_DISABLED,
computed(() => props.disabled ?? false)
);
let clearClickOutsideEvent: (() => void) | undefined;
const hasTrigger = useSlots().trigger !== undefined;
@ -50,9 +64,8 @@ whenever(
() => !isOpen.value,
() => clearClickOutsideEvent?.()
);
if (slots.trigger && !inject("closeMenu", false)) {
provide("closeMenu", () => (isOpen.value = false));
if (slots.trigger && inject(IK_CLOSE_MENU, undefined) === undefined) {
provide(IK_CLOSE_MENU, () => (isOpen.value = false));
}
const open = (event: MouseEvent) => {
@ -74,7 +87,7 @@ const open = (event: MouseEvent) => {
placementJs(event.currentTarget as HTMLElement, unrefElement(menu), {
placement:
props.placement ??
(unref(isParentHorizontal) !== false ? "bottom-start" : "right-start"),
(isParentHorizontal.value ? "bottom-start" : "right-start"),
});
});
};

View File

@ -10,7 +10,7 @@
>
<slot />
</MenuTrigger>
<AppMenu v-else shadow :disabled="isDisabled">
<AppMenu v-else :disabled="isDisabled" shadow>
<template #trigger="{ open, isOpen }">
<MenuTrigger
:active="isOpen"
@ -33,13 +33,17 @@
</template>
<script lang="ts" setup>
import { computed, inject, ref, unref } from "vue";
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
import { faAngleDown, faAngleRight } from "@fortawesome/free-solid-svg-icons";
import { noop } from "@vueuse/core";
import AppMenu from "@/components/menu/AppMenu.vue";
import MenuTrigger from "@/components/menu/MenuTrigger.vue";
import UiIcon from "@/components/ui/icon/UiIcon.vue";
import {
IK_CLOSE_MENU,
IK_MENU_DISABLED,
IK_MENU_HORIZONTAL,
} from "@/types/injection-keys";
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
import { faAngleDown, faAngleRight } from "@fortawesome/free-solid-svg-icons";
import { computed, inject, ref } from "vue";
const props = defineProps<{
icon?: IconDefinition;
@ -48,17 +52,25 @@ const props = defineProps<{
busy?: boolean;
}>();
const isParentHorizontal = inject("isMenuHorizontal", false);
const isMenuDisabled = inject("isMenuDisabled", false);
const isDisabled = computed(() => props.disabled || unref(isMenuDisabled));
const isParentHorizontal = inject(
IK_MENU_HORIZONTAL,
computed(() => false)
);
const isMenuDisabled = inject(
IK_MENU_DISABLED,
computed(() => false)
);
const isDisabled = computed(
() => props.disabled === true || isMenuDisabled.value
);
const submenuIcon = computed(() =>
unref(isParentHorizontal) ? faAngleDown : faAngleRight
isParentHorizontal.value ? faAngleDown : faAngleRight
);
const isHandlingClick = ref(false);
const isBusy = computed(() => isHandlingClick.value || props.busy);
const closeMenu = inject("closeMenu", noop);
const isBusy = computed(() => isHandlingClick.value || props.busy === true);
const closeMenu = inject(IK_CLOSE_MENU, undefined);
const handleClick = async () => {
if (isDisabled.value || isBusy.value) {
@ -68,7 +80,7 @@ const handleClick = async () => {
isHandlingClick.value = true;
try {
await props.onClick?.();
closeMenu();
closeMenu?.();
} finally {
isHandlingClick.value = false;
}

View File

@ -3,9 +3,13 @@
</template>
<script lang="ts" setup>
import { inject } from "vue";
import { IK_MENU_HORIZONTAL } from "@/types/injection-keys";
import { computed, inject } from "vue";
const horizontal = inject("isParentMenuHorizontal", false);
const horizontal = inject(
IK_MENU_HORIZONTAL,
computed(() => false)
);
</script>
<style lang="postcss" scoped>

View File

@ -11,21 +11,19 @@
</template>
<script lang="ts" setup>
import { IK_HOST_LAST_WEEK_STATS } from "@/types/injection-keys";
import { computed, inject } from "vue";
import { map } from "lodash-es";
import { useI18n } from "vue-i18n";
import LinearChart from "@/components/charts/LinearChart.vue";
import type { FetchedStats } from "@/composables/fetch-stats.composable";
import { formatSize } from "@/libs/utils";
import type { HostStats } from "@/libs/xapi-stats";
import type { LinearChartData } from "@/types/chart";
import { RRD_STEP_FROM_STRING } from "@/libs/xapi-stats";
import type { XenApiHost } from "@/libs/xen-api";
const { t } = useI18n();
const hostLastWeekStats =
inject<FetchedStats<XenApiHost, HostStats>>("hostLastWeekStats");
const hostLastWeekStats = inject(IK_HOST_LAST_WEEK_STATS);
const data = computed<LinearChartData>(() => {
const stats = hostLastWeekStats?.stats?.value;

View File

@ -9,20 +9,19 @@
</template>
<script lang="ts" setup>
import NoDataError from "@/components/NoDataError.vue";
import UiCardTitle from "@/components/ui/UiCardTitle.vue";
import UsageBar from "@/components/UsageBar.vue";
import type { Stat } from "@/composables/fetch-stats.composable";
import { getAvgCpuUsage } from "@/libs/utils";
import type { HostStats } from "@/libs/xapi-stats";
import { useHostStore } from "@/stores/host.store";
import { IK_HOST_STATS } from "@/types/injection-keys";
import { N_ITEMS } from "@/views/pool/PoolDashboardView.vue";
import { computed, type ComputedRef, inject } from "vue";
import NoDataError from "@/components/NoDataError.vue";
const { hasError } = useHostStore().subscribe();
const stats = inject<ComputedRef<Stat<HostStats>[]>>(
"hostStats",
const stats = inject(
IK_HOST_STATS,
computed(() => [])
);

View File

@ -12,20 +12,18 @@
<script lang="ts" setup>
import LinearChart from "@/components/charts/LinearChart.vue";
import type { FetchedStats } from "@/composables/fetch-stats.composable";
import type { HostStats } from "@/libs/xapi-stats";
import { RRD_STEP_FROM_STRING } from "@/libs/xapi-stats";
import type { XenApiHost } from "@/libs/xen-api";
import { useHostStore } from "@/stores/host.store";
import type { LinearChartData } from "@/types/chart";
import type { LinearChartData, ValueFormatter } from "@/types/chart";
import { IK_HOST_LAST_WEEK_STATS } from "@/types/injection-keys";
import { sumBy } from "lodash-es";
import { computed, inject } from "vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const hostLastWeekStats =
inject<FetchedStats<XenApiHost, HostStats>>("hostLastWeekStats");
const hostLastWeekStats = inject(IK_HOST_LAST_WEEK_STATS);
const { records: hosts } = useHostStore().subscribe();
@ -78,5 +76,5 @@ const data = computed<LinearChartData>(() => {
];
});
const customValueFormatter = (value: number) => `${value}%`;
const customValueFormatter: ValueFormatter = (value) => `${value}%`;
</script>

View File

@ -9,20 +9,19 @@
</template>
<script lang="ts" setup>
import UiCardTitle from "@/components/ui/UiCardTitle.vue";
import { type ComputedRef, computed, inject } from "vue";
import UsageBar from "@/components/UsageBar.vue";
import type { Stat } from "@/composables/fetch-stats.composable";
import { getAvgCpuUsage } from "@/libs/utils";
import type { VmStats } from "@/libs/xapi-stats";
import { N_ITEMS } from "@/views/pool/PoolDashboardView.vue";
import NoDataError from "@/components/NoDataError.vue";
import UiCardTitle from "@/components/ui/UiCardTitle.vue";
import UsageBar from "@/components/UsageBar.vue";
import { getAvgCpuUsage } from "@/libs/utils";
import { useVmStore } from "@/stores/vm.store";
import { IK_VM_STATS } from "@/types/injection-keys";
import { N_ITEMS } from "@/views/pool/PoolDashboardView.vue";
import { computed, type ComputedRef, inject } from "vue";
const { hasError } = useVmStore().subscribe();
const stats = inject<ComputedRef<Stat<VmStats>[]>>(
"vmStats",
const stats = inject(
IK_VM_STATS,
computed(() => [])
);

View File

@ -10,19 +10,18 @@
<script lang="ts" setup>
import UiCardTitle from "@/components/ui/UiCardTitle.vue";
import { IK_HOST_STATS } from "@/types/injection-keys";
import { type ComputedRef, computed, inject } from "vue";
import UsageBar from "@/components/UsageBar.vue";
import type { Stat } from "@/composables/fetch-stats.composable";
import { formatSize, parseRamUsage } from "@/libs/utils";
import type { HostStats } from "@/libs/xapi-stats";
import { N_ITEMS } from "@/views/pool/PoolDashboardView.vue";
import NoDataError from "@/components/NoDataError.vue";
import { useHostStore } from "@/stores/host.store";
const { hasError } = useHostStore().subscribe();
const stats = inject<ComputedRef<Stat<HostStats>[]>>(
"hostStats",
const stats = inject(
IK_HOST_STATS,
computed(() => [])
);

View File

@ -17,14 +17,12 @@
<script lang="ts" setup>
import LinearChart from "@/components/charts/LinearChart.vue";
import SizeStatsSummary from "@/components/ui/SizeStatsSummary.vue";
import type { FetchedStats } from "@/composables/fetch-stats.composable";
import { formatSize, getHostMemory } from "@/libs/utils";
import type { HostStats } from "@/libs/xapi-stats";
import { RRD_STEP_FROM_STRING } from "@/libs/xapi-stats";
import type { XenApiHost } from "@/libs/xen-api";
import { useHostMetricsStore } from "@/stores/host-metrics.store";
import { useHostStore } from "@/stores/host.store";
import type { LinearChartData } from "@/types/chart";
import type { LinearChartData, ValueFormatter } from "@/types/chart";
import { IK_HOST_LAST_WEEK_STATS } from "@/types/injection-keys";
import { sumBy } from "lodash-es";
import { computed, inject } from "vue";
import { useI18n } from "vue-i18n";
@ -36,8 +34,7 @@ const { runningHosts } = hostStore.subscribe({ hostMetricsSubscription });
const { t } = useI18n();
const hostLastWeekStats =
inject<FetchedStats<XenApiHost, HostStats>>("hostLastWeekStats");
const hostLastWeekStats = inject(IK_HOST_LAST_WEEK_STATS);
const customMaxValue = computed(() =>
sumBy(
@ -96,5 +93,6 @@ const data = computed<LinearChartData>(() => {
];
});
const customValueFormatter = (value: number) => String(formatSize(value));
const customValueFormatter: ValueFormatter = (value) =>
String(formatSize(value));
</script>

View File

@ -9,20 +9,19 @@
</template>
<script lang="ts" setup>
import UiCardTitle from "@/components/ui/UiCardTitle.vue";
import { type ComputedRef, computed, inject } from "vue";
import UsageBar from "@/components/UsageBar.vue";
import type { Stat } from "@/composables/fetch-stats.composable";
import { formatSize, parseRamUsage } from "@/libs/utils";
import type { VmStats } from "@/libs/xapi-stats";
import { N_ITEMS } from "@/views/pool/PoolDashboardView.vue";
import NoDataError from "@/components/NoDataError.vue";
import UiCardTitle from "@/components/ui/UiCardTitle.vue";
import UsageBar from "@/components/UsageBar.vue";
import { formatSize, parseRamUsage } from "@/libs/utils";
import { useVmStore } from "@/stores/vm.store";
import { IK_VM_STATS } from "@/types/injection-keys";
import { N_ITEMS } from "@/views/pool/PoolDashboardView.vue";
import { computed, type ComputedRef, inject } from "vue";
const { hasError } = useVmStore().subscribe();
const stats = inject<ComputedRef<Stat<VmStats>[]>>(
"vmStats",
const stats = inject(
IK_VM_STATS,
computed(() => [])
);

View File

@ -16,9 +16,13 @@
</template>
<script lang="ts" setup>
import { computed, inject, unref } from "vue";
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
import UiIcon from "@/components/ui/icon/UiIcon.vue";
import {
IK_BUTTON_GROUP_BUSY,
IK_BUTTON_GROUP_DISABLED,
} from "@/types/injection-keys";
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
import { computed, inject } from "vue";
const props = withDefaults(
defineProps<{
@ -30,11 +34,17 @@ const props = withDefaults(
{ busy: undefined, disabled: undefined }
);
const isGroupBusy = inject("isButtonGroupBusy", false);
const isBusy = computed(() => props.busy ?? unref(isGroupBusy));
const isGroupBusy = inject(
IK_BUTTON_GROUP_BUSY,
computed(() => false)
);
const isBusy = computed(() => props.busy ?? isGroupBusy.value);
const isGroupDisabled = inject("isButtonGroupDisabled", false);
const isDisabled = computed(() => props.disabled ?? unref(isGroupDisabled));
const isGroupDisabled = inject(
IK_BUTTON_GROUP_DISABLED,
computed(() => false)
);
const isDisabled = computed(() => props.disabled ?? isGroupDisabled.value);
</script>
<style lang="postcss" scoped>

View File

@ -15,7 +15,14 @@
<script lang="ts" setup>
import UiSpinner from "@/components/ui/UiSpinner.vue";
import { computed, inject, unref } from "vue";
import {
IK_BUTTON_GROUP_BUSY,
IK_BUTTON_GROUP_COLOR,
IK_BUTTON_GROUP_DISABLED,
IK_BUTTON_GROUP_OUTLINED,
IK_BUTTON_GROUP_TRANSPARENT,
} from "@/types/injection-keys";
import { computed, inject } from "vue";
import type { Color } from "@/types";
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
import UiIcon from "@/components/ui/icon/UiIcon.vue";
@ -39,17 +46,32 @@ const props = withDefaults(
}
);
const isGroupBusy = inject("isButtonGroupBusy", false);
const isBusy = computed(() => props.busy ?? unref(isGroupBusy));
const isGroupBusy = inject(
IK_BUTTON_GROUP_BUSY,
computed(() => false)
);
const isBusy = computed(() => props.busy ?? isGroupBusy.value);
const isGroupDisabled = inject("isButtonGroupDisabled", false);
const isDisabled = computed(() => props.disabled ?? unref(isGroupDisabled));
const isGroupDisabled = inject(
IK_BUTTON_GROUP_DISABLED,
computed(() => false)
);
const isDisabled = computed(() => props.disabled ?? isGroupDisabled.value);
const isGroupOutlined = inject("isButtonGroupOutlined", false);
const isGroupTransparent = inject("isButtonGroupTransparent", false);
const isGroupOutlined = inject(
IK_BUTTON_GROUP_OUTLINED,
computed(() => false)
);
const isGroupTransparent = inject(
IK_BUTTON_GROUP_TRANSPARENT,
computed(() => false)
);
const buttonGroupColor = inject("buttonGroupColor", "info");
const buttonColor = computed(() => props.color ?? unref(buttonGroupColor));
const buttonGroupColor = inject(
IK_BUTTON_GROUP_COLOR,
computed(() => "info")
);
const buttonColor = computed(() => props.color ?? buttonGroupColor.value);
const className = computed(() => {
return [
@ -58,8 +80,8 @@ const className = computed(() => {
busy: isBusy.value,
active: props.active,
disabled: isDisabled.value,
outlined: props.outlined ?? unref(isGroupOutlined),
transparent: props.transparent ?? unref(isGroupTransparent),
outlined: props.outlined ?? isGroupOutlined.value,
transparent: props.transparent ?? isGroupTransparent.value,
},
];
});

View File

@ -5,8 +5,15 @@
</template>
<script lang="ts" setup>
import { computed, provide } from "vue";
import type { Color } from "@/types";
import {
IK_BUTTON_GROUP_BUSY,
IK_BUTTON_GROUP_COLOR,
IK_BUTTON_GROUP_DISABLED,
IK_BUTTON_GROUP_OUTLINED,
IK_BUTTON_GROUP_TRANSPARENT,
} from "@/types/injection-keys";
import { computed, provide } from "vue";
const props = defineProps<{
busy?: boolean;
@ -17,23 +24,23 @@ const props = defineProps<{
merge?: boolean;
}>();
provide(
"isButtonGroupBusy",
IK_BUTTON_GROUP_BUSY,
computed(() => props.busy ?? false)
);
provide(
"isButtonGroupDisabled",
IK_BUTTON_GROUP_DISABLED,
computed(() => props.disabled ?? false)
);
provide(
"buttonGroupColor",
IK_BUTTON_GROUP_COLOR,
computed(() => props.color ?? "info")
);
provide(
"isButtonGroupOutlined",
IK_BUTTON_GROUP_OUTLINED,
computed(() => props.outlined ?? false)
);
provide(
"isButtonGroupTransparent",
IK_BUTTON_GROUP_TRANSPARENT,
computed(() => props.transparent ?? false)
);
</script>

View File

@ -5,11 +5,12 @@
</template>
<script lang="ts" setup>
import { IK_CARD_GROUP_VERTICAL } from "@/types/injection-keys";
import { inject, provide } from "vue";
const vertical = inject("isCardGroupVertical", false);
const vertical = inject(IK_CARD_GROUP_VERTICAL, false);
provide("isCardGroupVertical", !vertical);
provide(IK_CARD_GROUP_VERTICAL, !vertical);
</script>
<style lang="postcss" scoped>

View File

@ -9,7 +9,8 @@
</template>
<script lang="ts" setup>
import { type ComputedRef, computed, inject } from "vue";
import { IK_TAB_BAR_DISABLED } from "@/types/injection-keys";
import { computed, inject } from "vue";
withDefaults(
defineProps<{
@ -20,8 +21,8 @@ withDefaults(
{ tag: "span" }
);
const isTabBarDisabled = inject<ComputedRef<boolean>>(
"isTabBarDisabled",
const isTabBarDisabled = inject(
IK_TAB_BAR_DISABLED,
computed(() => false)
);
</script>

View File

@ -5,6 +5,7 @@
</template>
<script lang="ts" setup>
import { IK_TAB_BAR_DISABLED } from "@/types/injection-keys";
import { computed, provide } from "vue";
const props = defineProps<{
@ -12,8 +13,8 @@ const props = defineProps<{
}>();
provide(
"isTabBarDisabled",
computed(() => props.disabled)
IK_TAB_BAR_DISABLED,
computed(() => props.disabled ?? false)
);
</script>

View File

@ -5,3 +5,5 @@ export type LinearChartData = {
value: number;
}[];
}[];
export type ValueFormatter = (value: number) => string;

View File

@ -1,3 +1,72 @@
import type { InjectionKey } from "vue";
import type { FetchedStats, Stat } from "@/composables/fetch-stats.composable";
import type { HostStats, VmStats } from "@/libs/xapi-stats";
import type { XenApiHost } from "@/libs/xen-api";
import type { ValueFormatter } from "@/types/chart";
import type { ComputedRef, InjectionKey } from "vue";
export const IK_MENU_TELEPORTED = Symbol() as InjectionKey<boolean>;
export const IK_TAB_BAR_DISABLED = Symbol() as InjectionKey<
ComputedRef<boolean>
>;
export const IK_CHART_VALUE_FORMATTER = Symbol() as InjectionKey<
ComputedRef<ValueFormatter>
>;
export const IK_INPUT_TYPE = Symbol() as InjectionKey<"select" | "textarea">;
export const IK_CHECKBOX_TYPE = Symbol() as InjectionKey<
"checkbox" | "radio" | "toggle"
>;
export const IK_FORM_HAS_LABEL = Symbol() as InjectionKey<ComputedRef<boolean>>;
export const IK_FORM_LABEL_DISABLED = Symbol() as InjectionKey<
ComputedRef<boolean>
>;
export const IK_FORM_INPUT_COLOR = Symbol() as InjectionKey<
ComputedRef<"success" | "error" | "warning" | "info" | undefined>
>;
export const IK_MENU_DISABLED = Symbol() as InjectionKey<ComputedRef<boolean>>;
export const IK_MENU_HORIZONTAL = Symbol() as InjectionKey<
ComputedRef<boolean>
>;
export const IK_CLOSE_MENU = Symbol() as InjectionKey<() => void>;
export const IK_HOST_STATS = Symbol() as InjectionKey<
ComputedRef<Stat<HostStats>[]>
>;
export const IK_VM_STATS = Symbol() as InjectionKey<
ComputedRef<Stat<VmStats>[]>
>;
export const IK_HOST_LAST_WEEK_STATS = Symbol() as InjectionKey<
FetchedStats<XenApiHost, HostStats>
>;
export const IK_BUTTON_GROUP_DISABLED = Symbol() as InjectionKey<
ComputedRef<boolean>
>;
export const IK_BUTTON_GROUP_BUSY = Symbol() as InjectionKey<
ComputedRef<boolean>
>;
export const IK_BUTTON_GROUP_OUTLINED = Symbol() as InjectionKey<
ComputedRef<boolean>
>;
export const IK_BUTTON_GROUP_TRANSPARENT = Symbol() as InjectionKey<
ComputedRef<boolean>
>;
export const IK_BUTTON_GROUP_COLOR = Symbol() as InjectionKey<
ComputedRef<"success" | "error" | "warning" | "info">
>;
export const IK_CARD_GROUP_VERTICAL = Symbol() as InjectionKey<boolean>;

View File

@ -33,6 +33,11 @@ export const N_ITEMS = 5;
<script lang="ts" setup>
import UiCardGroup from "@/components/ui/UiCardGroup.vue";
import { useHostMetricsStore } from "@/stores/host-metrics.store";
import {
IK_HOST_LAST_WEEK_STATS,
IK_HOST_STATS,
IK_VM_STATS,
} from "@/types/injection-keys";
import { differenceBy } from "lodash-es";
import { provide, watch } from "vue";
import UiCardComingSoon from "@/components/ui/UiCardComingSoon.vue";
@ -77,9 +82,9 @@ const hostLastWeekStats = useFetchStats<XenApiHost, HostStats>(
GRANULARITY.Hours
);
provide("hostStats", hostStats);
provide("vmStats", vmStats);
provide("hostLastWeekStats", hostLastWeekStats);
provide(IK_HOST_STATS, hostStats);
provide(IK_VM_STATS, vmStats);
provide(IK_HOST_LAST_WEEK_STATS, hostLastWeekStats);
watch(runningHosts, (hosts, previousHosts) => {
// turned On