Refactor and enhance permission handling, UI components, and package metadata

- Updated ModelTable component to use more specific types for records and edit actions.
- Enhanced NavItem component to extend MUI ListItemProps for better type safety.
- Refactored normalizeLuaStructure to improve type handling with JsonValue.
- Updated LuaUIComponent and related types to use JsonValue for props and handler arguments.
- Modified AuditLog interface to use JsonObject for metadata.
- Improved importUIPages function to use a more specific database interface.
- Refactored builder-types to use JsonValue for component props and default values.
- Updated package index.json to reflect changes in package descriptions, dependencies, and added minLevel attributes.
- Enhanced permissions in Lua scripts to include new roles (moderator, supergod).
- Renamed and updated metadata for UI level packages to reflect new roles and functionalities.
- Added new UI level package (Level 6 - Supergod Panel) with associated scripts and components.
- Updated permissions check script to include new moderator role checks.
This commit is contained in:
2025-12-30 00:20:29 +00:00
parent b72763d9ff
commit fac6a49a64
27 changed files with 698 additions and 221 deletions

View File

@@ -17,9 +17,14 @@ import {
getRecordsKey,
sortRecords,
} from '@/lib/schema-utils'
import type { JsonObject, JsonValue } from '@/types/utility-types'
import { RecordForm } from './RecordForm'
type RecordValue = string | number | boolean | null | JsonObject | JsonValue[]
type RecordData = Record<string, RecordValue>
interface RelationCellValueProps {
value: string
relatedModel: string
@@ -29,8 +34,8 @@ interface RelationCellValueProps {
function RelationCellValue({ value, relatedModel, currentApp, schema }: RelationCellValueProps) {
const relatedRecordsKey = getRecordsKey(currentApp, relatedModel)
const [relatedRecords] = useKV<any[]>(relatedRecordsKey, [])
const relatedRecord = relatedRecords?.find((r: any) => r.id === value)
const [relatedRecords] = useKV<RecordData[]>(relatedRecordsKey, [])
const relatedRecord = relatedRecords?.find(r => r.id === value)
if (!relatedRecord)
return <span className="font-mono text-sm text-muted-foreground">{value}</span>
@@ -53,7 +58,7 @@ interface ModelListViewProps {
}
export function ModelListView({ model, schema, currentApp }: ModelListViewProps) {
const [records, setRecords] = useKV<any[]>(getRecordsKey(currentApp, model.name), [])
const [records, setRecords] = useKV<RecordData[]>(getRecordsKey(currentApp, model.name), [])
const [searchTerm, setSearchTerm] = useState('')
const [sortField, setSortField] = useState<string | null>(
model.ordering?.[0]?.replace('-', '') || null
@@ -61,9 +66,9 @@ export function ModelListView({ model, schema, currentApp }: ModelListViewProps)
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>(
model.ordering?.[0]?.startsWith('-') ? 'desc' : 'asc'
)
const [filters, setFilters] = useState<Record<string, any>>({})
const [filters, setFilters] = useState<Record<string, RecordValue>>({})
const [formOpen, setFormOpen] = useState(false)
const [editingRecord, setEditingRecord] = useState<any | null>(null)
const [editingRecord, setEditingRecord] = useState<RecordData | null>(null)
const displayFields =
model.listDisplay ||
@@ -102,7 +107,7 @@ export function ModelListView({ model, schema, currentApp }: ModelListViewProps)
setFormOpen(true)
}
const handleEdit = (record: any) => {
const handleEdit = (record: RecordData) => {
setEditingRecord(record)
setFormOpen(true)
}
@@ -112,7 +117,7 @@ export function ModelListView({ model, schema, currentApp }: ModelListViewProps)
toast.success('Record deleted')
}
const handleSave = (record: any) => {
const handleSave = (record: RecordData) => {
if (editingRecord) {
setRecords(current => (current || []).map(r => (r.id === record.id ? record : r)))
toast.success('Record updated')
@@ -122,7 +127,7 @@ export function ModelListView({ model, schema, currentApp }: ModelListViewProps)
}
}
const renderCellValue = (record: any, fieldName: string) => {
const renderCellValue = (record: RecordData, fieldName: string) => {
const field = model.fields.find(f => f.name === fieldName)
if (!field) return null

View File

@@ -13,11 +13,14 @@ import {
} from '@/components/ui'
import type { ModelSchema } from '@/lib/schema-types'
import { getFieldLabel } from '@/lib/schema-utils'
import type { JsonValue } from '@/types/utility-types'
type RecordData = Record<string, JsonValue>
interface DetailsDrawerProps {
open: boolean
onOpenChange: (open: boolean) => void
record: any | null
record: RecordData | null
model: ModelSchema
}

View File

@@ -10,13 +10,14 @@ import {
SelectValue,
} from '@/components/ui'
import type { FieldSchema, ModelSchema } from '@/lib/schema-types'
import type { JsonValue } from '@/types/utility-types'
interface ModelFiltersProps {
model: ModelSchema
filters: Record<string, any>
filters: Record<string, JsonValue>
searchTerm: string
onSearchChange: (value: string) => void
onFilterChange: (field: string, value: any) => void
onFilterChange: (field: string, value: JsonValue) => void
}
function getFilterableFields(model: ModelSchema): FieldSchema[] {

View File

@@ -13,17 +13,20 @@ import {
} from '@/components/ui'
import type { FieldSchema, ModelSchema } from '@/lib/schema-types'
import { getFieldLabel } from '@/lib/schema-utils'
import type { JsonValue } from '@/types/utility-types'
type RecordData = Record<string, JsonValue>
interface ModelTableProps {
model: ModelSchema
records: any[]
records: RecordData[]
displayFields: string[]
sortField?: string | null
sortDirection?: 'asc' | 'desc'
onSortChange?: (field: string) => void
onEdit?: (record: any) => void
onEdit?: (record: RecordData) => void
onDelete?: (id: string) => void
onRowClick?: (record: any) => void
onRowClick?: (record: RecordData) => void
renderRelationValue?: (value: string, field: FieldSchema) => ReactNode
}
@@ -41,7 +44,7 @@ export function ModelTable({
}: ModelTableProps) {
const actionColumns = onEdit || onDelete ? 1 : 0
const renderCellValue = (record: any, fieldName: string) => {
const renderCellValue = (record: RecordData, fieldName: string) => {
const field = model.fields.find(item => item.name === fieldName)
if (!field) return null

View File

@@ -1,9 +1,17 @@
'use client'
import { Badge, Box, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'
import {
Badge,
Box,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
type ListItemProps,
} from '@mui/material'
import { forwardRef, ReactNode } from 'react'
export interface NavItemProps {
export interface NavItemProps extends Omit<ListItemProps, 'children'> {
icon?: ReactNode
label: string
onClick?: () => void
@@ -30,6 +38,7 @@ const NavItem = forwardRef<HTMLLIElement, NavItemProps>(
href,
secondaryLabel,
dense = false,
sx,
...props
},
ref
@@ -39,9 +48,7 @@ const NavItem = forwardRef<HTMLLIElement, NavItemProps>(
ref={ref}
disablePadding
{...props}
sx={{
...(props as any).sx,
}}
sx={sx}
>
<ListItemButton
onClick={onClick}

View File

@@ -1,20 +1,22 @@
import type { LuaUIComponent } from './types/lua-ui-package'
import type { JsonValue } from '@/types/utility-types'
/**
* Normalize a Lua-converted structure to ensure arrays are properly converted
* Lua tables with sequential numeric keys (1, 2, 3...) should be JavaScript arrays
*/
export function normalizeLuaStructure(value: any): any {
export function normalizeLuaStructure(value: JsonValue): JsonValue {
if (value === null || value === undefined) {
return value
}
if (Array.isArray(value)) {
return value.map(normalizeLuaStructure)
return value.map(item => normalizeLuaStructure(item as JsonValue))
}
if (typeof value === 'object') {
const keys = Object.keys(value)
const obj = value as Record<string, JsonValue>
const keys = Object.keys(obj)
// Check if this looks like a Lua array (all keys are sequential numbers starting from 1)
const isLuaArray = keys.every((key) => {
@@ -24,20 +26,20 @@ export function normalizeLuaStructure(value: any): any {
if (isLuaArray && keys.length > 0) {
// Convert to JavaScript array
const arr: any[] = []
const arr: JsonValue[] = []
const sortedKeys = keys.map(Number).sort((a, b) => a - b)
for (const key of sortedKeys) {
arr.push(normalizeLuaStructure(value[key]))
arr.push(normalizeLuaStructure(obj[String(key)]))
}
return arr
}
// Otherwise, recursively normalize the object
const normalized: any = {}
const normalized: Record<string, JsonValue> = {}
for (const key of keys) {
normalized[key] = normalizeLuaStructure(value[key])
normalized[key] = normalizeLuaStructure(obj[key])
}
return normalized
@@ -49,6 +51,6 @@ export function normalizeLuaStructure(value: any): any {
/**
* Normalize a LuaUIComponent structure
*/
export function normalizeLuaComponent(component: any): LuaUIComponent {
export function normalizeLuaComponent(component: JsonValue): LuaUIComponent {
return normalizeLuaStructure(component) as LuaUIComponent
}

View File

@@ -2,6 +2,7 @@
* TypeScript types for Lua UI packages
* These types define the structure of UI packages written in Lua
*/
import type { JsonValue } from '@/types/utility-types'
/**
* Manifest.json structure for Lua UI packages
@@ -52,13 +53,13 @@ export interface LuaUIPage {
export interface LuaUIComponent {
type: string
props: Record<string, unknown>
props: Record<string, JsonValue>
children?: LuaUIComponent[]
}
export interface LuaUIAction {
name: string
handler: string | ((...args: any[]) => any)
handler: string | ((...args: JsonValue[]) => JsonValue)
}
export interface LuaUIValidation {
@@ -71,7 +72,7 @@ export interface LuaUIValidation {
max?: number
pattern?: string
format?: string
custom?: string | ((...args: any[]) => any)
custom?: string | ((...args: JsonValue[]) => JsonValue)
}
}
@@ -81,5 +82,5 @@ export interface LuaUIValidation {
export interface LuaUIPackage {
manifest: LuaUIManifest
pages: LuaUIPage[]
actions: Record<string, (...args: any[]) => any>
actions: Record<string, (...args: JsonValue[]) => JsonValue>
}

View File

@@ -1,4 +1,5 @@
import type { User } from '../../types/level-types'
import type { JsonObject } from '@/types/utility-types'
export type OperationType = 'CREATE' | 'READ' | 'UPDATE' | 'DELETE'
export type ResourceType =
@@ -28,7 +29,7 @@ export interface AuditLog {
success: boolean
errorMessage?: string
ipAddress?: string
metadata?: Record<string, any>
metadata?: JsonObject
}
export interface SecurityContext {

View File

@@ -2,11 +2,16 @@ import { readFile, readdir } from 'fs/promises'
import { join } from 'path'
import type { JsonObject } from '@/types/utility-types'
type UIPagesDb = {
query<T = JsonObject>(sql: string, params?: unknown[]): Promise<T[]>
execute(sql: string, params?: unknown[]): Promise<void>
}
/**
* Import UI pages from JSON seed data into the database
* Flow: JSON (packages/ui_pages/seed/pages/*.json) → Database (ui_page table)
*/
export async function importUIPages(db: any): Promise<void> {
export async function importUIPages(db: UIPagesDb): Promise<void> {
const pagesDir = join(process.cwd(), '../../packages/ui_pages/seed/pages')
try {

View File

@@ -1,9 +1,12 @@
import type { JsonValue } from '@/types/utility-types'
/**
* ComponentType - All supported UI component types in the builder
* @description Union type of all available components
* Supports: Layout (Flex, Grid, Container), Input (Input, Select, Switch),
* Display (Text, Heading, Badge), Interactive (Button, Dialog, Tabs)
*/
export type ComponentType =
| 'Button'
| 'Input'
@@ -39,7 +42,7 @@ export type ComponentType =
* @example { className: "mt-4", disabled: true, onClick: fn }
*/
export interface ComponentProps {
[key: string]: unknown
[key: string]: JsonValue
}
/**
@@ -85,7 +88,7 @@ export interface PropDefinition {
name: string
label: string
type: 'string' | 'number' | 'boolean' | 'select' | 'color' | 'dynamic-select'
defaultValue?: unknown
defaultValue?: JsonValue
options?: Array<{ value: string; label: string }>
dynamicSource?: string
description?: string

View File

@@ -1,19 +1,19 @@
{
"generatedAt": "2025-12-26T01:12:07.934Z",
"generatedAt": "2025-12-30T00:19:15.231Z",
"packages": [
{
"packageId": "admin_dialog",
"name": "Admin Dialog",
"version": "1.0.0",
"description": "Admin dialogs for user and settings management",
"description": "Admin dialog components",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_dialogs"],
"dependencies": [],
"exports": {
"scripts": ["user", "settings"],
"components": []
}
},
"minLevel": 4
},
{
"packageId": "arcade_lobby",
@@ -26,7 +26,8 @@
"dependencies": [],
"exports": {
"components": []
}
},
"minLevel": 2
},
{
"packageId": "codegen_studio",
@@ -39,7 +40,8 @@
"dependencies": [],
"exports": {
"components": []
}
},
"minLevel": 5
},
{
"packageId": "code_editor",
@@ -51,51 +53,79 @@
"category": "editors",
"dependencies": [],
"exports": {
"scripts": ["json", "lua", "theme"],
"components": ["CodeEditor", "JsonEditor", "LuaEditor", "ThemeEditor"]
}
"scripts": [
"json",
"lua",
"theme"
],
"components": [
"CodeEditor",
"JsonEditor",
"LuaEditor",
"ThemeEditor"
]
},
"minLevel": 5
},
{
"packageId": "dashboard",
"name": "Dashboard",
"version": "1.0.0",
"description": "Dashboard components with stats and layouts",
"description": "Dashboard layouts, stat cards, and widgets",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"scripts": ["stats", "layout"],
"components": []
}
"components": [
"StatCard",
"DashboardGrid",
"Widget"
],
"scripts": [
"stats",
"layout"
]
},
"minLevel": 2
},
{
"packageId": "data_table",
"name": "Data Table",
"version": "1.0.0",
"description": "Data table with columns, rows, and pagination",
"description": "Data table components",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"scripts": ["columns", "rows", "pagination"],
"components": []
}
},
"minLevel": 1
},
{
"packageId": "form_builder",
"name": "Form Builder",
"version": "1.0.0",
"description": "Form builder with field types and validation",
"description": "Form fields, validation, and submission handling",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"scripts": ["fields", "validate"],
"components": []
}
"components": [
"FormField",
"EmailField",
"PasswordField",
"NumberField",
"SearchBar"
],
"scripts": [
"fields",
"validate"
]
},
"minLevel": 1
},
{
"packageId": "forum_forge",
@@ -108,63 +138,71 @@
"dependencies": [],
"exports": {
"components": []
}
},
"minLevel": 2
},
{
"packageId": "nav_menu",
"name": "Navigation Menu",
"version": "1.0.0",
"description": "Navigation sidebar and menu components",
"description": "Sidebar, navigation menus, and breadcrumbs",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"dependencies": [
"ui_permissions"
],
"exports": {
"scripts": ["sidebar", "menu"],
"components": []
}
"components": [
"Sidebar",
"NavigationMenu",
"Breadcrumbs"
],
"scripts": [
"sidebar",
"menu"
]
},
"minLevel": 2
},
{
"packageId": "notification_center",
"name": "Notification Center",
"version": "1.0.0",
"description": "Toast notifications and notification list",
"description": "Notification center components",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"scripts": ["toast", "list"],
"components": []
}
},
"minLevel": 1
},
{
"packageId": "ui_auth",
"name": "Auth Components",
"packageId": "schema_editor",
"name": "Schema Editor",
"version": "1.0.0",
"description": "Authentication gate and access denied views",
"description": "Database schema editor components",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"category": "editors",
"dependencies": [
"form_builder"
],
"exports": {
"scripts": ["gate", "denied"],
"components": ["AuthGate", "AccessDenied"]
}
},
{
"packageId": "ui_dialogs",
"name": "Dialog Components",
"version": "1.0.0",
"description": "Confirm and alert dialog components",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"scripts": ["confirm", "alert"],
"components": ["ConfirmDialog", "AlertDialog"]
}
"scripts": [
"fields",
"tables",
"relations"
],
"components": [
"SchemaEditor",
"TableEditor",
"FieldEditor"
]
},
"minLevel": 5
},
{
"packageId": "social_hub",
@@ -207,21 +245,8 @@
"social_hub_feed_post_2_body",
"social_hub_feed_post_2_badge"
]
}
},
{
"packageId": "schema_editor",
"name": "Schema Editor",
"version": "1.0.0",
"description": "Database schema editor components",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "editors",
"dependencies": ["form_builder"],
"exports": {
"scripts": ["fields", "tables", "relations"],
"components": ["SchemaEditor", "TableEditor", "FieldEditor"]
}
},
"minLevel": 2
},
{
"packageId": "stream_cast",
@@ -234,93 +259,54 @@
"dependencies": [],
"exports": {
"components": []
}
},
"minLevel": 2
},
{
"packageId": "user_manager",
"name": "User Manager",
"packageId": "ui_auth",
"name": "Auth UI",
"version": "1.0.0",
"description": "User management components and actions",
"description": "Access denied, auth gate, and loading states",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "managers",
"dependencies": ["ui_permissions", "data_table"],
"category": "ui",
"dependencies": [
"ui_permissions"
],
"exports": {
"scripts": ["list", "actions"],
"components": ["UserManagement", "UserList", "UserActions"]
}
"components": [
"AccessDenied",
"AuthGate",
"PageLoader"
],
"scripts": [
"denied",
"gate"
]
},
"minLevel": 2
},
{
"packageId": "workflow_editor",
"name": "Workflow Editor",
"packageId": "ui_dialogs",
"name": "UI Dialogs",
"version": "1.0.0",
"description": "Workflow editor and run status components",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "editors",
"dependencies": [],
"exports": {
"scripts": ["editor", "status", "run"],
"components": ["WorkflowEditor", "WorkflowRunCard", "WorkflowRunStatus"]
}
},
{
"packageId": "ui_permissions",
"name": "UI Permissions",
"version": "1.0.0",
"description": "Shared permission utilities for page access control",
"description": "Confirmation, alert, and form dialogs",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"scripts": ["permissions"],
"components": []
}
},
{
"packageId": "ui_login",
"name": "Login Page",
"version": "1.0.0",
"description": "Login and registration page with form validation",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"exports": {
"pages": ["login"],
"scripts": ["login_ui", "login_validate"],
"components": []
}
},
{
"packageId": "ui_home",
"name": "Home Page",
"version": "1.0.0",
"description": "Level 1 home page with server status",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"exports": {
"pages": ["level1"],
"scripts": ["home_ui", "navigate"],
"components": []
}
},
{
"packageId": "ui_header",
"name": "App Header",
"version": "1.0.0",
"description": "Shared navigation header with user avatar and actions",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"exports": {
"components": ["AppHeader"],
"scripts": ["header"]
}
"components": [
"ConfirmDialog",
"AlertDialog",
"FormDialog"
],
"scripts": [
"confirm",
"alert"
]
},
"minLevel": 1
},
{
"packageId": "ui_footer",
@@ -332,9 +318,60 @@
"category": "ui",
"dependencies": [],
"exports": {
"components": ["AppFooter"],
"scripts": ["footer"]
}
"components": [
"AppFooter"
],
"scripts": [
"footer"
],
"pages": []
},
"minLevel": 1
},
{
"packageId": "ui_header",
"name": "App Header",
"version": "1.0.0",
"description": "Shared navigation header with user avatar and actions",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [
"ui_permissions"
],
"exports": {
"components": [
"AppHeader"
],
"scripts": [
"header"
],
"pages": []
},
"minLevel": 2
},
{
"packageId": "ui_home",
"name": "Home Page",
"version": "1.0.0",
"description": "Level 1 home page with server status",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [
"ui_permissions"
],
"exports": {
"pages": [
"level1"
],
"scripts": [
"home_ui",
"navigate"
],
"components": []
},
"minLevel": 1
},
{
"packageId": "ui_intro",
@@ -346,9 +383,15 @@
"category": "ui",
"dependencies": [],
"exports": {
"components": ["IntroSection"],
"scripts": ["intro"]
}
"components": [
"IntroSection"
],
"scripts": [
"intro"
],
"pages": []
},
"minLevel": 1
},
{
"packageId": "ui_level2",
@@ -358,53 +401,248 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions", "ui_header", "ui_intro"],
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro"
],
"exports": {
"pages": ["level2"],
"scripts": ["layout", "profile", "comments"]
}
"pages": [
"level2"
],
"scripts": [
"layout",
"profile",
"comments"
],
"components": []
},
"minLevel": 2
},
{
"packageId": "ui_level3",
"name": "Level 3 - Admin Panel",
"name": "Level 3 - Moderator Panel",
"version": "1.0.0",
"description": "Admin panel for user and content management",
"description": "Moderator panel for content moderation",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions", "ui_header", "ui_intro"],
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro"
],
"exports": {
"pages": ["level3"],
"scripts": ["layout", "users", "moderation"]
}
"pages": [
"level3"
],
"scripts": [
"layout",
"users",
"moderation"
],
"components": []
},
"minLevel": 3
},
{
"packageId": "ui_level4",
"name": "Level 4 - Builder",
"name": "Level 4 - Admin Panel",
"version": "1.0.0",
"description": "Application builder with schemas and workflows",
"description": "Admin panel for user and system management",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions", "ui_header", "ui_intro"],
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro",
"user_manager",
"admin_dialog"
],
"exports": {
"pages": ["level4"],
"scripts": ["layout", "schemas", "workflows"]
}
"pages": [
"level4"
],
"scripts": [
"layout",
"users",
"settings"
],
"components": []
},
"minLevel": 4
},
{
"packageId": "ui_level5",
"name": "Level 5 - Super God",
"name": "Level 5 - God Panel",
"version": "1.0.0",
"description": "Super god panel for tenant management",
"description": "God panel for application building, schemas, and workflows",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions", "ui_header", "ui_intro"],
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro",
"schema_editor",
"workflow_editor"
],
"exports": {
"pages": ["level5"],
"scripts": ["layout", "tenants", "transfer"]
"pages": [
"level5"
],
"scripts": [
"layout",
"schemas",
"workflows"
],
"components": []
},
"minLevel": 5
},
{
"packageId": "ui_level6",
"name": "Level 6 - Supergod Panel",
"version": "1.0.0",
"description": "Supergod panel for tenant management and system administration",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"minLevel": 6,
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro"
],
"exports": {
"pages": [
"level6"
],
"scripts": [
"layout",
"tenants",
"transfer",
"system"
],
"components": []
}
},
{
"packageId": "ui_login",
"name": "Login Page",
"version": "1.0.0",
"description": "Login and registration page with form validation",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [
"ui_permissions"
],
"exports": {
"pages": [
"login"
],
"scripts": [
"login_ui",
"login_actions"
],
"components": []
},
"minLevel": 1
},
{
"packageId": "ui_pages",
"name": "UI Pages Bundle",
"version": "2.0.0",
"description": "Meta-package that bundles all UI page packages",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [
"ui_permissions",
"ui_header",
"ui_footer",
"ui_intro",
"ui_login",
"ui_home",
"ui_level2",
"ui_level3",
"ui_level4",
"ui_level5",
"ui_level6"
],
"exports": {
"pages": [],
"scripts": [],
"components": []
},
"minLevel": 1
},
{
"packageId": "ui_permissions",
"name": "UI Permissions",
"version": "1.0.0",
"description": "Shared permission utilities for page access control",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"scripts": [
"permissions"
],
"components": []
},
"minLevel": 1
},
{
"packageId": "user_manager",
"name": "User Manager",
"version": "1.0.0",
"description": "User management components and actions",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "managers",
"dependencies": [
"ui_permissions",
"data_table"
],
"exports": {
"scripts": [
"list",
"actions"
],
"components": [
"UserManagement",
"UserList",
"UserActions"
]
},
"minLevel": 4
},
{
"packageId": "workflow_editor",
"name": "Workflow Editor",
"version": "1.0.0",
"description": "Workflow editor and run status components",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "editors",
"dependencies": [],
"exports": {
"scripts": [
"editor",
"status",
"run"
],
"components": [
"WorkflowEditor",
"WorkflowRunCard",
"WorkflowRunStatus"
]
},
"minLevel": 5
}
]
}
}

View File

@@ -1,11 +1,11 @@
local Permissions = {}
function Permissions.can_post(user)
return user and (user.role == "user" or user.role == "admin" or user.role == "god")
return user and (user.role == "user" or user.role == "moderator" or user.role == "admin" or user.role == "god" or user.role == "supergod")
end
function Permissions.can_moderate(user)
return user and (user.role == "admin" or user.role == "god" or user.role == "supergod")
return user and (user.role == "moderator" or user.role == "admin" or user.role == "god" or user.role == "supergod")
end
return Permissions

View File

@@ -2,12 +2,12 @@ local M = {}
function M.can_publish(user)
local role = user.role or "public"
return role == "admin" or role == "god" or role == "supergod"
return role == "moderator" or role == "admin" or role == "god" or role == "supergod"
end
function M.can_moderate(user)
local role = user.role or "public"
return role == "admin" or role == "god" or role == "supergod"
return role == "moderator" or role == "admin" or role == "god" or role == "supergod"
end
return M

View File

@@ -1,8 +1,8 @@
{
"packageId": "ui_level3",
"name": "Level 3 - Admin Panel",
"name": "Level 3 - Moderator Panel",
"version": "1.0.0",
"description": "Admin panel for user and content management",
"description": "Moderator panel for content moderation",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",

View File

@@ -1,15 +1,17 @@
{
"packageId": "ui_level4",
"name": "Level 4 - Builder",
"name": "Level 4 - Admin Panel",
"version": "1.0.0",
"description": "Application builder with schemas and workflows",
"description": "Admin panel for user and system management",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro"
"ui_intro",
"user_manager",
"admin_dialog"
],
"exports": {
"pages": [
@@ -17,8 +19,8 @@
],
"scripts": [
"layout",
"schemas",
"workflows"
"users",
"settings"
],
"components": []
},

View File

@@ -1,15 +1,17 @@
{
"packageId": "ui_level5",
"name": "Level 5 - Super God",
"name": "Level 5 - God Panel",
"version": "1.0.0",
"description": "Super god panel for tenant management",
"description": "God panel for application building, schemas, and workflows",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro"
"ui_intro",
"schema_editor",
"workflow_editor"
],
"exports": {
"pages": [
@@ -17,8 +19,8 @@
],
"scripts": [
"layout",
"tenants",
"transfer"
"schemas",
"workflows"
],
"components": []
},

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,16 @@
{
"packageId": "ui_level6",
"name": "Level 6 - Supergod Panel",
"version": "1.0.0",
"description": "Supergod panel for tenant management and system administration",
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"minLevel": 6,
"dependencies": ["ui_permissions", "ui_header", "ui_intro"],
"exports": {
"pages": ["level6"],
"scripts": ["layout", "tenants", "transfer", "system"],
"components": []
}
}

View File

@@ -0,0 +1,15 @@
-- Level 6 (Supergod) package initialization
local levels = require("ui_permissions.levels")
local M = {}
M.REQUIRED_LEVEL = levels.SUPERGOD
function M.init(context)
if context.user.level < M.REQUIRED_LEVEL then
return { allowed = false, redirect = "/access-denied" }
end
return { allowed = true }
end
return M

View File

@@ -0,0 +1,31 @@
-- Level 6 Supergod layout components
local M = {}
function M.supergod_sidebar(items)
return {
type = "supergod_sidebar",
width = "320px",
theme = "system",
items = items or {}
}
end
function M.supergod_toolbar(actions)
return {
type = "supergod_toolbar",
actions = actions or {},
showAllTenants = true,
showSystemMetrics = true
}
end
function M.supergod_content(children)
return {
type = "supergod_content",
fullWidth = true,
multiTenant = true,
children = children or {}
}
end
return M

View File

@@ -0,0 +1,9 @@
{
"scripts": [
{ "name": "init", "path": "init.lua", "description": "Level 6 initialization" },
{ "name": "layout", "path": "layout.lua", "description": "Supergod layout components" },
{ "name": "tenants", "path": "tenants.lua", "description": "Tenant management" },
{ "name": "transfer", "path": "transfer.lua", "description": "Power transfer utilities" },
{ "name": "system", "path": "system.lua", "description": "System administration" }
]
}

View File

@@ -0,0 +1,47 @@
-- System administration for supergod
local M = {}
function M.system_stats()
return {
type = "system_stats",
metrics = {
{ id = "tenants", label = "Total Tenants" },
{ id = "users", label = "Total Users" },
{ id = "storage", label = "Storage Used" },
{ id = "requests", label = "API Requests (24h)" }
}
}
end
function M.system_health()
return {
type = "system_health",
services = {
{ id = "database", label = "Database" },
{ id = "cache", label = "Cache" },
{ id = "queue", label = "Job Queue" },
{ id = "storage", label = "Object Storage" }
}
}
end
function M.system_logs()
return {
type = "system_logs",
filters = {
{ id = "level", options = { "error", "warn", "info", "debug" } },
{ id = "service", options = { "api", "worker", "scheduler" } },
{ id = "tenant", type = "tenant_select" }
}
}
end
function M.maintenance_mode(enabled)
return {
type = "maintenance_toggle",
enabled = enabled,
warningMessage = "Enabling maintenance mode will prevent all non-supergod users from accessing the system."
}
end
return M

View File

@@ -0,0 +1,40 @@
-- Tenant management for supergod
local M = {}
function M.tenant_list()
return {
type = "tenant_list",
columns = {
{ id = "name", label = "Tenant Name" },
{ id = "owner", label = "Owner" },
{ id = "users", label = "Users", type = "number" },
{ id = "status", label = "Status", type = "badge" },
{ id = "actions", label = "", type = "actions" }
}
}
end
function M.tenant_card(tenant)
return {
type = "tenant_card",
id = tenant.id,
name = tenant.name,
owner = tenant.owner,
userCount = tenant.userCount,
status = tenant.status
}
end
function M.create_tenant_form()
return {
type = "form",
id = "create_tenant",
fields = {
{ id = "name", type = "text", label = "Tenant Name", required = true },
{ id = "owner", type = "user_select", label = "Owner", required = true },
{ id = "plan", type = "select", label = "Plan", options = { "free", "pro", "enterprise" } }
}
}
end
return M

View File

@@ -0,0 +1,26 @@
-- Power transfer utilities for supergod
local M = {}
function M.transfer_form(from_user, to_user)
return {
type = "power_transfer_form",
fromUser = from_user,
toUser = to_user,
confirmationRequired = true,
warningMessage = "This action transfers all supergod privileges and cannot be undone."
}
end
function M.transfer_history()
return {
type = "transfer_history",
columns = {
{ id = "date", label = "Date", type = "date" },
{ id = "from", label = "From User" },
{ id = "to", label = "To User" },
{ id = "reason", label = "Reason" }
}
}
end
return M

View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"/>
<path d="M12 2a4.5 4.5 0 0 0 0 9 4.5 4.5 0 0 1 0 9"/>
<path d="M12 7v2"/>
<path d="M12 15v2"/>
<circle cx="12" cy="12" r="2"/>
<path d="M2 12h2"/>
<path d="M20 12h2"/>
</svg>

After

Width:  |  Height:  |  Size: 404 B

View File

@@ -16,7 +16,8 @@
"ui_level2",
"ui_level3",
"ui_level4",
"ui_level5"
"ui_level5",
"ui_level6"
],
"exports": {
"pages": [],

View File

@@ -5,6 +5,7 @@ local M = {}
local ROLE_MAP = {
public = LEVELS.PUBLIC,
user = LEVELS.USER,
moderator = LEVELS.MODERATOR,
admin = LEVELS.ADMIN,
god = LEVELS.GOD,
supergod = LEVELS.SUPERGOD
@@ -19,4 +20,12 @@ function M.can_access(user, required_level)
return M.get_level(user) >= required_level
end
function M.is_moderator_or_above(user)
return M.get_level(user) >= LEVELS.MODERATOR
end
function M.is_admin_or_above(user)
return M.get_level(user) >= LEVELS.ADMIN
end
return M