Initial import: shopdb-flask multi-site asset platform
Flask + Vue rewrite of the classic-ASP shopdb, built as a plugin framework so sister GE Aerospace sites can adopt it. Product version 0.7.0-pre-0.8.0, plugin contract 0.11.0, 966 backend tests. Key entry points: - docs/INSTALL-WINDOWS-IIS.md - tested Windows + IIS install runbook (own-site and subpath deployment methods) - docs/PILOT-DEPLOY.md - production pilot: stand up + import + verify - docs/IMPORT-API.md - schema-agnostic legacy data import contract - scripts/site_imports/wjf/ - West Jefferson reference import loader - docs/adr/ - twelve accepted architecture decision records
This commit is contained in:
35
frontend/src/composables/toast.js
Normal file
35
frontend/src/composables/toast.js
Normal file
@@ -0,0 +1,35 @@
|
||||
// Global toast notifications. Import useToast() anywhere and call
|
||||
// toast.success('...') / toast.error('...') / toast.info('...'). A single
|
||||
// <ToastHost /> mounted in AppLayout renders the stack.
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const state = reactive({
|
||||
items: [],
|
||||
})
|
||||
|
||||
let nextId = 1
|
||||
|
||||
function dismiss(id) {
|
||||
const index = state.items.findIndex(t => t.id === id)
|
||||
if (index !== -1) state.items.splice(index, 1)
|
||||
}
|
||||
|
||||
function push(message, type = 'info', duration = 5000) {
|
||||
if (!message) return
|
||||
const id = nextId++
|
||||
state.items.push({ id, message, type })
|
||||
if (duration > 0) {
|
||||
setTimeout(() => dismiss(id), duration)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
export function useToast() {
|
||||
return {
|
||||
items: state.items,
|
||||
dismiss,
|
||||
success: (message, duration) => push(message, 'success', duration),
|
||||
error: (message, duration) => push(message, 'error', duration ?? 8000),
|
||||
info: (message, duration) => push(message, 'info', duration),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user