Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ export default function AuthLayout({children}: Readonly<{ children: React.ReactN
width={40}
height={40}/>
<Spacing spacing={"xl"}/>
<Text style={{fontSize: "2rem", fontWeight: "600", lineHeight: "1"}}
<Text style={{fontSize: "2rem", fontWeight: "600"}}
hierarchy={"primary"}
display={"inline-block"}>
display={"inline"}>
Every great idea starts at zero. {" "}
<Text style={{fontSize: "2rem", fontWeight: "600", lineHeight: "1"}}
hierarchy={"tertiary"} display={"inline"}>
Start with CodeZero.
</Text>
</Text>
<Text style={{fontSize: "2rem", fontWeight: "600"}}
hierarchy={"tertiary"} display={"inline"}>
Start with CodeZero.
</Text>
<Spacing spacing={"xl"}/>
{children}
Expand Down
2 changes: 1 addition & 1 deletion src/app/(dashboard)/@bar/default.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React from "react";
import {ApplicationBarView} from "@edition/application/ApplicationBarView";
import {ApplicationBarView} from "@edition/application/views/ApplicationBarView";

const Page = () => {
return <ApplicationBarView/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(dashboard)/@tab/organizations/default.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import React from "react";
import {ApplicationTabView} from "@edition/application/ApplicationTabView";
import {ApplicationTabView} from "@edition/application/views/ApplicationTabView";

const Page: React.FC = () => {
return <ApplicationTabView/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(dashboard)/@tab/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import React from "react";
import {ApplicationTabView} from "@edition/application/ApplicationTabView";
import {ApplicationTabView} from "@edition/application/views/ApplicationTabView";

const Page: React.FC = () => {
return <ApplicationTabView/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(dashboard)/@tab/runtimes/default.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import React from "react";
import {ApplicationTabView} from "@edition/application/ApplicationTabView";
import {ApplicationTabView} from "@edition/application/views/ApplicationTabView";

const Page: React.FC = () => {
return <ApplicationTabView/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(dashboard)/@tab/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import React from "react";
import {ApplicationTabView} from "@edition/application/ApplicationTabView";
import {ApplicationTabView} from "@edition/application/views/ApplicationTabView";

const Page: React.FC = () => {
return <ApplicationTabView/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(dashboard)/@tab/users/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import React from "react";
import {ApplicationTabView} from "@edition/application/ApplicationTabView";
import {ApplicationTabView} from "@edition/application/views/ApplicationTabView";

const Page: React.FC = () => {
return <ApplicationTabView/>
Expand Down
4 changes: 3 additions & 1 deletion src/app/(dashboard)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {RuntimeService} from "@edition/runtime/services/Runtime.service";
import {ProjectService} from "@edition/project/services/Project.service";
import {RoleService} from "@edition/role/services/Role.service";
import Image from "next/image";
import {Application, ApplicationService} from "@edition/application/services/Application.service";

interface ApplicationLayoutProps {
children: React.ReactNode
Expand All @@ -49,10 +50,11 @@ const ApplicationLayout: React.FC<ApplicationLayoutProps> = ({children, bar, tab
const runtime = usePersistentReactiveArrayService<DRuntimeView, RuntimeService>(`dashboard::global_runtimes::${currentSession?.id}`, (store) => new RuntimeService(graphqlClient, store))
const project = usePersistentReactiveArrayService<DNamespaceProjectView, ProjectService>(`dashboard::projects::${currentSession?.id}`, (store) => new ProjectService(graphqlClient, store))
const role = usePersistentReactiveArrayService<DNamespaceRoleView, RoleService>(`dashboard::roles::${currentSession?.id}`, (store) => new RoleService(graphqlClient, store))
const application = usePersistentReactiveArrayService<Application, ApplicationService>(`dashboard::application::${currentSession?.id}`, (store) => new ApplicationService(graphqlClient, store))

if (currentSession === null) router.push("/login")

return <ContextStoreProvider services={[user, organization, member, namespace, runtime, project, role]}>
return <ContextStoreProvider services={[user, organization, member, namespace, runtime, project, role, application]}>
<DLayout style={{zIndex: 0}} layoutGap={"0"} showLayoutSplitter={false} leftContent={
<Flex p={0.7} pt={1} align={"center"} style={{flexDirection: "column", gap: "0.7rem"}}>
<div style={{
Expand Down
2 changes: 1 addition & 1 deletion src/app/(dashboard)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import React from "react";
import {ApplicationPage} from "@edition/application/ApplicationPage";
import {ApplicationPage} from "@edition/application/pages/ApplicationPage";

export default function Page() {
return <ApplicationPage/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(dashboard)/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import React from "react";
import {ApplicationSettingsPage} from "@edition/application/ApplicationSettingsPage";
import {ApplicationSettingsPage} from "@edition/application/pages/ApplicationSettingsPage";

export default function Page() {

Expand Down
2 changes: 1 addition & 1 deletion src/app/(flow)/@bar/default.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React from "react";
import {ApplicationBarView} from "@edition/application/ApplicationBarView";
import {ApplicationBarView} from "@edition/application/views/ApplicationBarView";

const Page = () => {
return <ApplicationBarView/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import React from "react";
import React, {startTransition} from "react";
import {
Badge,
Button,
Expand All @@ -11,7 +11,9 @@ import {
Flex,
Spacing,
SwitchInput,
Text,
Text, TextInput,
toast,
useForm,
useService,
useStore,
useUserSession
Expand All @@ -21,18 +23,68 @@ import {notFound} from "next/navigation";
import {Tab, TabContent, TabList, TabTrigger} from "@code0-tech/pictor/dist/components/tab/Tab";
import {IconLayoutSidebar} from "@tabler/icons-react";
import CardSection from "@code0-tech/pictor/dist/components/card/CardSection";
import process from "node:process";
import {ApplicationService} from "@edition/application/services/Application.service";

export const ApplicationSettingsPage: React.FC = () => {
const currentSession = useUserSession()

const userStore = useStore(UserService)
const userService = useService(UserService)
const currentUser = React.useMemo(() => userService.getById(currentSession?.user?.id), [userStore, currentSession])
const applicationService = useService(ApplicationService)
const applicationStore = useStore(ApplicationService)

const currentSession = useUserSession()

const currentUser = React.useMemo(
() => userService.getById(currentSession?.user?.id),
[userStore, currentSession]
)

const application = React.useMemo(
() => applicationService.get(),
[applicationStore]
)

if (currentUser && !currentUser.admin) {
notFound()
}

const initialValues = React.useMemo(
() => ({
adminStatusVisible: application?.settings?.adminStatusVisible,
organizationCreationRestricted: application?.settings?.organizationCreationRestricted,
userRegistrationEnabled: application?.settings?.userRegistrationEnabled,
legalNoticeUrl: !!application?.settings?.legalNoticeUrl ? application?.settings?.legalNoticeUrl : null,
privacyUrl: !!application?.settings?.privacyUrl ? application?.settings?.privacyUrl : null,
termsAndConditionsUrl: !!application?.settings?.termsAndConditionsUrl ? application?.settings?.termsAndConditionsUrl : null,
}),
[application]
)

const [inputs, validate] = useForm({
initialValues: initialValues,
validate: {},
onSubmit: (values) => {
startTransition(() => {
applicationService.applicationUpdate({
adminStatusVisible: values.adminStatusVisible,
organizationCreationRestricted: values.organizationCreationRestricted,
userRegistrationEnabled: values.userRegistrationEnabled,
legalNoticeUrl: !!values.legalNoticeUrl ? values.legalNoticeUrl : null,
privacyUrl: !!values.privacyUrl ? values.privacyUrl : null,
termsAndConditionsUrl: !!values.termsAndConditionsUrl ? values.termsAndConditionsUrl : null,
}).then(payload => {
if ((payload?.errors?.length ?? 0) <= 0) {
toast({
title: "The application was successfully updated.",
color: "success",
dismissible: true,
})
}
})
})
}
})

return <Tab orientation={"vertical"} defaultValue={"general"} h={"100%"}>
<DResizablePanelGroup>
<DResizablePanel id={"1"} defaultSize={"20%"} collapsedSize={"0%"}
Expand Down Expand Up @@ -88,7 +140,7 @@ export const ApplicationSettingsPage: React.FC = () => {
library</Text>
</Flex>
<Badge
color={"info"}>{process.env.NEXT_PUBLIC_pictorVersion ?? "v0.0.0-mvp.10"}</Badge>
color={"info"}>v0.0.0-mvp.10</Badge>
</Flex>
</CardSection>
<CardSection border>
Expand All @@ -101,9 +153,44 @@ export const ApplicationSettingsPage: React.FC = () => {
</Flex>
</CardSection>
</Card>
<Spacing spacing={"xl"}/>
<Flex justify={"space-between"} align={"center"}>
<Text size={"lg"} hierarchy={"primary"}>Legal url's</Text>
<Button color={"success"} onClick={validate}>Save</Button>
</Flex>
<Spacing spacing={"xl"}/>
<Card color={"secondary"}>
<CardSection border>
<Flex justify={"space-between"} align={"center"}>
<Flex style={{gap: ".35rem", flexDirection: "column"}}>
<Text size={"md"} hierarchy={"primary"}>Legal notice url</Text>
</Flex>
<TextInput {...inputs.getInputProps("legalNoticeUrl")}/>
</Flex>
</CardSection>
<CardSection border>
<Flex justify={"space-between"} align={"center"}>
<Flex style={{gap: ".35rem", flexDirection: "column"}}>
<Text size={"md"} hierarchy={"primary"}>Privacy information url</Text>
</Flex>
<TextInput {...inputs.getInputProps("privacyUrl")}/>
</Flex>
</CardSection>
<CardSection border>
<Flex justify={"space-between"} align={"center"}>
<Flex style={{gap: ".35rem", flexDirection: "column"}}>
<Text size={"md"} hierarchy={"primary"}>Terms and conditions url</Text>
</Flex>
<TextInput {...inputs.getInputProps("termsAndConditionsUrl")}/>
</Flex>
</CardSection>
</Card>
</TabContent>
<TabContent value={"restrictions"}>
<Text size={"xl"} hierarchy={"primary"}>Restrictions</Text>
<Flex justify={"space-between"} align={"center"}>
<Text size={"xl"} hierarchy={"primary"}>Restrictions</Text>
<Button color={"success"} onClick={validate}>Save</Button>
</Flex>
<Spacing spacing={"xl"}/>
<Card color={"secondary"}>
<CardSection border>
Expand All @@ -115,7 +202,8 @@ export const ApplicationSettingsPage: React.FC = () => {
to
administrators.</Text>
</Flex>
<SwitchInput w={"40px"}/>
<SwitchInput w={"40px"}
{...inputs.getInputProps("organizationCreationRestricted")}/>
</Flex>
</CardSection>
<CardSection border>
Expand All @@ -125,7 +213,18 @@ export const ApplicationSettingsPage: React.FC = () => {
<Text size={"md"} hierarchy={"tertiary"}>Set if user registration is
enabled.</Text>
</Flex>
<SwitchInput w={"40px"}/>
<SwitchInput w={"40px"}
{...inputs.getInputProps("userRegistrationEnabled")}/>
</Flex>
</CardSection>
<CardSection border>
<Flex justify={"space-between"} align={"center"}>
<Flex style={{gap: ".35rem", flexDirection: "column"}}>
<Text size={"md"} hierarchy={"primary"}>Admin status</Text>
<Text size={"md"} hierarchy={"tertiary"}>Set if users can se who is admin</Text>
</Flex>
<SwitchInput w={"40px"}
{...inputs.getInputProps("adminStatusVisible")}/>
</Flex>
</CardSection>
</Card>
Expand Down
67 changes: 67 additions & 0 deletions src/packages/ce/src/application/services/Application.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {ReactiveArrayService, ReactiveArrayStore} from "@code0-tech/pictor";
import {
Application as SApplication,
ApplicationSettingsUpdateInput,
ApplicationSettingsUpdatePayload,
Mutation,
Query
} from "@code0-tech/sagittarius-graphql-types";
import {Payload, View} from "@code0-tech/pictor/dist/utils/view";
import {GraphqlClient} from "@core/util/graphql-client";
import applicationQuery from "@edition/application/services/queries/Application.query.graphql"
import applicationUpdateMutation from "@edition/application/services/mutations/Application.update.mutation.graphql"

export type Application = SApplication & Payload

export class ApplicationService extends ReactiveArrayService<Application> {

private readonly client: GraphqlClient

constructor(client: GraphqlClient, store: ReactiveArrayStore<View<Application>>) {
super(store);
this.client = client
}


get(): SApplication {

const application = super.get(0)

if (!application) {
this.client.query<Query>({
query: applicationQuery
}).then(res => {
const app = res.data?.application
if (app) this.set(0, new View(app as Application))
})
}

return application

}

async applicationUpdate(payload: ApplicationSettingsUpdateInput): Promise<ApplicationSettingsUpdatePayload | undefined> {
const result = await this.client.mutate<Mutation, ApplicationSettingsUpdateInput>({
mutation: applicationUpdateMutation,
variables: {
...payload
}
})

if (result.data && result.data.applicationSettingsUpdate && result.data.applicationSettingsUpdate.applicationSettings) {
const application = this.get()
this.set(0, new View({
...application,
legalNoticeUrl: result.data.applicationSettingsUpdate.applicationSettings.legalNoticeUrl,
privacyUrl: result.data.applicationSettingsUpdate.applicationSettings.privacyUrl,
termsAndConditionsUrl: result.data.applicationSettingsUpdate.applicationSettings.termsAndConditionsUrl,
settings: {
...result.data.applicationSettingsUpdate.applicationSettings
}
} as Application))

}

return result.data?.applicationSettingsUpdate ?? undefined
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
fragment Application on Application {
__typename
metadata {
__typename
extensions
version
}
legalNoticeUrl
privacyUrl
termsAndConditionsUrl
settings {
__typename
termsAndConditionsUrl
privacyUrl
legalNoticeUrl
adminStatusVisible
organizationCreationRestricted
userRegistrationEnabled
}
userAbilities {
__typename
createOrganization
createRuntime
deleteRuntime
rotateRuntimeToken
updateApplicationSetting
updateRuntime
}
}
Loading