Skip to content

Commit

Permalink
feat: Add export plugin button in dev mode in AdminCP
Browse files Browse the repository at this point in the history
  • Loading branch information
aXenDeveloper committed Dec 9, 2024
1 parent 89ad465 commit 6a05401
Show file tree
Hide file tree
Showing 38 changed files with 340 additions and 104 deletions.
30 changes: 13 additions & 17 deletions apps/frontend/src/plugins/admin/langs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,7 @@
"desc": "We're detected changes in <bold>the plugin system</bold>. To apply these changes, you need to <bold>restart the server</bold>."
},
"dev": {
"overview": {
"title": "Overview"
},
"overview": "Overview",
"nav": {
"title": "Navigation in AdminCP",
"lang_key": "Lang Key: <key></key>",
Expand Down Expand Up @@ -363,6 +361,18 @@
"desc": "If you delete this permission, all children will be deleted too."
}
}
},
"export": {
"title": "Export Plugin",
"desc": "Choose version to export.",
"type": {
"rebuild": "Rebuild current version - {version}",
"new_version": "Create new version"
},
"version": "Version",
"version_code": "Version Code",
"success": "Plugin has been exported.",
"submit": "Export"
}
},
"create": {
Expand Down Expand Up @@ -411,20 +421,6 @@
"submit": "Yes, delete plugin",
"desc": "This action will delete <name></name> plugin created by <author></author> and all data associated with it.",
"info": "After the process is complete, you need to restart the server to apply the changes."
},
"download": {
"title": "Download Plugin",
"type": {
"rebuild": "Rebuild current version - {version}",
"new_version": "Create new version"
},
"version": {
"label": "Version"
},
"version_code": {
"label": "Version Code"
},
"submit": "Download"
}
},
"styles": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ShowNavPluginsAdminService } from './services/show.service';
plugin_code: 'plugins',
isAdmin: true,
route: 'nav',
isDev: true,
})
export class NavPluginsAdminController {
constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { ShowPermissionsAdminPluginsAdminService } from './services/show.service
plugin_code: 'plugins',
isAdmin: true,
route: 'permissions-admin',
isDev: true,
})
export class PermissionsAdminPluginsAdminController {
constructor(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Response } from 'express';

import { OnlyForDevelopment } from '@/guards/dev.guard';
import { Controllers } from '@/helpers/controller.decorator';
import {
Body,
Expand All @@ -10,6 +11,7 @@ import {
Put,
Query,
Res,
UseGuards,
} from '@nestjs/common';
import { ApiCreatedResponse, ApiOkResponse } from '@nestjs/swagger';
import { EditPluginsAdminBody } from 'vitnode-shared/admin/plugin.dto';
Expand Down Expand Up @@ -41,6 +43,7 @@ export class PluginsAdminController {

@ApiCreatedResponse({ description: 'Plugin created', type: ShowPluginAdmin })
@Post()
@UseGuards(OnlyForDevelopment)
async createPlugin(
@Body() body: CreatePluginsAdminBody,
): Promise<ShowPluginAdmin> {
Expand All @@ -49,6 +52,7 @@ export class PluginsAdminController {

@ApiOkResponse({ description: 'Plugin deleted' })
@Delete(':id')
@UseGuards(OnlyForDevelopment)
async deletePlugin(@Param('id') id: string): Promise<void> {
await this.deleteService.delete(+id);
}
Expand All @@ -66,7 +70,8 @@ export class PluginsAdminController {
}

@ApiOkResponse({ description: 'Plugin exported' })
@Post('export/:code')
@Post(':code/export')
@UseGuards(OnlyForDevelopment)
async exportPlugin(
@Param('code') code: string,
@Body() body: ExportPluginsAdminBody,
Expand Down
44 changes: 27 additions & 17 deletions packages/backend/src/core/admin/plugins/services/export.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ export class ExportPluginsAdminService {
});
}

// Check if version_code is greater than the current version_code
if (
version_code &&
configJSON.version_code &&
version_code <= configJSON.version_code
) {
return res.status(400).json({
message: 'Version code must be greater than the current version code',
});
}

configJSON.allow_default = allow_default;
configJSON.version = version ?? configJSON.version;
configJSON.version_code = version_code ?? configJSON.version_code;
Expand All @@ -70,23 +81,21 @@ export class ExportPluginsAdminService {
updated_at: new Date(),
})
.where(eq(core_plugins.code, code));

return;
} else {
await this.databaseService.db
.update(core_plugins)
.set({
version,
version_code,
allow_default,
updated_at: new Date(),
})
.where(eq(core_plugins.code, code));
}

await this.databaseService.db
.update(core_plugins)
.set({
version,
version_code,
allow_default,
updated_at: new Date(),
})
.where(eq(core_plugins.code, code));

// Prepare the export
const tempFolderName = removeSpecialCharacters(
`${code}-${version}-${generateRandomString(5)}-${currentUnixDate()}`,
`${code}-${version ?? plugin.version}-${generateRandomString(5)}-${currentUnixDate()}`,
);
const tempPath = join(this.tempPath, tempFolderName);
await mkdir(tempPath, { recursive: true });
Expand Down Expand Up @@ -135,10 +144,11 @@ export class ExportPluginsAdminService {

// Copy shared files
const sharedSource = ABSOLUTE_PATHS.plugin({ code }).shared;
if (!existsSync(sharedSource)) return;
const sharedPath = join(tempPath, 'shared');
await mkdir(sharedPath, { recursive: true });
await cp(sharedSource, sharedPath, { recursive: true });
if (existsSync(sharedSource)) {
const sharedPath = join(tempPath, 'shared');
await mkdir(sharedPath, { recursive: true });
await cp(sharedSource, sharedPath, { recursive: true });
}

// Create tar
const file = join(ABSOLUTE_PATHS.uploads.temp, `${tempFolderName}.tgz`);
Expand Down
7 changes: 7 additions & 0 deletions packages/backend/src/helpers/controller.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { AdminAuthGuard } from '@/guards/admin-auth.guard';
import { AuthGuard } from '@/guards/auth.guard';
import { OnlyForDevelopment } from '@/guards/dev.guard';
import { applyDecorators, Controller, UseGuards } from '@nestjs/common';
import { ApiSecurity, ApiTags } from '@nestjs/swagger';

interface Args {
isDev?: boolean;
plugin_code: string;
plugin_name: string;
route?: string;
Expand All @@ -30,9 +32,14 @@ export function Controllers({
isAdmin,
isProtect,
route,
isDev,
}: ArgsWithAdmin | ArgsWithout | ArgsWithProtect) {
const decorators = [Controller(`${plugin_code}${route ? `/${route}` : ''}`)];

if (isDev) {
decorators.push(UseGuards(OnlyForDevelopment));
}

if (isAdmin) {
decorators.push(
ApiTags(`Admin - ${plugin_name}`),
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const nestjsMainApp = async (app: INestApplication, options?: Args) => {
app.enableCors({
...options?.cors,
credentials: true,
exposedHeaders: ['Content-Disposition'],
origin: [
process.env.NEXT_PUBLIC_FRONTEND_URL ?? 'http://localhost:3000',
...(options?.cors?.origin ?? []),
Expand Down
4 changes: 4 additions & 0 deletions packages/frontend/src/api/fetcher-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export async function fetcherClient<
: null,
});

if (res.headers.get('Content-Disposition')) {
return { res, data: {} as TData };
}

let data = {} as TData;
try {
data = await res.json();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ export function FilterToolbarDataTable({
</PopoverTrigger>

<PopoverContent align="start" className="w-56 p-0">
<FilterToolbarDataTableContext.Provider value={{ title, id }}>
<FilterToolbarDataTableContext value={{ title, id }}>
<React.Suspense fallback={<Loader className="p-4" />}>
{children}
</React.Suspense>
</FilterToolbarDataTableContext.Provider>
</FilterToolbarDataTableContext>
</PopoverContent>
</Popover>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/components/editor/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export const Editor = ({
if (!editor) return null;

return (
<EditorStateContext.Provider
<EditorStateContext
value={{
editor,
value,
Expand Down Expand Up @@ -267,6 +267,6 @@ export const Editor = ({
setSelectedLanguage={setSelectedLanguage}
/>
</div>
</EditorStateContext.Provider>
</EditorStateContext>
);
};
4 changes: 2 additions & 2 deletions packages/frontend/src/components/ui/alert-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const AlertDialog = ({
const [open, setOpen] = React.useState(false);

return (
<AlertDialogContext.Provider
<AlertDialogContext
value={{ open: openProp ?? open, setOpen: onOpenChange ?? setOpen }}
>
<AlertDialogPrimitive.Root
Expand All @@ -37,7 +37,7 @@ const AlertDialog = ({
>
{children}
</AlertDialogPrimitive.Root>
</AlertDialogContext.Provider>
</AlertDialogContext>
);
};

Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/components/ui/carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function Carousel({
}, [api, onSelect]);

return (
<CarouselContext.Provider
<CarouselContext
value={{
carouselRef,
api: api,
Expand All @@ -123,7 +123,7 @@ function Carousel({
>
{children}
</div>
</CarouselContext.Provider>
</CarouselContext>
);
}

Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/components/ui/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const ChartContainer = ({
const chartId = `chart-${id ?? uniqueId.replace(/:/g, '')}`;

return (
<ChartContext.Provider value={{ config }}>
<ChartContext value={{ config }}>
<div
className={cn(
"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
Expand All @@ -64,7 +64,7 @@ const ChartContainer = ({
{children}
</RechartsPrimitive.ResponsiveContainer>
</div>
</ChartContext.Provider>
</ChartContext>
);
};

Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const Dialog = ({
const [isDirty, setIsDirty] = React.useState(false);

return (
<DialogContext.Provider
<DialogContext
value={{
open: openProp ?? open,
setOpen: val => {
Expand All @@ -50,7 +50,7 @@ const Dialog = ({
>
{children}
</DialogPrimitive.Root>
</DialogContext.Provider>
</DialogContext>
);
};

Expand Down
8 changes: 4 additions & 4 deletions packages/frontend/src/components/ui/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ const FormField = <
...props
}: ControllerProps<TFieldValues, TName>) => {
return (
<FormFieldContext.Provider value={{ name: props.name }}>
<FormFieldContext value={{ name: props.name }}>
<Controller {...props} />
</FormFieldContext.Provider>
</FormFieldContext>
);
};

Expand Down Expand Up @@ -111,9 +111,9 @@ const FormItem = ({
const id = React.useId();

return (
<FormItemContext.Provider value={{ id }}>
<FormItemContext value={{ id }}>
<div className={cn('space-y-2', className)} {...props} />
</FormItemContext.Provider>
</FormItemContext>
);
};

Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/components/ui/sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const Sheet = ({
const [open, setOpen] = React.useState(false);

return (
<SheetContext.Provider
<SheetContext
value={{
open: openProp ?? open,
setOpen: onOpenChange ?? setOpen,
Expand All @@ -41,7 +41,7 @@ const Sheet = ({
>
{children}
</SheetPrimitive.Root>
</SheetContext.Provider>
</SheetContext>
);
};

Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/components/ui/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ const SidebarProvider = ({
);

return (
<SidebarContext.Provider value={contextValue}>
<SidebarContext value={contextValue}>
<TooltipProvider delayDuration={0}>
<div
className={cn(
Expand All @@ -148,7 +148,7 @@ const SidebarProvider = ({
{children}
</div>
</TooltipProvider>
</SidebarContext.Provider>
</SidebarContext>
);
};

Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/components/ui/toggle-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ const ToggleGroup = ({
className={cn('flex items-center justify-center gap-1', className)}
{...props}
>
<ToggleGroupContext.Provider value={{ variant, size }}>
<ToggleGroupContext value={{ variant, size }}>
{children}
</ToggleGroupContext.Provider>
</ToggleGroupContext>
</ToggleGroupPrimitive.Root>
);

Expand Down
Loading

0 comments on commit 6a05401

Please sign in to comment.