This commit is contained in:
metacryst
2026-04-28 20:05:00 -05:00
commit 0d6c7683ff
123 changed files with 20922 additions and 0 deletions

View File

@@ -0,0 +1,149 @@
import server from "/@server/server.js"
import env from "/_/code/env.js"
import "/_/code/components/LoadingCircle.js"
import "./DesktopSettingsSidebar.js"
import "./DesktopRolesSection.js"
import "./DesktopIntegrationsSection.js"
css(`
settings- {
font-family: 'Arial';
scrollbar-width: none;
-ms-overflow-style: none;
}
settings- input::placeholder {
color: var(--headertext);
opacity: 0.35;
}
`)
class Settings extends Shadow {
activeSection = "roles"
loaded = false
roles = []
allApps = []
selectedRoleId = null
roleApps = {}
confirmDeleteId = null
stripeDetails = null
render() {
HStack(() => {
DesktopSettingsSidebar(this.activeSection, (section) => {
this.activeSection = section
this.rerender()
})
VStack(() => {
if (!this.loaded) {
VStack(() => LoadingCircle())
.flex(1)
.justifyContent("center")
.alignItems("center")
} else if (this.activeSection === "roles")
DesktopRolesSection(
this.roles,
this.allApps,
this.selectedRoleId,
this.roleApps,
this.confirmDeleteId,
(id) => { this.selectedRoleId = id; this.confirmDeleteId = null; this.rerender() },
(id) => this.deleteRole(id),
(id) => { this.confirmDeleteId = id; this.rerender() },
(name) => this.createRole(name),
(roleId, appId, add) => this.toggleRoleApp(roleId, appId, add)
)
else if (this.activeSection === "integrations")
DesktopIntegrationsSection(this.stripeDetails, () => this.handleConnectStripe())
})
.flex(1).height(100, pct).overflowY("auto")
})
.height(100, pct).width(100, pct).overflow("hidden")
.onAppear(async () => {
if (this.loaded) return
await this.loadRoles()
this.stripeDetails = await server.getStripeProfile(global.currentNetwork.id)
this.rerender()
})
}
// ── Server actions ────────────────────────────────────────────────
async loadRoles() {
const [roles, apps] = await Promise.all([
server.getRoles(global.currentNetwork.id),
server.getAllApps()
])
this.roles = Array.isArray(roles) ? roles : []
this.allApps = Array.isArray(apps) ? apps : []
this.selectedRoleId = this.roles[0]?.id ?? null
await Promise.all(this.roles.map(async role => {
const roleApps = await server.getRoleApps(role.id)
this.roleApps[role.id] = new Set(Array.isArray(roleApps) ? roleApps.map(a => a.id) : [])
}))
this.loaded = true
this.rerender()
}
async createRole(name) {
const result = await server.createRole(name, global.currentNetwork.id)
if (!result?.error && result?.role) {
this.roles.push(result.role)
this.roleApps[result.role.id] = new Set()
this.selectedRoleId = result.role.id
this.rerender()
}
}
async deleteRole(roleId) {
await server.deleteRole(roleId, global.currentNetwork.id)
this.roles = this.roles.filter(r => r.id !== roleId)
delete this.roleApps[roleId]
this.selectedRoleId = this.roles[0]?.id ?? null
this.confirmDeleteId = null
this.rerender()
}
async toggleRoleApp(roleId, appId, add) {
if (add) {
await server.addRoleApp(roleId, appId)
if (!this.roleApps[roleId]) this.roleApps[roleId] = new Set()
this.roleApps[roleId].add(appId)
} else {
await server.removeRoleApp(roleId, appId)
this.roleApps[roleId]?.delete(appId)
}
if (roleId == global.currentNetwork.role?.id) {
const appName = this.allApps.find(a => a.id === appId)?.name
if (appName) {
if (add) {
global.currentNetwork.apps.push(appName)
} else {
global.currentNetwork.apps = global.currentNetwork.apps.filter(a => a !== appName)
}
document.querySelector("app-menu")?.rerender()
}
}
this.rerender()
}
handleConnectStripe() {
const state = btoa(JSON.stringify({ returnTo: window.location.href, networkId: global.currentNetwork.id }))
const params = new URLSearchParams({
response_type: "code",
client_id: env.client_id,
scope: "read_write",
redirect_uri: `${env.baseURL}/stripe/onboardingcomplete`,
state,
})
window.location.href = `https://connect.stripe.com/oauth/authorize?${params}`
}
}
register(Settings)