create-mithaq 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSES/openstatus-time-picker.txt +21 -0
- package/index.js +457 -63
- package/package.json +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/package.json +5 -3
- package/template/apps/{asas-platform → asas-backoffice}/src/api.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/auth-frame.tsx +12 -12
- package/template/apps/asas-backoffice/src/components.ts +35 -0
- package/template/apps/asas-backoffice/src/first-user.ts +14 -0
- package/template/apps/{asas-platform → asas-backoffice}/src/links.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/locale-switch.tsx +7 -5
- package/template/apps/asas-backoffice/src/no-organization.tsx +5 -0
- package/template/apps/asas-backoffice/src/redirect.ts +1 -0
- package/template/apps/{asas-platform → asas-backoffice}/src/request-headers.ts +1 -1
- package/template/apps/asas-backoffice/src/routeTree.gen.ts +206 -0
- package/template/apps/asas-backoffice/src/router.tsx +18 -0
- package/template/apps/asas-backoffice/src/routes/(screens)/backoffice/files.ts +10 -0
- package/template/apps/{asas-platform/src/routes/(screens)/platform → asas-backoffice/src/routes/(screens)/backoffice}/screen.json +426 -64
- package/template/apps/{asas-platform/src/routes/(screens)/platform → asas-backoffice/src/routes/(screens)/backoffice}/types.ts +18 -0
- package/template/apps/{asas-platform/src/routes/(screens)/platform.$.tsx → asas-backoffice/src/routes/(screens)/backoffice.$.tsx} +4 -4
- package/template/apps/{asas-platform/src/routes/(screens)/platform.index.tsx → asas-backoffice/src/routes/(screens)/backoffice.index.tsx} +3 -3
- package/template/apps/{asas-platform/src/routes/(screens)/platform.tsx → asas-backoffice/src/routes/(screens)/backoffice.tsx} +3 -3
- package/template/apps/{asas-platform → asas-backoffice}/src/routes/__root.tsx +2 -2
- package/template/apps/asas-backoffice/src/routes/api/$.ts +34 -0
- package/template/apps/asas-backoffice/src/routes/auth.create-first-user.tsx +113 -0
- package/template/apps/{asas-platform → asas-backoffice}/src/routes/auth.sign-in.tsx +9 -4
- package/template/apps/{asas-platform → asas-backoffice}/src/routes/unauthorized.tsx +24 -12
- package/template/apps/{asas-platform → asas-backoffice}/src/screen-form.tsx +5 -3
- package/template/apps/{asas-platform → asas-backoffice}/src/screen-list.tsx +6 -5
- package/template/apps/{asas-platform → asas-backoffice}/src/screen-names.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/screens.tsx +46 -26
- package/template/apps/asas-backoffice/src/server.ts +30 -0
- package/template/apps/{asas-platform → asas-backoffice}/src/slide.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/start.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/styles.css +9 -7
- package/template/apps/{asas-platform → asas-backoffice}/tsconfig.json +2 -2
- package/template/apps/{asas-platform → asas-backoffice}/vite.config.ts +7 -1
- package/template/apps/asas-tanstack/package.json +4 -2
- package/template/apps/asas-tanstack/src/api.ts +1 -1
- package/template/apps/asas-tanstack/src/auth-frame.tsx +12 -12
- package/template/apps/asas-tanstack/src/choose-password.tsx +150 -0
- package/template/apps/asas-tanstack/src/components.ts +35 -0
- package/template/apps/asas-tanstack/src/copy.ts +416 -79
- package/template/apps/asas-tanstack/src/first-run.ts +16 -0
- package/template/apps/asas-tanstack/src/links.ts +1 -1
- package/template/apps/asas-tanstack/src/locale-switch.tsx +7 -5
- package/template/apps/asas-tanstack/src/no-organization.tsx +108 -0
- package/template/apps/asas-tanstack/src/redirect.ts +20 -1
- package/template/apps/asas-tanstack/src/request-headers.ts +1 -1
- package/template/apps/asas-tanstack/src/routeTree.gen.ts +42 -0
- package/template/apps/asas-tanstack/src/router.tsx +12 -1
- package/template/apps/asas-tanstack/src/routes/(screens)/dashboard/files.ts +9 -2
- package/template/apps/asas-tanstack/src/routes/(screens)/dashboard/screen.json +475 -116
- package/template/apps/asas-tanstack/src/routes/(screens)/dashboard/types.ts +4 -2
- package/template/apps/asas-tanstack/src/routes/(screens)/portal/files.ts +7 -2
- package/template/apps/asas-tanstack/src/routes/(screens)/portal/screen.json +83 -319
- package/template/apps/asas-tanstack/src/routes/(screens)/portal/types.ts +3 -1
- package/template/apps/asas-tanstack/src/routes/__root.tsx +1 -1
- package/template/apps/asas-tanstack/src/routes/auth.accept-invitation.tsx +14 -7
- package/template/apps/asas-tanstack/src/routes/auth.first-run.tsx +114 -0
- package/template/apps/asas-tanstack/src/routes/auth.forgot-password.tsx +2 -2
- package/template/apps/asas-tanstack/src/routes/auth.handoff.ts +5 -5
- package/template/apps/asas-tanstack/src/routes/auth.reset-password.tsx +7 -100
- package/template/apps/asas-tanstack/src/routes/auth.set-password.tsx +16 -0
- package/template/apps/asas-tanstack/src/routes/auth.sign-in.tsx +27 -15
- package/template/apps/asas-tanstack/src/routes/auth.sign-up.tsx +59 -38
- package/template/apps/asas-tanstack/src/routes/index.tsx +18 -14
- package/template/apps/asas-tanstack/src/routes/unauthorized.tsx +24 -12
- package/template/apps/asas-tanstack/src/screen-form.tsx +5 -3
- package/template/apps/asas-tanstack/src/screen-list.tsx +6 -5
- package/template/apps/asas-tanstack/src/screen-names.ts +1 -1
- package/template/apps/asas-tanstack/src/screens.tsx +46 -26
- package/template/apps/asas-tanstack/src/server.ts +10 -0
- package/template/apps/asas-tanstack/src/slide.ts +1 -1
- package/template/apps/asas-tanstack/src/styles.css +7 -3
- package/template/apps/asas-tanstack/tsconfig.json +2 -2
- package/template/apps/asas-tanstack/vite.config.ts +7 -1
- package/template/package.json +3 -3
- package/template/templates/asas/.claude/skills/add-field/SKILL.md +27 -0
- package/template/templates/asas/.claude/skills/add-kayan/SKILL.md +26 -0
- package/template/templates/asas/.claude/skills/eject-admin-piece/SKILL.md +28 -0
- package/template/templates/asas/.claude/skills/upgrade-mithaq/SKILL.md +35 -0
- package/template/templates/asas/.env.example +22 -5
- package/template/templates/asas/AGENTS.md +101 -0
- package/template/templates/asas/CLAUDE.md +1 -0
- package/template/templates/asas/README.md +1056 -0
- package/template/templates/asas/package.json +19 -4
- package/template/templates/asas/src/asas.ts +81 -56
- package/template/templates/asas/src/{platform-http.ts → backoffice-http.ts} +48 -27
- package/template/templates/asas/src/dev-setup.ts +112 -0
- package/template/templates/asas/src/local-database.ts +22 -0
- package/template/templates/asas/src/messages/account.json +129 -103
- package/template/templates/asas/src/messages/auditLog.json +223 -105
- package/template/templates/asas/src/messages/backofficeLog.json +132 -0
- package/template/templates/asas/src/messages/courses.json +256 -214
- package/template/templates/asas/src/messages/enrollments.json +45 -27
- package/template/templates/asas/src/messages/invitation.json +72 -56
- package/template/templates/asas/src/messages/localUsers.json +34 -28
- package/template/templates/asas/src/messages/media.json +31 -21
- package/template/templates/asas/src/messages/member.json +59 -39
- package/template/templates/asas/src/messages/memberRoles.json +37 -31
- package/template/templates/asas/src/messages/mithaq.json +206 -162
- package/template/templates/asas/src/messages/organization.json +63 -41
- package/template/templates/asas/src/messages/organizationRole.json +59 -47
- package/template/templates/asas/src/messages/roles.json +59 -45
- package/template/templates/asas/src/messages/session.json +99 -79
- package/template/templates/asas/src/messages/sessions.json +110 -80
- package/template/templates/asas/src/messages/settings.json +51 -53
- package/template/templates/asas/src/messages/tags.json +31 -21
- package/template/templates/asas/src/messages/user.json +109 -87
- package/template/templates/asas/src/messages/verification.json +59 -47
- package/template/templates/asas/src/migrations/20261014221355_tags_restrict/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261014221355_tags_restrict/snapshot.json +3881 -0
- package/template/templates/asas/src/migrations/20261014222218_one_seat_per_session/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261014222218_one_seat_per_session/snapshot.json +3894 -0
- package/template/templates/asas/src/migrations/20261014223522_session_archive_reason/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261014223522_session_archive_reason/snapshot.json +3907 -0
- package/template/templates/asas/src/migrations/20261014225728_course_archive_by_operation/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261014225728_course_archive_by_operation/snapshot.json +3907 -0
- package/template/templates/asas/src/migrations/20261015042444_organization_names/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261015042444_organization_names/snapshot.json +3920 -0
- package/template/templates/asas/src/migrations/20261015053212_member_last_seen/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261015053212_member_last_seen/snapshot.json +3933 -0
- package/template/templates/asas/src/migrations/20261015093203_activity_and_staff_history/migration.sql +15 -0
- package/template/templates/asas/src/migrations/20261015093203_activity_and_staff_history/snapshot.json +4113 -0
- package/template/templates/asas/src/migrations/20261015095752_portal/migration.sql +2 -0
- package/template/templates/asas/src/migrations/20261015095752_portal/snapshot.json +4113 -0
- package/template/templates/asas/src/migrations/20261015135529_better_auth_indexes/migration.sql +9 -0
- package/template/templates/asas/src/migrations/20261015135529_better_auth_indexes/snapshot.json +4302 -0
- package/template/templates/asas/src/migrations/20261015162438_audit_changes_json/migration.sql +27 -0
- package/template/templates/asas/src/migrations/20261015162438_audit_changes_json/snapshot.json +4289 -0
- package/template/templates/asas/src/migrations/schema.ts +1 -0
- package/template/templates/asas/src/mithaq.ts +4 -406
- package/template/templates/asas/src/organizations.ts +3 -0
- package/template/templates/asas/src/seed.ts +147 -45
- package/template/templates/asas/src/{ui-platform → ui-backoffice}/home.tsx +9 -9
- package/template/templates/asas/src/ui-backoffice/organization-actions.tsx +121 -0
- package/template/templates/asas/src/{ui-platform → ui-backoffice}/record-page.tsx +4 -4
- package/template/templates/asas/src/{ui-platform → ui-backoffice}/role-cells.tsx +13 -6
- package/template/templates/asas/src/{ui-platform → ui-backoffice}/user-actions.tsx +46 -48
- package/template/templates/asas/src/ui-dashboard/dashboard.tsx +10 -4
- package/template/templates/asas/src/ui-dashboard/home.tsx +73 -0
- package/template/templates/asas/src/ui-dashboard/members-card.tsx +147 -0
- package/template/templates/asas/src/ui-dashboard/members.tsx +637 -438
- package/template/templates/asas/src/ui-dashboard/versions.tsx +22 -8
- package/template/templates/asas/src/ui-portal/courses-home.tsx +96 -0
- package/template/templates/asas/src/ui-portal/home.tsx +9 -13
- package/template/templates/features/audit-log/audit-log/audit-log.ts +284 -0
- package/template/templates/features/audit-log/backoffice-log/backoffice-log.ts +67 -0
- package/template/templates/features/audit-log/index.ts +4 -0
- package/template/templates/features/audit-log/package.json +13 -0
- package/template/templates/features/auth/index.ts +11 -0
- package/template/templates/{asas/src → features/auth}/local-users/local-users.ts +7 -7
- package/template/templates/{auth → features/auth}/package.json +2 -3
- package/template/templates/{asas/src/kayan → features}/auth/user/account.access.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/account.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/invitation.access.ts +1 -1
- package/template/templates/{asas/src/kayan → features}/auth/user/invitation.ts +3 -3
- package/template/templates/{asas/src/kayan → features}/auth/user/member.access.ts +4 -4
- package/template/templates/{asas/src/kayan → features}/auth/user/member.screens.ts +5 -5
- package/template/templates/{asas/src/kayan → features}/auth/user/member.ts +4 -3
- package/template/templates/{asas/src/kayan → features}/auth/user/organization.access.ts +6 -6
- package/template/templates/{asas/src/kayan → features}/auth/user/organization.screens.ts +6 -6
- package/template/templates/{asas/src/kayan → features}/auth/user/organization.ts +2 -1
- package/template/templates/{asas/src/kayan → features}/auth/user/organizationRole.access.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/organizationRole.ts +3 -3
- package/template/templates/{asas/src/kayan → features}/auth/user/session.access.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/session.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/user.access.ts +8 -7
- package/template/templates/{asas/src/kayan → features}/auth/user/user.screens.ts +9 -9
- package/template/templates/{asas/src/kayan → features}/auth/user/user.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/verification.access.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/verification.ts +2 -2
- package/template/templates/{asas/src → features/courses}/courses/courses.ts +122 -133
- package/template/templates/features/courses/courses/cover-reads.ts +33 -0
- package/template/templates/features/courses/courses/ui/archived-badge.tsx +9 -0
- package/template/templates/{asas/src → features/courses}/courses/ui/fee-cell.tsx +1 -1
- package/template/templates/{asas/src → features/courses}/courses/ui/status-cell.tsx +5 -3
- package/template/templates/features/courses/courses/ui/unpublish-button.tsx +15 -0
- package/template/templates/features/courses/domain/archive.ts +39 -0
- package/template/templates/features/courses/domain/on-offer.ts +6 -0
- package/template/templates/features/courses/enrollments/enrollments.ts +309 -0
- package/template/templates/{asas/src → features/courses}/enrollments/ui/session-cell.tsx +17 -7
- package/template/templates/{asas/src → features/courses/enrollments}/ui/session-labels.tsx +3 -3
- package/template/templates/features/courses/index.ts +8 -0
- package/template/templates/features/courses/package.json +24 -0
- package/template/templates/features/courses/portal/ui/catalogue.tsx +86 -0
- package/template/templates/features/courses/portal/ui/course.tsx +176 -0
- package/template/templates/features/courses/portal/ui/enrollments.tsx +170 -0
- package/template/templates/features/courses/portal/ui/parts.tsx +95 -0
- package/template/templates/features/courses/portal/ui/reads.ts +76 -0
- package/template/templates/features/courses/portal/ui/rules.ts +87 -0
- package/template/templates/features/courses/portal/ui/shell.tsx +194 -0
- package/template/templates/features/courses/sessions/seats.ts +42 -0
- package/template/templates/{asas/src → features/courses}/sessions/sessions.ts +45 -14
- package/template/templates/features/media/index.ts +10 -0
- package/template/templates/{asas/src → features/media}/media/media.ts +34 -40
- package/template/templates/{asas/src → features/media}/media/ui/preview.tsx +2 -2
- package/template/templates/features/media/package.json +19 -0
- package/template/templates/features/roles/index.ts +4 -0
- package/template/templates/{asas/src → features/roles}/member-roles/member-roles.ts +15 -15
- package/template/templates/features/roles/package.json +21 -0
- package/template/templates/{asas/src → features/roles}/roles/roles.ts +23 -23
- package/template/templates/{asas/src → features/roles}/roles/ui/role-form.tsx +65 -24
- package/template/templates/{asas/src → features/roles}/roles/ui/roles.tsx +49 -25
- package/template/templates/features/settings/index.ts +3 -0
- package/template/templates/features/settings/package.json +13 -0
- package/template/templates/{asas/src → features/settings}/settings/settings.ts +12 -17
- package/template/templates/features/tags/index.ts +3 -0
- package/template/templates/features/tags/package.json +14 -0
- package/template/templates/{asas/src → features/tags}/tags/tags.ts +15 -15
- package/template/templates/mithaq/package.json +33 -0
- package/template/templates/mithaq/src/mail/index.ts +32 -0
- package/template/templates/mithaq/src/mail/mailers.ts +36 -0
- package/template/templates/{asas/src/audit-log/sink.ts → mithaq/src/mithaq/audit-sink.ts} +31 -9
- package/template/templates/{auth/src/platform-roles.ts → mithaq/src/mithaq/auth/backoffice-roles.ts} +44 -23
- package/template/templates/mithaq/src/mithaq/auth/index.ts +1859 -0
- package/template/templates/mithaq/src/mithaq/auth/organizations.ts +80 -0
- package/template/templates/{asas/src → mithaq/src/mithaq}/pages.ts +16 -7
- package/template/templates/mithaq/src/mithaq/rich-text-nodes.ts +19 -0
- package/template/templates/mithaq/src/mithaq.ts +593 -0
- package/template/templates/mithaq/src/roles/default-member-roles.ts +29 -0
- package/template/templates/{asas → mithaq}/src/roles/grants.ts +1 -1
- package/template/templates/mithaq/src/roles/member-access.ts +11 -0
- package/template/templates/{asas/src → mithaq/src/roles}/statements.ts +6 -4
- package/template/templates/mithaq/src/roles/system-roles.ts +16 -0
- package/template/templates/{asas/src → mithaq/src/roles}/tenant-access.ts +96 -57
- package/template/templates/{asas/src → mithaq/src/roles}/tenant-roles.ts +84 -25
- package/template/templates/{asas → mithaq}/src/steps/expected-updated-at.ts +2 -2
- package/template/templates/{asas → mithaq}/src/storage/index.ts +3 -1
- package/template/templates/mithaq/src/ui/activity-page.tsx +33 -0
- package/template/templates/mithaq/src/ui/activity.tsx +527 -0
- package/template/templates/{asas → mithaq}/src/ui/app-shell.tsx +27 -19
- package/template/templates/mithaq/src/ui/rich-text-nodes.tsx +33 -0
- package/template/templates/{asas → mithaq}/src/ui/screen-nav.tsx +1 -1
- package/template/templates/{asas → mithaq}/src/ui/top-shell.tsx +8 -8
- package/template/apps/asas-platform/src/components/mithaq/cells.tsx +0 -112
- package/template/apps/asas-platform/src/components/mithaq/controls.tsx +0 -650
- package/template/apps/asas-platform/src/components/mithaq/field-shell.tsx +0 -53
- package/template/apps/asas-platform/src/components/mithaq/filter-operators.ts +0 -108
- package/template/apps/asas-platform/src/components/mithaq/form.tsx +0 -1467
- package/template/apps/asas-platform/src/components/mithaq/list-columns.tsx +0 -108
- package/template/apps/asas-platform/src/components/mithaq/list-filters.tsx +0 -368
- package/template/apps/asas-platform/src/components/mithaq/list-pagination.tsx +0 -153
- package/template/apps/asas-platform/src/components/mithaq/list-query.ts +0 -432
- package/template/apps/asas-platform/src/components/mithaq/list-selection.tsx +0 -74
- package/template/apps/asas-platform/src/components/mithaq/list.tsx +0 -865
- package/template/apps/asas-platform/src/components/mithaq/nav.tsx +0 -871
- package/template/apps/asas-platform/src/components/mithaq/nodes.tsx +0 -1024
- package/template/apps/asas-platform/src/components/mithaq/relationship-cell.tsx +0 -127
- package/template/apps/asas-platform/src/components/mithaq/relationship-control.tsx +0 -400
- package/template/apps/asas-platform/src/components/mithaq/rich-text-nodes.ts +0 -6
- package/template/apps/asas-platform/src/components/mithaq/rich-text.tsx +0 -1083
- package/template/apps/asas-platform/src/components/mithaq/upload.tsx +0 -686
- package/template/apps/asas-platform/src/components/ui/drawer.tsx +0 -216
- package/template/apps/asas-platform/src/redirect.ts +0 -1
- package/template/apps/asas-platform/src/routeTree.gen.ts +0 -181
- package/template/apps/asas-platform/src/router.tsx +0 -7
- package/template/apps/asas-platform/src/routes/(screens)/platform/files.ts +0 -4
- package/template/apps/asas-platform/src/routes/api/$.ts +0 -30
- package/template/apps/asas-platform/src/server.ts +0 -20
- package/template/apps/asas-tanstack/src/components/mithaq/cells.tsx +0 -112
- package/template/apps/asas-tanstack/src/components/mithaq/controls.tsx +0 -650
- package/template/apps/asas-tanstack/src/components/mithaq/field-shell.tsx +0 -53
- package/template/apps/asas-tanstack/src/components/mithaq/filter-operators.ts +0 -108
- package/template/apps/asas-tanstack/src/components/mithaq/form.tsx +0 -1467
- package/template/apps/asas-tanstack/src/components/mithaq/list-columns.tsx +0 -108
- package/template/apps/asas-tanstack/src/components/mithaq/list-filters.tsx +0 -368
- package/template/apps/asas-tanstack/src/components/mithaq/list-pagination.tsx +0 -153
- package/template/apps/asas-tanstack/src/components/mithaq/list-query.ts +0 -432
- package/template/apps/asas-tanstack/src/components/mithaq/list-selection.tsx +0 -74
- package/template/apps/asas-tanstack/src/components/mithaq/list.tsx +0 -865
- package/template/apps/asas-tanstack/src/components/mithaq/nav.tsx +0 -871
- package/template/apps/asas-tanstack/src/components/mithaq/nodes.tsx +0 -1024
- package/template/apps/asas-tanstack/src/components/mithaq/relationship-cell.tsx +0 -127
- package/template/apps/asas-tanstack/src/components/mithaq/relationship-control.tsx +0 -400
- package/template/apps/asas-tanstack/src/components/mithaq/rich-text-nodes.ts +0 -6
- package/template/apps/asas-tanstack/src/components/mithaq/rich-text.tsx +0 -1083
- package/template/apps/asas-tanstack/src/components/mithaq/upload.tsx +0 -686
- package/template/apps/asas-tanstack/src/components/ui/drawer.tsx +0 -215
- package/template/templates/asas/src/audit-log/audit-log.ts +0 -187
- package/template/templates/asas/src/audit-log/ui/activity.tsx +0 -243
- package/template/templates/asas/src/courses/ui/archive-button.tsx +0 -25
- package/template/templates/asas/src/courses/ui/no-courses-on-offer.tsx +0 -11
- package/template/templates/asas/src/courses/ui/on-offer.ts +0 -6
- package/template/templates/asas/src/enrollments/enrollments.ts +0 -137
- package/template/templates/asas/src/rich-text-nodes.ts +0 -11
- package/template/templates/asas/src/roles.ts +0 -16
- package/template/templates/asas/src/ui/rich-text-nodes.tsx +0 -15
- package/template/templates/asas/src/ui-platform/organization-actions.tsx +0 -114
- package/template/templates/auth/src/index.ts +0 -690
- /package/template/apps/{asas-platform → asas-backoffice}/components.json +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/gitignore +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/public/favicon.svg +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/accordion.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/alert-dialog.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/avatar.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/badge.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/breadcrumb.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/button-group.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/button.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/calendar.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/card.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/chart.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/checkbox.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/collapsible.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/combobox.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/dialog.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/direction.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/directional-icon.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/dropdown-menu.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/field.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/input-group.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/input-otp.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/input.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/label.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/popover.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/radio-group.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/resizable.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/scroll-area.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/select.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/separator.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/sheet.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/sidebar.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/skeleton.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/slider.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/spinner.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/switch.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/table.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/tabs.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/textarea.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/toggle-group.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/toggle.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/tooltip.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/copy.ts +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/hooks/use-mobile.ts +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/lib/utils.ts +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/theme.ts +0 -0
- /package/template/templates/{asas/src/kayan → features}/auth/user/index.ts +0 -0
- /package/template/templates/{asas/src → features/courses}/courses/ui/no-courses.tsx +0 -0
- /package/template/templates/{asas → mithaq}/components.json +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/defaults.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/local.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/r2.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/s3.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/uploadthing.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/ui/kpi-card.tsx +0 -0
- /package/template/templates/{asas → mithaq}/src/ui/record-page.tsx +0 -0
- /package/template/templates/{asas → mithaq}/src/ui/table-page.tsx +0 -0
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// The portal's own button for `archive`, drawn in the edit page's danger zone
|
|
2
|
-
// as the registry draws its buttons: one click, behind the page's confirm,
|
|
3
|
-
// with the reason written for the viewer in the viewer's locale, where the
|
|
4
|
-
// dashboard asks for one in a dialog.
|
|
5
|
-
import type { ButtonProps } from 'mithaq/admin'
|
|
6
|
-
import { useLocale, useRecord, useUser } from 'mithaq/admin/react'
|
|
7
|
-
import { Button } from '@/components/ui/button'
|
|
8
|
-
|
|
9
|
-
export function ArchiveButton({ busy, operation, run }: ButtonProps) {
|
|
10
|
-
const { t } = useLocale()
|
|
11
|
-
const record = useRecord()
|
|
12
|
-
const user = useUser()
|
|
13
|
-
return (
|
|
14
|
-
<Button
|
|
15
|
-
type="button"
|
|
16
|
-
variant="outline"
|
|
17
|
-
data-archive-button={operation}
|
|
18
|
-
data-row={String(record?.id ?? '')}
|
|
19
|
-
disabled={busy || !record}
|
|
20
|
-
onClick={() => void run({ reason: t('courses.operations.archive.portalReason', 'Archived from the portal by {name}')!.replace('{name}', () => user.name) })}
|
|
21
|
-
>
|
|
22
|
-
{t('courses.operations.archive', 'Archive')}
|
|
23
|
-
</Button>
|
|
24
|
-
)
|
|
25
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { EmptyProps } from 'mithaq/admin'
|
|
2
|
-
import { useKayan, useLocale } from 'mithaq/admin/react'
|
|
3
|
-
|
|
4
|
-
export function NoCourses({ page }: EmptyProps) {
|
|
5
|
-
const { t } = useLocale()
|
|
6
|
-
return (
|
|
7
|
-
<p data-empty={`${useKayan().name}${page.path}`} className="text-muted-foreground text-sm">
|
|
8
|
-
{t('courses.noneOnOffer', 'No courses on offer yet.')}
|
|
9
|
-
</p>
|
|
10
|
-
)
|
|
11
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// The courses the portal offers: every course not archived. The portal lists
|
|
2
|
-
// these alone, as its screen's `baseFilter` for the kayan, and its home counts
|
|
3
|
-
// these alone. Plain data in a file of its own, so the page that counts reads it
|
|
4
|
-
// without the kayan's declaration. A course with no `archived` value is not
|
|
5
|
-
// archived either.
|
|
6
|
-
export const onOffer = { or: [{ archived: { exists: false } }, { archived: { equals: false } }] }
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { defaultFields, defaultOperations, folderOf } from 'mithaq'
|
|
2
|
-
import { defineKayan, organization } from '../mithaq.ts'
|
|
3
|
-
import { readsPast, user as actor } from '../tenant-access.ts'
|
|
4
|
-
import { activity, appPage, danger, platformList, platformRecord, topPage } from '../pages.ts'
|
|
5
|
-
import { user } from '../kayan/auth/user/user.ts'
|
|
6
|
-
import { sessions } from '../sessions/sessions.ts'
|
|
7
|
-
|
|
8
|
-
const ui = folderOf(new URL('./ui/', import.meta.url))
|
|
9
|
-
const sessionCell = ui('session-cell.tsx#SessionCell')
|
|
10
|
-
const enrollment = [{ section: 'enrollment', label: { en: 'Enrollment', ar: 'التسجيل' }, fields: ['session', 'student'] }] as const
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The seats an actor reads, edits and deletes, inside its active organization:
|
|
14
|
-
* every seat of its organization for an actor holding
|
|
15
|
-
* `enrollments.others` and for platform staff, its own seats alone for anyone
|
|
16
|
-
* else. That is the student, whose enrollment keys would otherwise reach every
|
|
17
|
-
* other student's seat, and a custom role a tenant writes without the key.
|
|
18
|
-
* Another's seat answers 404, as a missing row does.
|
|
19
|
-
*
|
|
20
|
-
* The id is read off the actor as an own key, and an actor carrying none reaches
|
|
21
|
-
* no seat. Every read answers from it, a session's join of its enrollments
|
|
22
|
-
* included.
|
|
23
|
-
*/
|
|
24
|
-
const ownSeats = ({ user }: { user: unknown }) => {
|
|
25
|
-
if (readsPast(user, 'enrollments.others')) return true
|
|
26
|
-
const actor = user && typeof user === 'object' ? (user as Record<string, unknown>) : undefined
|
|
27
|
-
const id = actor && Object.hasOwn(actor, 'id') ? actor.id : undefined
|
|
28
|
-
return typeof id === 'string' && id ? { student: { equals: id } } : false
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const enrollments = defineKayan({
|
|
32
|
-
name: 'enrollments',
|
|
33
|
-
access: { read: ownSeats, update: ownSeats, delete: ownSeats },
|
|
34
|
-
fields: {
|
|
35
|
-
...defaultFields,
|
|
36
|
-
organization,
|
|
37
|
-
// Read as the session's course and its start on every screen, where a
|
|
38
|
-
// session alone is titled by its start.
|
|
39
|
-
//
|
|
40
|
-
// Both are required, so no write makes a seat for nobody or in nothing, and
|
|
41
|
-
// a session or a person that holds one is not deleted under it: a required
|
|
42
|
-
// relationship restricts.
|
|
43
|
-
session: {
|
|
44
|
-
kind: 'relationship', label: { en: 'Session', ar: 'الحصة' }, relationTo: () => sessions,
|
|
45
|
-
rules: { required: true },
|
|
46
|
-
targets: { dashboard: { cell: sessionCell }, portal: { cell: sessionCell }, platform: { cell: sessionCell } },
|
|
47
|
-
},
|
|
48
|
-
// A create that names no student enrolls the person making it: the runner's
|
|
49
|
-
// defaults step fills it from the actor, and a field with a default is one a
|
|
50
|
-
// create may leave out, at the HTTP boundary too. A role without the column's
|
|
51
|
-
// key is refused the filled value, so today only the instructor's and the
|
|
52
|
-
// administrator's API create fills it; the student reads its own seats and
|
|
53
|
-
// creates none.
|
|
54
|
-
student: {
|
|
55
|
-
kind: 'relationship', label: { en: 'Student', ar: 'الطالب' }, relationTo: () => user,
|
|
56
|
-
rules: { required: true, defaultValue: actor.id },
|
|
57
|
-
},
|
|
58
|
-
/**
|
|
59
|
-
* The field the language names as its soft-delete mark, so a student who
|
|
60
|
-
* leaves a session is a row this kayan keeps rather than one it removes: an
|
|
61
|
-
* enrollment is the record that the student was there. It is the one kayan
|
|
62
|
-
* of this template that takes the mark. Nothing points at an enrollment, so
|
|
63
|
-
* no child outlives it, and nothing refers to it through a `restrict`
|
|
64
|
-
* foreign key that a delete would have to release. Nobody supplies the
|
|
65
|
-
* mark: the runner writes it at the delete.
|
|
66
|
-
*
|
|
67
|
-
* `session` and `student` are required, so each restricts, and a session or
|
|
68
|
-
* a person a marked enrollment still names is not deleted under it.
|
|
69
|
-
*/
|
|
70
|
-
deletedAt: {
|
|
71
|
-
kind: 'datetime',
|
|
72
|
-
label: { en: 'Deleted at', ar: 'تاريخ الحذف' },
|
|
73
|
-
rules: { providedBy: { create: 'never', update: 'never' } },
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
targets: {
|
|
77
|
-
// Every organization's rows on the platform, read-only, and each row's
|
|
78
|
-
// record, which only reads. A record is titled by its student, a person the
|
|
79
|
-
// platform reads, where a session is titled only by its start.
|
|
80
|
-
platform: {
|
|
81
|
-
useAsTitle: 'student',
|
|
82
|
-
pages: {
|
|
83
|
-
...platformList('/enrollments', { columns: ['session', 'student', 'organization', 'createdAt'], filters: ['organization', 'session', 'student'], sort: '-createdAt' }),
|
|
84
|
-
...platformRecord({
|
|
85
|
-
path: '/enrollments/:id',
|
|
86
|
-
main: [{ section: 'enrollment', label: { en: 'Enrollment', ar: 'التسجيل' }, fields: ['session', 'student', 'deletedAt'] }],
|
|
87
|
-
}),
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
service: { operations: defaultOperations },
|
|
91
|
-
// Both screens list enrollments; the portal's create opens as a drawer over
|
|
92
|
-
// its list. Titled by the student on the dashboard, as on the platform, so a
|
|
93
|
-
// tab and a heading tell one seat from another; on the portal, where the
|
|
94
|
-
// student is most often the viewer, by the session.
|
|
95
|
-
dashboard: {
|
|
96
|
-
useAsTitle: 'student',
|
|
97
|
-
description: {
|
|
98
|
-
en: 'Which student holds a seat in which session.',
|
|
99
|
-
ar: 'أي طالب يشغل مقعدا في أي حصة.',
|
|
100
|
-
},
|
|
101
|
-
pages: {
|
|
102
|
-
// The same table every kayan's list is. Searched by the student's name,
|
|
103
|
-
// the one column of a person a tenant reads, and filtered by session,
|
|
104
|
-
// student and when the student enrolled, as the course list is.
|
|
105
|
-
list: { path: '/enrollments', page: appPage([{ layout: 'table', main: [{ list: {
|
|
106
|
-
columns: ['session', 'student', 'createdAt'],
|
|
107
|
-
filters: ['session', 'student', 'createdAt'],
|
|
108
|
-
search: ['student.name'],
|
|
109
|
-
} }] }]) },
|
|
110
|
-
create: { path: '/enrollments/new', page: appPage([{ layout: 'record', main: [{ form: enrollment }] }]) },
|
|
111
|
-
// The editor layout, and the one timestamp worth reading here, named and
|
|
112
|
-
// read-only: when the student enrolled, beside the organization it
|
|
113
|
-
// belongs to, read by its name.
|
|
114
|
-
edit: {
|
|
115
|
-
path: '/enrollments/:id',
|
|
116
|
-
page: appPage([{
|
|
117
|
-
layout: 'record',
|
|
118
|
-
main: [{ form: enrollment }],
|
|
119
|
-
side: [{ section: 'record', label: { en: 'Record', ar: 'السجل' }, fields: [{ field: 'organization', readOnly: true }, { field: 'createdAt', readOnly: true }] }, activity],
|
|
120
|
-
danger: danger(),
|
|
121
|
-
}]),
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
portal: {
|
|
126
|
-
useAsTitle: 'session',
|
|
127
|
-
pages: {
|
|
128
|
-
list: { path: '/enrollments', page: topPage([{ layout: 'page', main: [{ list: { columns: ['session', 'createdAt'] } }] }]) },
|
|
129
|
-
// The student too, as the dashboard draws it, so an instructor picks
|
|
130
|
-
// whom it enrolls. A role without `enrollments.fields.student` is not
|
|
131
|
-
// projected the field and is drawn the session alone.
|
|
132
|
-
create: { path: '/enrollments/new', mode: 'drawer', page: topPage([{ layout: 'page', main: [{ form: ['session', 'student'] }] }]) },
|
|
133
|
-
edit: { path: '/enrollments/:id', page: topPage([{ layout: 'page', main: [{ form: ['session'] }] }]) },
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
})
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// The Lexical node classes this project's rich text is written in: the one
|
|
2
|
-
// list both halves read, the server's write and every screen's editor and
|
|
3
|
-
// viewer, so neither can take a node the other does not. A node of the
|
|
4
|
-
// project's own is spread after the defaults, `[...defaultNodes, CalloutNode]`,
|
|
5
|
-
// and a node that draws React keeps its DOM-free class here and its React
|
|
6
|
-
// subclass in the client file. This project opts in to the upload node, an
|
|
7
|
-
// image of the organization's own `media` inside the text, whose server half
|
|
8
|
-
// refuses one pointing at a kayan that holds no files.
|
|
9
|
-
import { defaultNodes, UploadNode } from 'mithaq/rich-text'
|
|
10
|
-
|
|
11
|
-
export const richTextNodes = [...defaultNodes, UploadNode]
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// The subpath, so a page piece reading the fixed roles' labels loads no server code.
|
|
2
|
-
import { platformRoles } from '@asas/auth/platform-roles'
|
|
3
|
-
import type { SystemRoles } from 'mithaq'
|
|
4
|
-
import { tenantRoles } from './tenant-roles.ts'
|
|
5
|
-
|
|
6
|
-
export { tenantRoles }
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Every role this project ships, the platform's and the tenants', which is what
|
|
10
|
-
* the access target takes whole: it holds a slug's keys wherever the project's
|
|
11
|
-
* reader answers it. The platform roles are `@asas/auth`'s, because the column
|
|
12
|
-
* they live on is Better Auth's own `user.role` and the admin plugin's roles are
|
|
13
|
-
* built from the same lists. The reader answers them in the platform app alone,
|
|
14
|
-
* and an assignment never names one.
|
|
15
|
-
*/
|
|
16
|
-
export const systemRoles = { ...platformRoles, ...tenantRoles } as const satisfies SystemRoles
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// What every screen's rich text editor and viewer draw with: this project's
|
|
2
|
-
// own node list, the one its server parses every write with, each class swapped
|
|
3
|
-
// for its React subclass where one extends it, and the `/` menu's picks. A
|
|
4
|
-
// provider each screen names, so no control, read view or panel can take
|
|
5
|
-
// another list.
|
|
6
|
-
import type { ReactNode } from 'react'
|
|
7
|
-
import type { ProviderProps } from 'mithaq/admin'
|
|
8
|
-
import { RichTextContext, defaultPicks, defaultViews, viewsOf } from '@/components/mithaq/rich-text.tsx'
|
|
9
|
-
import { UploadPlugin, UploadView, imagePick } from '@/components/mithaq/upload.tsx'
|
|
10
|
-
import { richTextNodes } from '../rich-text-nodes.ts'
|
|
11
|
-
|
|
12
|
-
// The upload node's `/` entry "Image" opens its dialog in every editor.
|
|
13
|
-
const value = { nodes: viewsOf(richTextNodes, [...defaultViews, UploadView]), picks: [...defaultPicks, imagePick], Plugin: UploadPlugin }
|
|
14
|
-
|
|
15
|
-
export const RichTextNodes = ({ children }: ProviderProps<ReactNode>) => <RichTextContext value={value}>{children}</RichTextContext>
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
// The list's cell for the `slug` column. Rename is drawn only where this actor holds
|
|
2
|
-
// `organization.rename`, and members only where this actor reads them; the route refuses a rename
|
|
3
|
-
// without the key. A rename that lands asks the list behind it to be read again through
|
|
4
|
-
// `mithaq:refresh`, so the list keeps its scroll.
|
|
5
|
-
import { useState, type FormEvent } from 'react'
|
|
6
|
-
import { holds, type CellProps } from 'mithaq/admin'
|
|
7
|
-
import { useAccess, useLocale, useScreen } from 'mithaq/admin/react'
|
|
8
|
-
import { writeQuery } from '@/components/mithaq/list-query.ts'
|
|
9
|
-
import { Button } from '@/components/ui/button'
|
|
10
|
-
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
|
11
|
-
import { Input } from '@/components/ui/input'
|
|
12
|
-
import { Label } from '@/components/ui/label'
|
|
13
|
-
|
|
14
|
-
const slugShape = /^[a-z0-9]+(-[a-z0-9]+)*$/
|
|
15
|
-
|
|
16
|
-
export function OrganizationActions({ value, row }: CellProps) {
|
|
17
|
-
const { t } = useLocale()
|
|
18
|
-
const access = useAccess()
|
|
19
|
-
const screen = useScreen()
|
|
20
|
-
const renames = holds(access, 'organization.rename')
|
|
21
|
-
const members = holds(access, 'member.find') && screen.kayan.member?.pages.list !== undefined
|
|
22
|
-
const [open, setOpen] = useState(false)
|
|
23
|
-
const [refusal, setRefusal] = useState<string>()
|
|
24
|
-
const [done, setDone] = useState<string>()
|
|
25
|
-
/** Said here rather than by the browser's own bubble, which is in the browser's language. */
|
|
26
|
-
const [wrong, setWrong] = useState<{ name?: string; slug?: string }>({})
|
|
27
|
-
const id = String(row.id ?? '')
|
|
28
|
-
const save = async (event: FormEvent<HTMLFormElement>) => {
|
|
29
|
-
event.preventDefault()
|
|
30
|
-
const box = (key: string) => (event.currentTarget.elements.namedItem(key) as HTMLInputElement | null)?.value ?? ''
|
|
31
|
-
const name = box('name')
|
|
32
|
-
const slug = box('slug')
|
|
33
|
-
const found = {
|
|
34
|
-
name: name.trim() ? undefined : t('organization.name.required', 'This field is required.'),
|
|
35
|
-
slug: !slug ? t('organization.slug.required', 'This field is required.') : slugShape.test(slug) ? undefined : t('platform.slugPattern', 'A slug is lowercase letters and digits joined by single dashes, such as admin-org.'),
|
|
36
|
-
}
|
|
37
|
-
setWrong(found)
|
|
38
|
-
if (found.name || found.slug) return
|
|
39
|
-
const response = await fetch('/api/platform/organizations/update', {
|
|
40
|
-
method: 'POST',
|
|
41
|
-
headers: { 'content-type': 'application/json' },
|
|
42
|
-
body: JSON.stringify({ id, name, slug }),
|
|
43
|
-
})
|
|
44
|
-
if (!response.ok) {
|
|
45
|
-
const key = ((await response.json().catch(() => null)) as { data?: { key?: string } } | null)?.data?.key
|
|
46
|
-
return setRefusal((key && t(key)) ?? t('platform.refused', 'The platform refused that action.'))
|
|
47
|
-
}
|
|
48
|
-
window.dispatchEvent(new Event('mithaq:refresh'))
|
|
49
|
-
// A function, so a name holding `$&` is put in as written.
|
|
50
|
-
setDone((t('platform.renamed', 'The organization is now named {name}.') ?? '').replace('{name}', () => name))
|
|
51
|
-
}
|
|
52
|
-
return (
|
|
53
|
-
<div data-organization={id} className="flex items-center gap-2 whitespace-nowrap">
|
|
54
|
-
{/* An identifier, read left to right in either locale. */}
|
|
55
|
-
<span dir="ltr">{String(value ?? '')}</span>
|
|
56
|
-
{renames ? (
|
|
57
|
-
<Button size="sm" variant="outline" className="max-sm:h-11" data-action="rename" onClick={() => setOpen(true)}>
|
|
58
|
-
{t('platform.rename', 'Rename')}
|
|
59
|
-
</Button>
|
|
60
|
-
) : null}
|
|
61
|
-
{members ? (
|
|
62
|
-
<Button
|
|
63
|
-
size="sm"
|
|
64
|
-
variant="outline"
|
|
65
|
-
className="max-sm:h-11"
|
|
66
|
-
data-action="members"
|
|
67
|
-
nativeButton={false}
|
|
68
|
-
render={<a href={`${screen.path}${screen.kayan.member!.pages.list!.path}?${new URLSearchParams(writeQuery({ where: { or: [{ and: [{ organizationId: { equals: id } }] }] } }))}`} />}
|
|
69
|
-
>
|
|
70
|
-
{t('platform.members', 'Members')}
|
|
71
|
-
</Button>
|
|
72
|
-
) : null}
|
|
73
|
-
{open ? (
|
|
74
|
-
<Dialog open onOpenChange={setOpen}>
|
|
75
|
-
{/* Cancel is the way out, so the primitive's own close, named in
|
|
76
|
-
English alone, is not drawn beside it. */}
|
|
77
|
-
<DialogContent showCloseButton={false}>
|
|
78
|
-
<DialogHeader>
|
|
79
|
-
<DialogTitle>{t('platform.rename', 'Rename')}</DialogTitle>
|
|
80
|
-
<DialogDescription aria-live="polite">{done ?? t('platform.renameAbout', 'The new name and slug take the place of the old ones for everyone in this organization.')}</DialogDescription>
|
|
81
|
-
</DialogHeader>
|
|
82
|
-
{done ? (
|
|
83
|
-
<DialogFooter>
|
|
84
|
-
<DialogClose render={<Button type="button" variant="outline" />}>{t('admin.close', 'Close')}</DialogClose>
|
|
85
|
-
</DialogFooter>
|
|
86
|
-
) : (
|
|
87
|
-
<form noValidate onSubmit={(event) => void save(event)} className="grid gap-4">
|
|
88
|
-
<div className="grid gap-2">
|
|
89
|
-
<Label htmlFor={`organization-name-${id}`}>{t('organization.name', 'Name')}</Label>
|
|
90
|
-
<Input id={`organization-name-${id}`} name="name" required aria-required dir="auto" defaultValue={String(row.name ?? '')} aria-invalid={wrong.name ? true : undefined} aria-describedby={wrong.name ? `organization-name-${id}-error` : undefined} />
|
|
91
|
-
{wrong.name ? <p id={`organization-name-${id}-error`} role="alert" className="text-sm text-destructive">{wrong.name}</p> : null}
|
|
92
|
-
</div>
|
|
93
|
-
<div className="grid gap-2">
|
|
94
|
-
<Label htmlFor={`organization-slug-${id}`}>{t('organization.slug', 'Slug')}</Label>
|
|
95
|
-
<Input id={`organization-slug-${id}`} name="slug" required aria-required dir="ltr" pattern={slugShape.source.slice(1, -1)} defaultValue={String(value ?? '')} aria-invalid={wrong.slug ? true : undefined} aria-describedby={wrong.slug ? `organization-slug-${id}-error` : undefined} />
|
|
96
|
-
{wrong.slug ? <p id={`organization-slug-${id}-error`} role="alert" className="text-sm text-destructive">{wrong.slug}</p> : null}
|
|
97
|
-
</div>
|
|
98
|
-
{refusal ? (
|
|
99
|
-
<p role="alert" className="text-sm text-destructive">
|
|
100
|
-
{refusal}
|
|
101
|
-
</p>
|
|
102
|
-
) : null}
|
|
103
|
-
<DialogFooter>
|
|
104
|
-
<DialogClose render={<Button type="button" variant="outline" />}>{t('admin.cancel', 'Cancel')}</DialogClose>
|
|
105
|
-
<Button type="submit">{t('admin.save', 'Save')}</Button>
|
|
106
|
-
</DialogFooter>
|
|
107
|
-
</form>
|
|
108
|
-
)}
|
|
109
|
-
</DialogContent>
|
|
110
|
-
</Dialog>
|
|
111
|
-
) : null}
|
|
112
|
-
</div>
|
|
113
|
-
)
|
|
114
|
-
}
|