Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Configuration variable editor (WIP) #449

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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: 11 additions & 1 deletion apps/backend/src/api/routes/settings.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Sections,
} from '@gitroom/backend/services/auth/permissions/permissions.service';
import { OrganizationService } from '@gitroom/nestjs-libraries/database/prisma/organizations/organization.service';
import { ConfigurationVariableService } from '@gitroom/nestjs-libraries/database/prisma/configuration/configuration.variable.service';
import {AddTeamMemberDto} from "@gitroom/nestjs-libraries/dtos/settings/add.team.member.dto";
import {ApiTags} from "@nestjs/swagger";

Expand All @@ -16,9 +17,18 @@ import {ApiTags} from "@nestjs/swagger";
export class SettingsController {
constructor(
private _starsService: StarsService,
private _organizationService: OrganizationService
private _organizationService: OrganizationService,
private _configurationVariableService: ConfigurationVariableService
) {}

@Get('/cvars/all')
@CheckPolicies([AuthorizationActions.Create, Sections.ADMIN])
async getConfigurationVariables() {
return {
configurationVariables: await this._configurationVariableService.getAll(),
};
}

@Get('/github')
@CheckPolicies([AuthorizationActions.Create, Sections.ADMIN])
async getConnectedGithubAccounts(@GetOrgFromRequest() org: Organization) {
Expand Down
16 changes: 6 additions & 10 deletions apps/frontend/src/components/layout/top.menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,12 @@ export const useMenuItems = () => {
},
]
: []),
...(!isGeneral
? [
{
name: 'Settings',
icon: 'settings',
path: '/settings',
role: ['ADMIN', 'SUPERADMIN'],
},
]
: []),
{
name: 'Settings',
icon: 'settings',
path: '/settings',
role: ['ADMIN', 'SUPERADMIN'],
},
{
name: 'Marketplace',
icon: 'marketplace',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use client';

// import { FormProvider, SubmitHandler, useForm } from 'react-hook-form';
// import { useMemo } from 'react';
// import { classValidatorResolver } from '@hookform/resolvers/class-validator';
// import { SaveConfigurationVariableDto, SaveConfigurationVariablesDto } from '@gitroom/nestjs-libraries/dtos/settings/configuration-variables.dto.ts';
import { Button } from '@gitroom/react/form/button'
import { useCallback, useState } from 'react'
import useSWR from 'swr'
import { useFetch } from '@gitroom/helpers/utils/custom.fetch'

export const ConfigurationVariableEditorComponent = () => {
// const resolver = useMemo(() => classValidatorResolver(SaveConfigurationVariableDto), []);

const fetch = useFetch();

// const form = useForm({ resolver, values: { message: '' } });

const [state, setState] = useState(true);

Check warning

Code scanning / ESLint

Disallow unused variables Warning

'state' is assigned a value but never used.

Copilot Autofix AI 2 days ago

To fix the problem, we need to remove the unused state variable and its associated useState hook. This will eliminate the ESLint error and make the code cleaner and more efficient.

  • Remove the const [state, setState] = useState(true); line from the code.
  • Ensure that any other references to state or setState are also removed, although in this case, there are none.
Suggested changeset 1
apps/frontend/src/components/settings/configuration-variable-editor.component.tsx

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/apps/frontend/src/components/settings/configuration-variable-editor.component.tsx b/apps/frontend/src/components/settings/configuration-variable-editor.component.tsx
--- a/apps/frontend/src/components/settings/configuration-variable-editor.component.tsx
+++ b/apps/frontend/src/components/settings/configuration-variable-editor.component.tsx
@@ -18,3 +18,2 @@
 
-  const [state, setState] = useState(true);
 
EOF
@@ -18,3 +18,2 @@

const [state, setState] = useState(true);

Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options

const fetchCvars = useCallback(async () => {
const cvars = await (
await fetch('/settings/cvars/all', {
method: 'GET',
})
).json();

setState(cvars);
return cvars;
}, [])

Check warning

Code scanning / ESLint

verifies the list of dependencies for Hooks like useEffect and similar Warning

React Hook useCallback has a missing dependency: 'fetch'. Either include it or remove the dependency array.

const { data, error, isLoading } = useSWR('/settings/cvars/all', fetchCvars)

/*
const submit: SubmitHandler<SaveConfigurationVariableDto> = async (data) => {
Fixed Show fixed Hide fixed
await fetch(`/settings/cvars/${params.id}`, {
method: 'POST',
body: JSON.stringify(data),
});
mutate();
form.reset();
}
*/

if (isLoading) return <div>Loading...</div>
if (error) return <div className = "text-red-700">Error loading data</div>

return (
<div>
<h3 className = "text-[20px] mb-[6px]">Configuration Variable Editor</h3>
<p className = "mb-[12px]">This screen is only accessible and editable by super admins, it includes configuration that effects the entire app. </p>

{data.configurationVariables.map((cvar) => (
<div className = "grid grid-cols-2 p-1" key={cvar.description}>
<div>
<label className = "">
<strong className = "font-bold"><abbr title = {cvar.key}>{cvar.title}</abbr></strong>
</label>
<p className = "text-customColor18">{cvar.description}</p>

{cvar.docs && (
<a href = {cvar.docs} target = "_blank" className = "text-customColor4">More docs...</a>
)}
</div>
<div className="">
{cvar.datatype === 'bool' ? (
<input type = "checkbox" name = "" value = "1"></input>
) : (
<input className="bg-input border border-fifth rounded-[4px] text-inputText flex-grow p-1" name="{...form.register(cvar.key)}" value="?" autocomplete="off"></input>
)}
</div>
</div>
))}

<Button className = "rounded-[4px]">Save</Button>

</div>
)
}
4 changes: 4 additions & 0 deletions apps/frontend/src/components/settings/settings.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { GithubComponent } from '@gitroom/frontend/components/settings/github.co
import { useCallback, useEffect } from 'react';
import { useUser } from '@gitroom/frontend/components/layout/user.context';
import { TeamsComponent } from '@gitroom/frontend/components/settings/teams.component';
import { ConfigurationVariableEditorComponent } from '@gitroom/frontend/components/settings/configuration-variable-editor.component';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import useSWR from 'swr';
import { LoadingComponent } from '@gitroom/frontend/components/layout/loading';
Expand Down Expand Up @@ -70,6 +71,9 @@ export const SettingsComponent = () => {
{/*</div>*/}
</div>
)}

