diff --git a/backend/app/settings.py b/backend/app/settings.py index 88db622..52cf0dc 100644 --- a/backend/app/settings.py +++ b/backend/app/settings.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import Literal, Optional -from pydantic import ConfigDict +from pydantic import ConfigDict, Field from pydantic_settings import BaseSettings @@ -14,7 +14,7 @@ def resolve_env_file(base_dir: str = ".") -> str: class Settings(BaseSettings): - env: Literal["dev", "prod", "demo"] = "dev" + env: Literal["dev", "prod", "demo"] = Field(default="dev", alias="ENV") database_url: str = "sqlite:///./test.db" frontend_url: Optional[str] = None @@ -29,6 +29,7 @@ class Settings(BaseSettings): model_config = ConfigDict( env_file=resolve_env_file(), env_file_encoding="utf-8", + case_sensitive=False, ) @property diff --git a/docker-compose.yaml b/docker-compose.yaml index 32437ec..a400adc 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,22 +1,4 @@ services: - db: - image: postgres:15 - container_name: evsy-db - restart: always - environment: - POSTGRES_USER: evsy - POSTGRES_PASSWORD: evsy - POSTGRES_DB: evsy - volumes: - - postgres_data:/var/lib/postgresql/data -# ports: -# - "5432:5432" - healthcheck: - test: ["CMD", "pg_isready", "-U", "evsy"] - interval: 10s - timeout: 5s - retries: 5 - backend: build: context: ./backend @@ -52,5 +34,23 @@ services: backend: condition: service_healthy + db: + image: postgres:15 + container_name: evsy-db + restart: always + environment: + POSTGRES_USER: evsy + POSTGRES_PASSWORD: evsy + POSTGRES_DB: evsy + volumes: + - postgres_data:/var/lib/postgresql/data +# ports: +# - "5432:5432" + healthcheck: + test: ["CMD", "pg_isready", "-U", "evsy"] + interval: 10s + timeout: 5s + retries: 5 + volumes: postgres_data: diff --git a/frontend/src/modules/fields/components/FieldTypeBadge.vue b/frontend/src/modules/fields/components/FieldTypeBadge.vue index 24bd1ca..fb86c68 100644 --- a/frontend/src/modules/fields/components/FieldTypeBadge.vue +++ b/frontend/src/modules/fields/components/FieldTypeBadge.vue @@ -2,12 +2,16 @@ import { FieldType } from '@/modules/fields/types' import { Badge } from '@/shared/ui/badge' import { cn } from '@/shared/utils/general' // your utility for class merging -import { useAttrs } from 'vue' +import { computed, useAttrs } from 'vue' -const props = defineProps<{ +interface Props { type: FieldType monochrome?: boolean -}>() +} + +const props = withDefaults(defineProps(), { + monochrome: false, +}) const attrs = useAttrs() @@ -31,10 +35,12 @@ const colorClass = { const baseClass = 'text-xs tracking-widest uppercase' -const finalClass = cn( - baseClass, - props.monochrome ? 'bg-muted text-foreground' : colorClass[props.type], - attrs.class as string | undefined +const color = computed(() => + props.monochrome ? 'bg-muted text-foreground' : colorClass[props.type] +) + +const finalClass = computed(() => + cn(baseClass, color, color.value, attrs.class as string | undefined) ) diff --git a/frontend/src/modules/fields/components/fieldColumns.ts b/frontend/src/modules/fields/components/fieldColumns.ts index 05f0fc2..8478ab3 100644 --- a/frontend/src/modules/fields/components/fieldColumns.ts +++ b/frontend/src/modules/fields/components/fieldColumns.ts @@ -1,10 +1,11 @@ import { h } from 'vue' -import type { Field } from '@/modules/fields/types.ts' +import type { Field, FieldType } from '@/modules/fields/types.ts' import type { ColumnDef } from '@tanstack/vue-table' import FieldsDataTableDropdown from '@/modules/fields/components/FieldsDataTableDropdown.vue' import { RouterLink } from 'vue-router' import DataTableColumnHeader from '@/shared/components/data/DataTableColumnHeader.vue' import { fieldsTableFilter } from '@/shared/utils/tableFilters' +import FieldTypeBadge from '@/modules/fields/components/FieldTypeBadge.vue' export function getFieldColumns( onEdit: (field: Field) => void, @@ -63,7 +64,7 @@ export function getFieldColumns( accessorKey: 'field_type', enableHiding: false, meta: { - class: 'w-[10ch]', + class: 'max-w-[10ch] text-left', headerClass: 'w-[10ch]', }, header: ({ column }) => @@ -73,7 +74,7 @@ export function getFieldColumns( }), cell: ({ row }) => { const field_type = String(row.getValue('field_type')) - return h('div', { class: 'text-left font-medium' }, field_type) + return h(FieldTypeBadge, { type: field_type as FieldType }, field_type) }, filterFn: (row, id, value) => { return value.includes(row.getValue(id)) diff --git a/frontend/src/modules/switchboard/api.ts b/frontend/src/modules/switchboard/api.ts index 4c94b53..28944dd 100644 --- a/frontend/src/modules/switchboard/api.ts +++ b/frontend/src/modules/switchboard/api.ts @@ -1,17 +1,17 @@ import { api } from '@/shared/utils/api' import type { ExportBundle, ImportBundle, ResetPreview } from './types' -export const seedDatabase = () => api.post('/admin/seed') +export const seedDatabase = () => api.post('/admin/seed/') export const resetDatabase = (dryRun = false) => api - .post('/admin/reset', null, { + .post('/admin/reset/', null, { params: { dry_run: dryRun }, }) .then(r => r.data) export const importData = (payload: ImportBundle, source = 'json') => - api.post('/admin/io/import', payload, { params: { source } }) + api.post('/admin/io/import/', payload, { params: { source } }) export const exportData = (target = 'json') => - api.get('/admin/io/export', { params: { target } }) + api.get('/admin/io/export/', { params: { target } }) diff --git a/frontend/src/modules/switchboard/components/ResetPanel.vue b/frontend/src/modules/switchboard/components/ResetPanel.vue index 0104a9d..d273cbc 100644 --- a/frontend/src/modules/switchboard/components/ResetPanel.vue +++ b/frontend/src/modules/switchboard/components/ResetPanel.vue @@ -6,11 +6,12 @@ import { Button } from '@/shared/ui/button' import { useEnhancedToast } from '@/shared/composables/useEnhancedToast' import type { ResetPreview } from '../types' import { Badge } from '@/shared/ui/badge' +import { Skeleton } from '@/shared/ui/skeleton' const queryClient = useQueryClient() const { showSuccess } = useEnhancedToast() -const { data: preview } = useQuery({ +const { data: preview, isLoading } = useQuery({ queryKey: ['resetPreview'], queryFn: () => resetDatabase(true), select: data => (data as ResetPreview).would_delete, @@ -35,24 +36,35 @@ const { mutate: handleReset, isPending: isResetting } = useMutation({
- + {{ preview.events }} events - + + {{ preview.fields }} fields - + + {{ preview.tags }} tags
+
+ + + +
diff --git a/frontend/src/modules/tags/components/TagsDataGrid.vue b/frontend/src/modules/tags/components/TagsDataGrid.vue index 0324cb7..4ee1705 100644 --- a/frontend/src/modules/tags/components/TagsDataGrid.vue +++ b/frontend/src/modules/tags/components/TagsDataGrid.vue @@ -62,10 +62,8 @@ const handleSearchKeydown = (event: KeyboardEvent) => { diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index be85212..c69924d 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -7,6 +7,13 @@ const publicPages = ['/login', '/signup', '/landing', '/oauth/callback'] const router = createRouter({ history: createWebHistory(), routes: routes, + scrollBehavior(to, from, savedPosition) { + if (savedPosition) { + return savedPosition + } else { + return { top: 0, behavior: 'smooth' } + } + }, }) router.beforeEach((to, _from, next) => { diff --git a/frontend/src/shared/utils/api.ts b/frontend/src/shared/utils/api.ts index 0ac47e8..b7d6d1a 100644 --- a/frontend/src/shared/utils/api.ts +++ b/frontend/src/shared/utils/api.ts @@ -3,7 +3,7 @@ import { useAuthStore } from '@/modules/auth/stores/useAuthStore' import router from '@/router' export const api = axios.create({ - baseURL: import.meta.env.VITE_API_URL ?? '/api/v1', + baseURL: import.meta.env.VITE_API_URL || '/api/v1', headers: { 'Content-Type': 'application/json', },