Start working towards a consistent model/transformer layout
This commit is contained in:
parent
9f934b5ab8
commit
a00fee5516
17 changed files with 303 additions and 267 deletions
|
@ -150,6 +150,7 @@
|
|||
"svg-url-loader": "^7.1.1",
|
||||
"tailwindcss": "^3.0.23",
|
||||
"terser-webpack-plugin": "^4.2.3",
|
||||
"ts-essentials": "^9.1.2",
|
||||
"twin.macro": "^2.8.2",
|
||||
"typescript": "^4.4.4",
|
||||
"webpack": "^4.46.0",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Model, UUID, WithRelationships, withRelationships } from '@/api/admin/index';
|
||||
import { Nest } from '@/api/admin/nest';
|
||||
import http, { QueryBuilderParams, withQueryBuilderParams } from '@/api/http';
|
||||
import { AdminTransformers } from '@/api/admin/transformers';
|
||||
import Transformers from '@definitions/admin/transformers';
|
||||
import { AxiosError } from 'axios';
|
||||
import { useRouteMatch } from 'react-router-dom';
|
||||
import useSWR, { SWRResponse } from 'swr';
|
||||
|
@ -64,7 +64,7 @@ export const getEgg = async (id: number | string): Promise<LoadedEgg> => {
|
|||
},
|
||||
});
|
||||
|
||||
return withRelationships(AdminTransformers.toEgg(data), 'nest', 'variables');
|
||||
return withRelationships(Transformers.toEgg(data), 'nest', 'variables');
|
||||
};
|
||||
|
||||
export const searchEggs = async (nestId: number, params: QueryBuilderParams<'name'>): Promise<WithRelationships<Egg, 'variables'>[]> => {
|
||||
|
@ -75,7 +75,7 @@ export const searchEggs = async (nestId: number, params: QueryBuilderParams<'nam
|
|||
},
|
||||
});
|
||||
|
||||
return data.data.map(AdminTransformers.toEgg);
|
||||
return data.data.map(Transformers.toEgg);
|
||||
};
|
||||
|
||||
export const exportEgg = async (eggId: number): Promise<Record<string, any>> => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import http from '@/api/http';
|
||||
import { EggVariable } from '@/api/admin/egg';
|
||||
import { AdminTransformers } from '@/api/admin/transformers';
|
||||
import Transformers from '@definitions/admin/transformers';
|
||||
|
||||
export type CreateEggVariable = Omit<EggVariable, 'id' | 'eggId' | 'createdAt' | 'updatedAt' | 'relationships'>;
|
||||
|
||||
|
@ -18,5 +18,5 @@ export default async (eggId: number, variable: CreateEggVariable): Promise<EggVa
|
|||
},
|
||||
);
|
||||
|
||||
return AdminTransformers.toEggVariable(data);
|
||||
return Transformers.toEggVariable(data);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import http from '@/api/http';
|
||||
import { EggVariable } from '@/api/admin/egg';
|
||||
import { AdminTransformers } from '@/api/admin/transformers';
|
||||
import Transformers from '@definitions/admin/transformers';
|
||||
|
||||
export default async (eggId: number, variables: Omit<EggVariable, 'eggId' | 'createdAt' | 'updatedAt'>[]): Promise<EggVariable[]> => {
|
||||
const { data } = await http.patch(
|
||||
|
@ -17,5 +17,5 @@ export default async (eggId: number, variables: Omit<EggVariable, 'eggId' | 'cre
|
|||
})),
|
||||
);
|
||||
|
||||
return data.data.map(AdminTransformers.toEggVariable);
|
||||
return data.data.map(Transformers.toEggVariable);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Model, UUID } from '@/api/admin/index';
|
||||
import { Egg } from '@/api/admin/egg';
|
||||
import http, { QueryBuilderParams, withQueryBuilderParams } from '@/api/http';
|
||||
import { AdminTransformers } from '@/api/admin/transformers';
|
||||
import Transformers from '@definitions/admin/transformers';
|
||||
|
||||
export interface Nest extends Model {
|
||||
id: number;
|
||||
|
@ -21,5 +21,5 @@ export const searchNests = async (params: QueryBuilderParams<'name'>): Promise<N
|
|||
params: withQueryBuilderParams(params),
|
||||
});
|
||||
|
||||
return data.data.map(AdminTransformers.toNest);
|
||||
return data.data.map(Transformers.toNest);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Model, UUID, WithRelationships, withRelationships } from '@/api/admin/index';
|
||||
import { Location } from '@/api/admin/location';
|
||||
import http, { QueryBuilderParams, withQueryBuilderParams } from '@/api/http';
|
||||
import { AdminTransformers } from '@/api/admin/transformers';
|
||||
import Transformers from '@definitions/admin/transformers';
|
||||
import { Server } from '@/api/admin/server';
|
||||
|
||||
interface NodePorts {
|
||||
|
@ -64,7 +64,7 @@ export const getNode = async (id: string | number): Promise<WithRelationships<No
|
|||
},
|
||||
});
|
||||
|
||||
return withRelationships(AdminTransformers.toNode(data.data), 'location');
|
||||
return withRelationships(Transformers.toNode(data.data), 'location');
|
||||
};
|
||||
|
||||
export const searchNodes = async (params: QueryBuilderParams<'name'>): Promise<Node[]> => {
|
||||
|
@ -72,7 +72,7 @@ export const searchNodes = async (params: QueryBuilderParams<'name'>): Promise<N
|
|||
params: withQueryBuilderParams(params),
|
||||
});
|
||||
|
||||
return data.data.map(AdminTransformers.toNode);
|
||||
return data.data.map(Transformers.toNode);
|
||||
};
|
||||
|
||||
export const getAllocations = async (id: string | number, params?: QueryBuilderParams<'ip' | 'server_id'>): Promise<Allocation[]> => {
|
||||
|
@ -80,5 +80,5 @@ export const getAllocations = async (id: string | number, params?: QueryBuilderP
|
|||
params: withQueryBuilderParams(params),
|
||||
});
|
||||
|
||||
return data.data.map(AdminTransformers.toAllocation);
|
||||
return data.data.map(Transformers.toAllocation);
|
||||
};
|
||||
|
|
|
@ -3,9 +3,9 @@ import { AxiosError } from 'axios';
|
|||
import { useRouteMatch } from 'react-router-dom';
|
||||
import http from '@/api/http';
|
||||
import { Model, UUID, withRelationships, WithRelationships } from '@/api/admin/index';
|
||||
import { AdminTransformers } from '@/api/admin/transformers';
|
||||
import Transformers from '@definitions/admin/transformers';
|
||||
import { Allocation, Node } from '@/api/admin/node';
|
||||
import { User } from '@/api/admin/user';
|
||||
import { User } from '@definitions/admin/models';
|
||||
import { Egg, EggVariable } from '@/api/admin/egg';
|
||||
import { Nest } from '@/api/admin/nest';
|
||||
|
||||
|
@ -83,7 +83,7 @@ export const getServer = async (id: number | string): Promise<LoadedServer> => {
|
|||
},
|
||||
});
|
||||
|
||||
return withRelationships(AdminTransformers.toServer(data), 'allocations', 'user', 'node', 'variables');
|
||||
return withRelationships(Transformers.toServer(data), 'allocations', 'user', 'node', 'variables');
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,212 +0,0 @@
|
|||
/* eslint-disable camelcase */
|
||||
import { Allocation, Node } from '@/api/admin/node';
|
||||
import { Server, ServerVariable } from '@/api/admin/server';
|
||||
import { FractalResponseData, FractalResponseList } from '@/api/http';
|
||||
import { User, UserRole } from '@/api/admin/user';
|
||||
import { Location } from '@/api/admin/location';
|
||||
import { Egg, EggVariable } from '@/api/admin/egg';
|
||||
import { Nest } from '@/api/admin/nest';
|
||||
|
||||
const isList = (data: FractalResponseList | FractalResponseData): data is FractalResponseList => data.object === 'list';
|
||||
|
||||
function transform<T, M = undefined> (data: undefined, transformer: (callback: FractalResponseData) => T, missing?: M): undefined;
|
||||
function transform<T, M> (data: FractalResponseData | undefined, transformer: (callback: FractalResponseData) => T, missing?: M): T | M | undefined;
|
||||
function transform<T, M> (data: FractalResponseList | undefined, transformer: (callback: FractalResponseData) => T, missing?: M): T[] | undefined;
|
||||
function transform<T> (data: FractalResponseData | FractalResponseList | undefined, transformer: (callback: FractalResponseData) => T, missing = undefined) {
|
||||
if (data === undefined) return undefined;
|
||||
|
||||
if (isList(data)) {
|
||||
return data.data.map(transformer);
|
||||
}
|
||||
|
||||
return !data ? missing : transformer(data);
|
||||
}
|
||||
|
||||
export class AdminTransformers {
|
||||
static toServer = ({ attributes }: FractalResponseData): Server => {
|
||||
const { oom_disabled, ...limits } = attributes.limits;
|
||||
const { allocations, egg, nest, node, user, variables } = attributes.relationships || {};
|
||||
|
||||
return {
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
externalId: attributes.external_id,
|
||||
identifier: attributes.identifier,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
status: attributes.status,
|
||||
userId: attributes.owner_id,
|
||||
nodeId: attributes.node_id,
|
||||
allocationId: attributes.allocation_id,
|
||||
eggId: attributes.egg_id,
|
||||
nestId: attributes.nest_id,
|
||||
limits: { ...limits, oomDisabled: oom_disabled },
|
||||
featureLimits: attributes.feature_limits,
|
||||
container: attributes.container,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
allocations: transform(allocations as FractalResponseList | undefined, this.toAllocation),
|
||||
nest: transform(nest as FractalResponseData | undefined, this.toNest),
|
||||
egg: transform(egg as FractalResponseData | undefined, this.toEgg),
|
||||
node: transform(node as FractalResponseData | undefined, this.toNode),
|
||||
user: transform(user as FractalResponseData | undefined, this.toUser),
|
||||
variables: transform(variables as FractalResponseList | undefined, this.toServerEggVariable),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
static toNode = ({ attributes }: FractalResponseData): Node => {
|
||||
return {
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
isPublic: attributes.public,
|
||||
locationId: attributes.location_id,
|
||||
databaseHostId: attributes.database_host_id,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
fqdn: attributes.fqdn,
|
||||
ports: {
|
||||
http: {
|
||||
public: attributes.publicPortHttp,
|
||||
listen: attributes.listenPortHttp,
|
||||
},
|
||||
sftp: {
|
||||
public: attributes.publicPortSftp,
|
||||
listen: attributes.listenPortSftp,
|
||||
},
|
||||
},
|
||||
scheme: attributes.scheme,
|
||||
isBehindProxy: attributes.behindProxy,
|
||||
isMaintenanceMode: attributes.maintenance_mode,
|
||||
memory: attributes.memory,
|
||||
memoryOverallocate: attributes.memory_overallocate,
|
||||
disk: attributes.disk,
|
||||
diskOverallocate: attributes.disk_overallocate,
|
||||
uploadSize: attributes.upload_size,
|
||||
daemonBase: attributes.daemonBase,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
location: transform(attributes.relationships?.location as FractalResponseData, this.toLocation),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
static toUserRole = ({ attributes }: FractalResponseData): UserRole => ({
|
||||
id: attributes.id,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
relationships: {},
|
||||
});
|
||||
|
||||
static toUser = ({ attributes }: FractalResponseData): User => {
|
||||
return {
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
externalId: attributes.external_id,
|
||||
username: attributes.username,
|
||||
email: attributes.email,
|
||||
language: attributes.language,
|
||||
adminRoleId: attributes.adminRoleId || null,
|
||||
roleName: attributes.role_name,
|
||||
isRootAdmin: attributes.root_admin,
|
||||
isUsingTwoFactor: attributes['2fa'] || false,
|
||||
avatarUrl: attributes.avatar_url,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
role: transform(attributes.relationships?.role as FractalResponseData, this.toUserRole) || null,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
static toLocation = ({ attributes }: FractalResponseData): Location => ({
|
||||
id: attributes.id,
|
||||
short: attributes.short,
|
||||
long: attributes.long,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
nodes: transform(attributes.relationships?.node as FractalResponseList, this.toNode),
|
||||
},
|
||||
});
|
||||
|
||||
static toEgg = ({ attributes }: FractalResponseData): Egg => ({
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
nestId: attributes.nest_id,
|
||||
author: attributes.author,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
features: attributes.features,
|
||||
dockerImages: attributes.docker_images,
|
||||
configFiles: attributes.config?.files,
|
||||
configStartup: attributes.config?.startup,
|
||||
configStop: attributes.config?.stop,
|
||||
configFrom: attributes.config?.extends,
|
||||
startup: attributes.startup,
|
||||
copyScriptFrom: attributes.copy_script_from,
|
||||
scriptContainer: attributes.script?.container,
|
||||
scriptEntry: attributes.script?.entry,
|
||||
scriptIsPrivileged: attributes.script?.privileged,
|
||||
scriptInstall: attributes.script?.install,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
nest: transform(attributes.relationships?.nest as FractalResponseData, this.toNest),
|
||||
variables: transform(attributes.relationships?.variables as FractalResponseList, this.toEggVariable),
|
||||
},
|
||||
});
|
||||
|
||||
static toEggVariable = ({ attributes }: FractalResponseData): EggVariable => ({
|
||||
id: attributes.id,
|
||||
eggId: attributes.egg_id,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
environmentVariable: attributes.env_variable,
|
||||
defaultValue: attributes.default_value,
|
||||
isUserViewable: attributes.user_viewable,
|
||||
isUserEditable: attributes.user_editable,
|
||||
// isRequired: attributes.required,
|
||||
rules: attributes.rules,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {},
|
||||
});
|
||||
|
||||
static toServerEggVariable = (data: FractalResponseData): ServerVariable => ({
|
||||
...this.toEggVariable(data),
|
||||
serverValue: data.attributes.server_value,
|
||||
});
|
||||
|
||||
static toAllocation = ({ attributes }: FractalResponseData): Allocation => ({
|
||||
id: attributes.id,
|
||||
ip: attributes.ip,
|
||||
port: attributes.port,
|
||||
alias: attributes.alias || null,
|
||||
isAssigned: attributes.assigned,
|
||||
relationships: {
|
||||
node: transform(attributes.relationships?.node as FractalResponseData, this.toNode),
|
||||
server: transform(attributes.relationships?.server as FractalResponseData, this.toServer),
|
||||
},
|
||||
getDisplayText (): string {
|
||||
const raw = `${this.ip}:${this.port}`;
|
||||
|
||||
return !this.alias ? raw : `${this.alias} (${raw})`;
|
||||
},
|
||||
});
|
||||
|
||||
static toNest = ({ attributes }: FractalResponseData): Nest => ({
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
author: attributes.author,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
eggs: transform(attributes.relationships?.eggs as FractalResponseList, this.toEgg),
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,38 +1,11 @@
|
|||
import { Model, UUID } from '@/api/admin/index';
|
||||
import { Server } from '@/api/admin/server';
|
||||
import http, { QueryBuilderParams, withQueryBuilderParams } from '@/api/http';
|
||||
import { AdminTransformers } from '@/api/admin/transformers';
|
||||
|
||||
export interface User extends Model {
|
||||
id: number;
|
||||
uuid: UUID;
|
||||
externalId: string;
|
||||
username: string;
|
||||
email: string;
|
||||
language: string;
|
||||
adminRoleId: number | null;
|
||||
roleName: string;
|
||||
isRootAdmin: boolean;
|
||||
isUsingTwoFactor: boolean;
|
||||
avatarUrl: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
relationships: {
|
||||
role: UserRole | null;
|
||||
servers?: Server[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface UserRole extends Model {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
import Transformers from '@definitions/admin/transformers';
|
||||
import { User } from '@definitions/admin/models';
|
||||
|
||||
export const getUser = async (id: string | number): Promise<User> => {
|
||||
const { data } = await http.get(`/api/application/users/${id}`);
|
||||
|
||||
return AdminTransformers.toUser(data.data);
|
||||
return Transformers.toUser(data.data);
|
||||
};
|
||||
|
||||
export const searchUserAccounts = async (params: QueryBuilderParams<'username' | 'email'>): Promise<User[]> => {
|
||||
|
@ -40,5 +13,5 @@ export const searchUserAccounts = async (params: QueryBuilderParams<'username' |
|
|||
params: withQueryBuilderParams(params),
|
||||
});
|
||||
|
||||
return data.data.map(AdminTransformers.toUser);
|
||||
return data.data.map(Transformers.toUser);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import { Model as BaseModel, UUID } from '@/api/definitions';
|
||||
import { Server } from '@/api/admin/server';
|
||||
import { MarkRequired } from 'ts-essentials';
|
||||
|
||||
interface Model extends BaseModel {
|
||||
relationships: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a model to have optional relationships that are marked as being
|
||||
* present in a given pathway. This allows different API calls to specify the
|
||||
* "completeness" of a response object without having to make every API return
|
||||
* the same information, or every piece of logic do explicit null checking.
|
||||
*
|
||||
* Example:
|
||||
* >> const user: WithLoadedRelations<User, 'servers'> = {};
|
||||
* >> // "user.servers" is no longer potentially undefined.
|
||||
*/
|
||||
type WithLoadedRelations<M extends Model, R extends keyof M['relationships']> = M & {
|
||||
relationships: MarkRequired<M['relationships'], R>;
|
||||
};
|
||||
|
||||
interface User extends Model {
|
||||
id: number;
|
||||
uuid: UUID;
|
||||
externalId: string;
|
||||
username: string;
|
||||
email: string;
|
||||
language: string;
|
||||
adminRoleId: number | null;
|
||||
roleName: string;
|
||||
isRootAdmin: boolean;
|
||||
isUsingTwoFactor: boolean;
|
||||
avatarUrl: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
relationships: {
|
||||
role: UserRole | null;
|
||||
// TODO: just use an API call, this is probably a bad idea for performance.
|
||||
servers?: Server[];
|
||||
};
|
||||
}
|
||||
|
||||
interface UserRole extends Model {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
/* eslint-disable camelcase */
|
||||
import { Allocation, Node } from '@/api/admin/node';
|
||||
import { Server, ServerVariable } from '@/api/admin/server';
|
||||
import { FractalResponseData, FractalResponseList } from '@/api/http';
|
||||
import * as Models from '@definitions/admin/models';
|
||||
import { Location } from '@/api/admin/location';
|
||||
import { Egg, EggVariable } from '@/api/admin/egg';
|
||||
import { Nest } from '@/api/admin/nest';
|
||||
|
||||
const isList = (data: FractalResponseList | FractalResponseData): data is FractalResponseList => data.object === 'list';
|
||||
|
||||
function transform<T, M = undefined> (data: undefined, transformer: (callback: FractalResponseData) => T, missing?: M): undefined;
|
||||
function transform<T, M> (data: FractalResponseData | undefined, transformer: (callback: FractalResponseData) => T, missing?: M): T | M | undefined;
|
||||
function transform<T, M> (data: FractalResponseList | undefined, transformer: (callback: FractalResponseData) => T, missing?: M): T[] | undefined;
|
||||
function transform<T> (data: FractalResponseData | FractalResponseList | undefined, transformer: (callback: FractalResponseData) => T, missing = undefined) {
|
||||
if (data === undefined) return undefined;
|
||||
|
||||
if (isList(data)) {
|
||||
return data.data.map(transformer);
|
||||
}
|
||||
|
||||
return !data ? missing : transformer(data);
|
||||
}
|
||||
|
||||
export default class Transformers {
|
||||
static toServer = ({ attributes }: FractalResponseData): Server => {
|
||||
const { oom_disabled, ...limits } = attributes.limits;
|
||||
const { allocations, egg, nest, node, user, variables } = attributes.relationships || {};
|
||||
|
||||
return {
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
externalId: attributes.external_id,
|
||||
identifier: attributes.identifier,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
status: attributes.status,
|
||||
userId: attributes.owner_id,
|
||||
nodeId: attributes.node_id,
|
||||
allocationId: attributes.allocation_id,
|
||||
eggId: attributes.egg_id,
|
||||
nestId: attributes.nest_id,
|
||||
limits: { ...limits, oomDisabled: oom_disabled },
|
||||
featureLimits: attributes.feature_limits,
|
||||
container: attributes.container,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
allocations: transform(allocations as FractalResponseList | undefined, this.toAllocation),
|
||||
nest: transform(nest as FractalResponseData | undefined, this.toNest),
|
||||
egg: transform(egg as FractalResponseData | undefined, this.toEgg),
|
||||
node: transform(node as FractalResponseData | undefined, this.toNode),
|
||||
user: transform(user as FractalResponseData | undefined, this.toUser),
|
||||
variables: transform(variables as FractalResponseList | undefined, this.toServerEggVariable),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
static toNode = ({ attributes }: FractalResponseData): Node => {
|
||||
return {
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
isPublic: attributes.public,
|
||||
locationId: attributes.location_id,
|
||||
databaseHostId: attributes.database_host_id,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
fqdn: attributes.fqdn,
|
||||
ports: {
|
||||
http: {
|
||||
public: attributes.publicPortHttp,
|
||||
listen: attributes.listenPortHttp,
|
||||
},
|
||||
sftp: {
|
||||
public: attributes.publicPortSftp,
|
||||
listen: attributes.listenPortSftp,
|
||||
},
|
||||
},
|
||||
scheme: attributes.scheme,
|
||||
isBehindProxy: attributes.behindProxy,
|
||||
isMaintenanceMode: attributes.maintenance_mode,
|
||||
memory: attributes.memory,
|
||||
memoryOverallocate: attributes.memory_overallocate,
|
||||
disk: attributes.disk,
|
||||
diskOverallocate: attributes.disk_overallocate,
|
||||
uploadSize: attributes.upload_size,
|
||||
daemonBase: attributes.daemonBase,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
location: transform(attributes.relationships?.location as FractalResponseData, this.toLocation),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
static toUserRole = ({ attributes }: FractalResponseData): Models.UserRole => ({
|
||||
id: attributes.id,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
relationships: {},
|
||||
});
|
||||
|
||||
static toUser = ({ attributes }: FractalResponseData): Models.User => {
|
||||
return {
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
externalId: attributes.external_id,
|
||||
username: attributes.username,
|
||||
email: attributes.email,
|
||||
language: attributes.language,
|
||||
adminRoleId: attributes.adminRoleId || null,
|
||||
roleName: attributes.role_name,
|
||||
isRootAdmin: attributes.root_admin,
|
||||
isUsingTwoFactor: attributes['2fa'] || false,
|
||||
avatarUrl: attributes.avatar_url,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
role: transform(attributes.relationships?.role as FractalResponseData, this.toUserRole) || null,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
static toLocation = ({ attributes }: FractalResponseData): Location => ({
|
||||
id: attributes.id,
|
||||
short: attributes.short,
|
||||
long: attributes.long,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
nodes: transform(attributes.relationships?.node as FractalResponseList, this.toNode),
|
||||
},
|
||||
});
|
||||
|
||||
static toEgg = ({ attributes }: FractalResponseData): Egg => ({
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
nestId: attributes.nest_id,
|
||||
author: attributes.author,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
features: attributes.features,
|
||||
dockerImages: attributes.docker_images,
|
||||
configFiles: attributes.config?.files,
|
||||
configStartup: attributes.config?.startup,
|
||||
configStop: attributes.config?.stop,
|
||||
configFrom: attributes.config?.extends,
|
||||
startup: attributes.startup,
|
||||
copyScriptFrom: attributes.copy_script_from,
|
||||
scriptContainer: attributes.script?.container,
|
||||
scriptEntry: attributes.script?.entry,
|
||||
scriptIsPrivileged: attributes.script?.privileged,
|
||||
scriptInstall: attributes.script?.install,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
nest: transform(attributes.relationships?.nest as FractalResponseData, this.toNest),
|
||||
variables: transform(attributes.relationships?.variables as FractalResponseList, this.toEggVariable),
|
||||
},
|
||||
});
|
||||
|
||||
static toEggVariable = ({ attributes }: FractalResponseData): EggVariable => ({
|
||||
id: attributes.id,
|
||||
eggId: attributes.egg_id,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
environmentVariable: attributes.env_variable,
|
||||
defaultValue: attributes.default_value,
|
||||
isUserViewable: attributes.user_viewable,
|
||||
isUserEditable: attributes.user_editable,
|
||||
// isRequired: attributes.required,
|
||||
rules: attributes.rules,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {},
|
||||
});
|
||||
|
||||
static toServerEggVariable = (data: FractalResponseData): ServerVariable => ({
|
||||
...this.toEggVariable(data),
|
||||
serverValue: data.attributes.server_value,
|
||||
});
|
||||
|
||||
static toAllocation = ({ attributes }: FractalResponseData): Allocation => ({
|
||||
id: attributes.id,
|
||||
ip: attributes.ip,
|
||||
port: attributes.port,
|
||||
alias: attributes.alias || null,
|
||||
isAssigned: attributes.assigned,
|
||||
relationships: {
|
||||
node: transform(attributes.relationships?.node as FractalResponseData, this.toNode),
|
||||
server: transform(attributes.relationships?.server as FractalResponseData, this.toServer),
|
||||
},
|
||||
getDisplayText (): string {
|
||||
const raw = `${this.ip}:${this.port}`;
|
||||
|
||||
return !this.alias ? raw : `${this.alias} (${raw})`;
|
||||
},
|
||||
});
|
||||
|
||||
static toNest = ({ attributes }: FractalResponseData): Nest => ({
|
||||
id: attributes.id,
|
||||
uuid: attributes.uuid,
|
||||
author: attributes.author,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
createdAt: new Date(attributes.created_at),
|
||||
updatedAt: new Date(attributes.updated_at),
|
||||
relationships: {
|
||||
eggs: transform(attributes.relationships?.eggs as FractalResponseList, this.toEgg),
|
||||
},
|
||||
});
|
||||
}
|
4
resources/scripts/api/definitions/index.d.ts
vendored
Normal file
4
resources/scripts/api/definitions/index.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface Model {}
|
||||
|
||||
export type UUID = string;
|
|
@ -1,8 +1,7 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface Model {}
|
||||
import { Model, UUID } from '@/api/definitions';
|
||||
|
||||
interface SecurityKey extends Model {
|
||||
uuid: string;
|
||||
uuid: UUID;
|
||||
name: string;
|
||||
type: 'public-key';
|
||||
publicKeyId: string;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, { useState } from 'react';
|
||||
import { useFormikContext } from 'formik';
|
||||
import SearchableSelect, { Option } from '@/components/elements/SearchableSelect';
|
||||
import { User, searchUserAccounts } from '@/api/admin/user';
|
||||
import { User } from '@definitions/admin/models';
|
||||
import { searchUserAccounts } from '@/api/admin/user';
|
||||
|
||||
export default ({ selected }: { selected?: User }) => {
|
||||
const { setFieldValue } = useFormikContext();
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Checkbox } from '@/components/elements/inputs';
|
|||
import { Dropdown } from '@/components/elements/dropdown';
|
||||
import { BanIcon, DotsVerticalIcon, LockOpenIcon, PencilIcon, SupportIcon, TrashIcon } from '@heroicons/react/solid';
|
||||
import React, { useState } from 'react';
|
||||
import { User } from '@/api/admin/user';
|
||||
import { User } from '@definitions/admin/models';
|
||||
import { Dialog } from '@/components/elements/dialog';
|
||||
import { Button } from '@/components/elements/button/index';
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import http from '@/api/http';
|
||||
import { User } from '@/api/admin/user';
|
||||
import { AdminTransformers } from '@/api/admin/transformers';
|
||||
import { User } from '@definitions/admin/models';
|
||||
import Transformers from '@definitions/admin/transformers';
|
||||
import { LockOpenIcon, PlusIcon, SupportIcon, TrashIcon } from '@heroicons/react/solid';
|
||||
import { Button } from '@/components/elements/button/index';
|
||||
import { Checkbox, InputField } from '@/components/elements/inputs';
|
||||
|
@ -16,7 +16,7 @@ const UsersContainerV2 = () => {
|
|||
useEffect(() => {
|
||||
http.get('/api/application/users')
|
||||
.then(({ data }) => {
|
||||
setUsers(data.data.map(AdminTransformers.toUser));
|
||||
setUsers(data.data.map(Transformers.toUser));
|
||||
})
|
||||
.catch(console.error);
|
||||
}, []);
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -11036,6 +11036,7 @@ fsevents@^1.2.7:
|
|||
swr: ^1.0.1
|
||||
tailwindcss: ^3.0.23
|
||||
terser-webpack-plugin: ^4.2.3
|
||||
ts-essentials: ^9.1.2
|
||||
twin.macro: ^2.8.2
|
||||
typescript: ^4.4.4
|
||||
uuid: ^3.4.0
|
||||
|
@ -13389,6 +13390,15 @@ resolve@^2.0.0-next.3:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-essentials@npm:^9.1.2":
|
||||
version: 9.1.2
|
||||
resolution: "ts-essentials@npm:9.1.2"
|
||||
peerDependencies:
|
||||
typescript: ">=4.1.0"
|
||||
checksum: 3b14d8511557bd1bdec068505074ee41d3b1cdb052d3c66a5046f00b483bd4722d529b32a99cca424a9d7db9caff7ba108acbf344a5477a741e0616af5649b47
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-toolbelt@npm:^9.6.0":
|
||||
version: 9.6.0
|
||||
resolution: "ts-toolbelt@npm:9.6.0"
|
||||
|
|
Loading…
Reference in a new issue