<ConfigurationVariableEditorComponent />

{!!user?.tier?.team_members && <TeamsComponent />}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { PrismaRepository } from '@gitroom/nestjs-libraries/database/prisma/prisma.service';
import { Injectable } from '@nestjs/common';

@Injectable()
export class ConfigurationVariableRepository {
constructor(
private _configurationVariables: PrismaRepository<'configurationVariables'>
) {}

getOrDefault(key: string, defaultValue: string) {
const dbVal = this._configurationVariables.model.configurationVariables.findFirst({
where: {
key,
},
});

if (dbVal) {
return dbVal;
} else {
return defaultValue;
}
}

isSet(key: string) {
return !!this._configurationVariables.model.configurationVariables.findFirst({
where: {
key,
},
});
}

set(key: string, value: string) {
return this._configurationVariables.model.configurationVariables.create({
data: {
key,
value,
},
});
}

getAll() {
return this._configurationVariables.model.configurationVariables.findMany();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Injectable } from '@nestjs/common';

import { ConfigurationVariableRepository } from '@gitroom/nestjs-libraries/database/prisma/configuration/configuration.variable.repository';

@Injectable()
export class ConfigurationVariableService {
private cvars: {
key: string,
title: string,
description: string,
datatype: string,
default: string | null,
val: string | null,
section: string[],
docs?: string,
}[];

constructor(
private _configurationVariableRepository: ConfigurationVariableRepository,
) {
this.cvars = [
{
key: 'USER_REGISTRATION_DISABLED',
title: 'Disable user registration',
description: 'If user registration is disabled, only super admins can create new users',
datatype: 'bool',
default: 'true',
val: 'true',
section: ['Functionality'],
},
{
key: 'MARKETPLACE_DISABLED',
title: 'Disable marketplace',
description: 'If the marketplace is disabled, users will not be able to buy or sell posts',
datatype: 'bool',
default: 'true',
val: 'true',
section: ['Functionality'],
},
{
key: 'DISCORD_CLIENT_ID',
title: 'Discord client ID',
description: 'Used to authenticate with Discord with OAuth.',
docs: 'https://docs.postiz.com/providers/discord',
datatype: 'string',
default: null,
val: null,
section: ['Providers', 'Discord'],
},
{
key: 'DISCORD_CLIENT_SECRET',
title: 'Discord client secret',
description: 'Used to authenticate with Discord with OAuth.',
datatype: 'string',
default: null,
val: null,
section: ['Providers', 'Discord'],
},
]
}

getOrDefault(key: string, defaultValue: string) {
return this._configurationVariableRepository.getOrDefault(key, defaultValue);
}

getOrEmpty(key: string) {
return this._configurationVariableRepository.getOrDefault(key, '');
}

isSet(key: string) {
return this._configurationVariableRepository.isSet(key);
}

set(key: string, value: string) {
return this._configurationVariableRepository.set(key, value);
}

getAll() {
return this.cvars;
// return this._configurationVariableRepository.getAll();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Global, Module } from '@nestjs/common';
import { PrismaRepository, PrismaService } from './prisma.service';
import { OrganizationRepository } from '@gitroom/nestjs-libraries/database/prisma/organizations/organization.repository';
import { OrganizationService } from '@gitroom/nestjs-libraries/database/prisma/organizations/organization.service';
import { ConfigurationVariableRepository } from '@gitroom/nestjs-libraries/database/prisma/configuration/configuration.variable.repository';
import { ConfigurationVariableService } from '@gitroom/nestjs-libraries/database/prisma/configuration/configuration.variable.service';
import { UsersService } from '@gitroom/nestjs-libraries/database/prisma/users/users.service';
import { UsersRepository } from '@gitroom/nestjs-libraries/database/prisma/users/users.repository';
import { StarsService } from '@gitroom/nestjs-libraries/database/prisma/stars/stars.service';
Expand Down Expand Up @@ -41,6 +43,8 @@ import { AgenciesRepository } from '@gitroom/nestjs-libraries/database/prisma/ag
UsersRepository,
OrganizationService,
OrganizationRepository,
ConfigurationVariableService,
ConfigurationVariableRepository,
StarsService,
StarsRepository,
SubscriptionService,
Expand Down
9 changes: 8 additions & 1 deletion libraries/nestjs-libraries/src/database/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,13 @@ model Messages {
@@index([deletedAt])
}

model ConfigurationVariables {
key String @unique
value String

@@index([key])
}

enum OrderStatus {
PENDING
ACCEPTED
Expand Down Expand Up @@ -486,4 +493,4 @@ enum APPROVED_SUBMIT_FOR_ORDER {
NO
WAITING_CONFIRMATION
YES
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {IsDefined, IsString, ValidateNested} from 'class-validator';
import {Type} from 'class-transformer';

export class SaveConfigurationVariableDto {
@IsString()
key: string;

@IsString()
val: string;
}

export class SaveConfigurationVariablesDto {
@ValidateNested({each: true})
@Type(() => ConfigurationVariableDto)
configurationVariables: Record<string, ConfigurationVariableDto>;
}
Loading