diff --git a/src/assets/icons/error.svg b/src/assets/icons/error.svg
new file mode 100644
index 0000000..d9ea3d0
--- /dev/null
+++ b/src/assets/icons/error.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/CommandPalette.vue b/src/components/CommandPalette.vue
index e9f1a1a..e89b7be 100644
--- a/src/components/CommandPalette.vue
+++ b/src/components/CommandPalette.vue
@@ -2,6 +2,8 @@
import { useMagicKeys } from "@vueuse/core";
import { injectStrict } from "@/lib/utils";
import Loading from "@/assets/icons/loading.svg";
+import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
+import Error from "@/assets/icons/Error.svg";
import {
CommandPaletteStateKey,
@@ -23,7 +25,7 @@ import {
const keys = useMagicKeys();
const cmdK = keys["Cmd+K"];
-const { open, commands, callStack, loading } = injectStrict(
+const { open, commands, callStack, loading, executionError } = injectStrict(
CommandPaletteStateKey
);
const openCommandPalette = injectStrict(OpenCommandPaletteKey);
@@ -100,6 +102,17 @@ watchEffect(() => {
+
+
+ Something went wrong!
+ {{
+ executionError
+ }}
+
diff --git a/src/components/tables/configmaps/columns.ts b/src/components/tables/configmaps.ts
similarity index 100%
rename from src/components/tables/configmaps/columns.ts
rename to src/components/tables/configmaps.ts
diff --git a/src/components/tables/cronjobs/columns.ts b/src/components/tables/cronjobs.ts
similarity index 100%
rename from src/components/tables/cronjobs/columns.ts
rename to src/components/tables/cronjobs.ts
diff --git a/src/components/tables/deployments/columns.ts b/src/components/tables/deployments.ts
similarity index 100%
rename from src/components/tables/deployments/columns.ts
rename to src/components/tables/deployments.ts
diff --git a/src/components/tables/ingresses/columns.ts b/src/components/tables/ingresses.ts
similarity index 100%
rename from src/components/tables/ingresses/columns.ts
rename to src/components/tables/ingresses.ts
diff --git a/src/components/tables/jobs/columns.ts b/src/components/tables/jobs.ts
similarity index 100%
rename from src/components/tables/jobs/columns.ts
rename to src/components/tables/jobs.ts
diff --git a/src/components/tables/persistentvolumeclaims/columns.ts b/src/components/tables/persistentvolumeclaims.ts
similarity index 100%
rename from src/components/tables/persistentvolumeclaims/columns.ts
rename to src/components/tables/persistentvolumeclaims.ts
diff --git a/src/components/tables/pods/columns.ts b/src/components/tables/pods.ts
similarity index 73%
rename from src/components/tables/pods/columns.ts
rename to src/components/tables/pods.ts
index 503b557..d51a7a5 100644
--- a/src/components/tables/pods/columns.ts
+++ b/src/components/tables/pods.ts
@@ -1,5 +1,6 @@
import { V1Pod } from "@kubernetes/client-node";
import { ColumnDef } from "@tanstack/vue-table";
+import { RowAction } from "@/components/tables/types";
export const columns: ColumnDef[] = [
{
@@ -36,3 +37,18 @@ export const columns: ColumnDef[] = [
accessorKey: "spec.nodeName",
},
];
+
+export const rowActions: RowAction[] = [
+ {
+ label: "Describe",
+ handler: (row) => {
+ console.log("Describe", row);
+ },
+ },
+ {
+ label: "Logs",
+ handler: (row) => {
+ console.log("Logs", row);
+ },
+ },
+];
diff --git a/src/components/tables/secrets/columns.ts b/src/components/tables/secrets.ts
similarity index 100%
rename from src/components/tables/secrets/columns.ts
rename to src/components/tables/secrets.ts
diff --git a/src/components/tables/services/columns.ts b/src/components/tables/services.ts
similarity index 100%
rename from src/components/tables/services/columns.ts
rename to src/components/tables/services.ts
diff --git a/src/components/tables/types.ts b/src/components/tables/types.ts
new file mode 100644
index 0000000..3424c5c
--- /dev/null
+++ b/src/components/tables/types.ts
@@ -0,0 +1,4 @@
+export interface RowAction {
+ label: string;
+ handler: (row: T) => void;
+}
diff --git a/src/components/tables/virtualservices/columns.ts b/src/components/tables/virtualservices.ts
similarity index 100%
rename from src/components/tables/virtualservices/columns.ts
rename to src/components/tables/virtualservices.ts
diff --git a/src/components/ui/DataTable.vue b/src/components/ui/DataTable.vue
index ca45b19..abfa703 100644
--- a/src/components/ui/DataTable.vue
+++ b/src/components/ui/DataTable.vue
@@ -1,6 +1,13 @@
+
+
+
+
+
+
diff --git a/src/components/ui/alert/AlertDescription.vue b/src/components/ui/alert/AlertDescription.vue
new file mode 100644
index 0000000..a539b63
--- /dev/null
+++ b/src/components/ui/alert/AlertDescription.vue
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert/AlertTitle.vue b/src/components/ui/alert/AlertTitle.vue
new file mode 100644
index 0000000..c5dd22c
--- /dev/null
+++ b/src/components/ui/alert/AlertTitle.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert/index.ts b/src/components/ui/alert/index.ts
new file mode 100644
index 0000000..499ee68
--- /dev/null
+++ b/src/components/ui/alert/index.ts
@@ -0,0 +1,21 @@
+import { cva } from 'class-variance-authority'
+
+export { default as Alert } from './Alert.vue'
+export { default as AlertTitle } from './AlertTitle.vue'
+export { default as AlertDescription } from './AlertDescription.vue'
+
+export const alertVariants = cva(
+ 'relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7',
+ {
+ variants: {
+ variant: {
+ default: 'bg-background text-foreground',
+ destructive:
+ 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
+ },
+ },
+ defaultVariants: {
+ variant: 'default',
+ },
+ },
+)
diff --git a/src/components/ui/command/CommandDialog.vue b/src/components/ui/command/CommandDialog.vue
index 345eb3e..9d16399 100644
--- a/src/components/ui/command/CommandDialog.vue
+++ b/src/components/ui/command/CommandDialog.vue
@@ -1,6 +1,6 @@
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuCheckboxItem.vue b/src/components/ui/context-menu/ContextMenuCheckboxItem.vue
new file mode 100644
index 0000000..aca044c
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuCheckboxItem.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuContent.vue b/src/components/ui/context-menu/ContextMenuContent.vue
new file mode 100644
index 0000000..4e201ff
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuContent.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuGroup.vue b/src/components/ui/context-menu/ContextMenuGroup.vue
new file mode 100644
index 0000000..b7458d7
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuGroup.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuItem.vue b/src/components/ui/context-menu/ContextMenuItem.vue
new file mode 100644
index 0000000..0071251
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuItem.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuLabel.vue b/src/components/ui/context-menu/ContextMenuLabel.vue
new file mode 100644
index 0000000..3702f39
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuLabel.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuPortal.vue b/src/components/ui/context-menu/ContextMenuPortal.vue
new file mode 100644
index 0000000..73dc714
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuPortal.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuRadioGroup.vue b/src/components/ui/context-menu/ContextMenuRadioGroup.vue
new file mode 100644
index 0000000..33273a7
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuRadioGroup.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuRadioItem.vue b/src/components/ui/context-menu/ContextMenuRadioItem.vue
new file mode 100644
index 0000000..298e6f7
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuRadioItem.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuSeparator.vue b/src/components/ui/context-menu/ContextMenuSeparator.vue
new file mode 100644
index 0000000..bf1eca8
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuSeparator.vue
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuShortcut.vue b/src/components/ui/context-menu/ContextMenuShortcut.vue
new file mode 100644
index 0000000..e97f3c2
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuShortcut.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuSub.vue b/src/components/ui/context-menu/ContextMenuSub.vue
new file mode 100644
index 0000000..7abc360
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuSub.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuSubContent.vue b/src/components/ui/context-menu/ContextMenuSubContent.vue
new file mode 100644
index 0000000..bfdf27b
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuSubContent.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuSubTrigger.vue b/src/components/ui/context-menu/ContextMenuSubTrigger.vue
new file mode 100644
index 0000000..6469f5f
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuSubTrigger.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/ContextMenuTrigger.vue b/src/components/ui/context-menu/ContextMenuTrigger.vue
new file mode 100644
index 0000000..9747cc1
--- /dev/null
+++ b/src/components/ui/context-menu/ContextMenuTrigger.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/context-menu/index.ts b/src/components/ui/context-menu/index.ts
new file mode 100644
index 0000000..157f7b1
--- /dev/null
+++ b/src/components/ui/context-menu/index.ts
@@ -0,0 +1,14 @@
+export { default as ContextMenu } from './ContextMenu.vue'
+export { default as ContextMenuTrigger } from './ContextMenuTrigger.vue'
+export { default as ContextMenuContent } from './ContextMenuContent.vue'
+export { default as ContextMenuGroup } from './ContextMenuGroup.vue'
+export { default as ContextMenuRadioGroup } from './ContextMenuRadioGroup.vue'
+export { default as ContextMenuItem } from './ContextMenuItem.vue'
+export { default as ContextMenuCheckboxItem } from './ContextMenuCheckboxItem.vue'
+export { default as ContextMenuRadioItem } from './ContextMenuRadioItem.vue'
+export { default as ContextMenuShortcut } from './ContextMenuShortcut.vue'
+export { default as ContextMenuSeparator } from './ContextMenuSeparator.vue'
+export { default as ContextMenuLabel } from './ContextMenuLabel.vue'
+export { default as ContextMenuSub } from './ContextMenuSub.vue'
+export { default as ContextMenuSubTrigger } from './ContextMenuSubTrigger.vue'
+export { default as ContextMenuSubContent } from './ContextMenuSubContent.vue'
diff --git a/src/main.ts b/src/main.ts
index 409462e..d779051 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -10,3 +10,11 @@ if (process.env.NODE_ENV === "development") {
}
createApp(App).use(router).mount("#app");
+
+window.addEventListener("contextmenu", (e) => e.preventDefault());
+
+window.addEventListener("keydown", (e) => {
+ if (e.metaKey && e.key === "r") {
+ window.location.reload();
+ }
+});
diff --git a/src/providers/CommandPaletteProvider.ts b/src/providers/CommandPaletteProvider.ts
index e09aeb5..5721a17 100644
--- a/src/providers/CommandPaletteProvider.ts
+++ b/src/providers/CommandPaletteProvider.ts
@@ -24,6 +24,7 @@ export interface CommandPaletteState {
commands: Command[];
commandCache: Map;
loading: boolean;
+ executionError: string | null;
}
export default {
@@ -36,6 +37,7 @@ export default {
commands: [],
commandCache: new Map(),
loading: false,
+ executionError: null,
});
provide(CommandPaletteStateKey, toRefs(state));
@@ -97,17 +99,26 @@ export default {
push(command, state.commandCache.get(command.id) as Command[]);
}
- command.commands().then((commands: Command[]) => {
- state.commandCache.set(command.id, commands);
-
- if (state.callStack.has(command)) {
- state.callStack.delete(command);
- }
-
- push(command, commands);
-
- state.loading = false;
- });
+ command
+ .commands()
+ .then((commands: Command[]) => {
+ state.commandCache.set(command.id, commands);
+
+ if (state.callStack.has(command)) {
+ state.callStack.delete(command);
+ }
+
+ push(command, commands);
+
+ state.loading = false;
+ })
+ .catch((error) => {
+ state.loading = false;
+ state.executionError = error.message;
+ setTimeout(() => {
+ state.executionError = null;
+ }, 2500);
+ });
} else {
command.execute();
clearStack();
diff --git a/src/views/ConfigMaps.vue b/src/views/ConfigMaps.vue
index b128924..9aaf661 100644
--- a/src/views/ConfigMaps.vue
+++ b/src/views/ConfigMaps.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/configmaps/columns";
+import { columns } from "@/components/tables/configmaps";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -52,3 +52,4 @@ x
+@/components/tables/configmaps/configmaps
diff --git a/src/views/CronJobs.vue b/src/views/CronJobs.vue
index 747dc7c..8a240e8 100644
--- a/src/views/CronJobs.vue
+++ b/src/views/CronJobs.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/cronjobs/columns";
+import { columns } from "@/components/tables/cronjobs";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -52,3 +52,4 @@ x
+@/components/tables/cronjobs/cronjobs
diff --git a/src/views/Deployments.vue b/src/views/Deployments.vue
index dcd9f62..8c642cc 100644
--- a/src/views/Deployments.vue
+++ b/src/views/Deployments.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/deployments/columns";
+import { columns } from "@/components/tables/deployments";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -51,3 +51,4 @@ const { startRefreshing, stopRefreshing } = useDataRefresher(
+@/components/tables/deployments/deployments
diff --git a/src/views/Ingresses.vue b/src/views/Ingresses.vue
index a3e2fe1..d31cd94 100644
--- a/src/views/Ingresses.vue
+++ b/src/views/Ingresses.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/ingresses/columns";
+import { columns } from "@/components/tables/ingresses";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -51,3 +51,4 @@ const { startRefreshing, stopRefreshing } = useDataRefresher(
+@/components/tables/ingresses/ingresses
diff --git a/src/views/Jobs.vue b/src/views/Jobs.vue
index 71b4925..c0cd422 100644
--- a/src/views/Jobs.vue
+++ b/src/views/Jobs.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/jobs/columns";
+import { columns } from "@/components/tables/jobs";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -51,3 +51,4 @@ x
+@/components/tables/jobs/jobs
diff --git a/src/views/PersistentVolumeClaims.vue b/src/views/PersistentVolumeClaims.vue
index 4d17004..17009b5 100644
--- a/src/views/PersistentVolumeClaims.vue
+++ b/src/views/PersistentVolumeClaims.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/persistentvolumeclaims/columns";
+import { columns } from "@/components/tables/persistentvolumeclaims";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -52,3 +52,4 @@ x
+@/components/tables/persistentvolumeclaims/persistentvolumeclaims
diff --git a/src/views/Pods.vue b/src/views/Pods.vue
index 547ad2f..b676495 100644
--- a/src/views/Pods.vue
+++ b/src/views/Pods.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/pods/columns";
+import { columns, rowActions } from "@/components/tables/pods";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -49,5 +49,5 @@ const { startRefreshing, stopRefreshing } = useDataRefresher(getPods, 1000, [
x
-
+
diff --git a/src/views/Secrets.vue b/src/views/Secrets.vue
index a0e7f55..7726fc1 100644
--- a/src/views/Secrets.vue
+++ b/src/views/Secrets.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/secrets/columns";
+import { columns } from "@/components/tables/secrets";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -52,3 +52,4 @@ x
+@/components/tables/secrets/secrets
diff --git a/src/views/Services.vue b/src/views/Services.vue
index 8a72af5..a8a29c2 100644
--- a/src/views/Services.vue
+++ b/src/views/Services.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/services/columns";
+import { columns } from "@/components/tables/services";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -51,3 +51,4 @@ const { startRefreshing, stopRefreshing } = useDataRefresher(
+@/components/tables/services/services
diff --git a/src/views/VirtualServices.vue b/src/views/VirtualServices.vue
index f2e9f50..8fe11ca 100644
--- a/src/views/VirtualServices.vue
+++ b/src/views/VirtualServices.vue
@@ -9,7 +9,7 @@ import { KubeContextStateKey } from "@/providers/KubeContextProvider";
const { context, namespace } = injectStrict(KubeContextStateKey);
import DataTable from "@/components/ui/DataTable.vue";
-import { columns } from "@/components/tables/virtualservices/columns";
+import { columns } from "@/components/tables/virtualservices";
import { useDataRefresher } from "@/composables/refresher";
const { toast } = useToast();
@@ -51,3 +51,4 @@ const { startRefreshing, stopRefreshing } = useDataRefresher(
+@/components/tables/virtualservices/virtualservices
diff --git a/tailwind.config.js b/tailwind.config.js
index 2a58b8a..6fd7346 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -2,8 +2,6 @@ const animate = require("tailwindcss-animate");
/** @type {import('tailwindcss').Config} */
module.exports = {
- important: true,
-
darkMode: ["class"],
content: [