feat(tech-tree): add tech-categories collection, permissions, and treePosition
Add the tech-categories collection that gives technologies a home off the
flat uncategorized pool, plus the schema support the admin editor needs.
- New `tech-categories` collection (unique name, timeline `position`,
optional hex `color`) with a `Technologies.category` FK (ON DELETE set
null) so deleting a category just unfiles its technologies.
- Add `Technologies.treePosition {x,y}` so the canvas can pin a node's
manual position; clearing it uses `{x:null,y:null}`.
- Register the two hand-written migrations (tech-categories + treePosition)
and regenerate payload-types, the drizzle schema, and the admin importMap.
- Register the `tech-categories:*` permission group and grant Intelligence
division members admin-panel access, mirroring technologies.
This commit is contained in:
parent
954e6e2c44
commit
15f2d0c573
12 changed files with 70877 additions and 3 deletions
|
|
@ -36,12 +36,14 @@ import { default as default_7fa52484aec46e988e9cfb5e86c0c759 } from '@/component
|
|||
import { SelectField as SelectField_4490b89d4413c1ffaecdacfe72efaf73 } from '@ai-stack/payloadcms/client'
|
||||
import { PromptEditorField as PromptEditorField_4490b89d4413c1ffaecdacfe72efaf73 } from '@ai-stack/payloadcms/client'
|
||||
import { default as default_b16af798585cda7cfed92f7b1dd0c707 } from '@/components/admin/shims/ShimContentField'
|
||||
import { default as default_a6bf792526e9f56202161f190c57e1c6 } from '@/components/admin/tech-tree/TechTreeNav'
|
||||
import { default as default_2f6c866ab4d4d51b3789f090b84b85c7 } from '@/components/static/VersionOverlay'
|
||||
import { default as default_508743824696caae2894ebf34c2e68bb } from '@/components/graphics/AppIcon'
|
||||
import { default as default_e752fee78378294ff03f91dba0a75a04 } from '@/components/graphics/AppLogo'
|
||||
import { default as default_05548cb43495e62d80b80ec4d9f0f7e9 } from '@/components/static/BeforeDashboardText'
|
||||
import { default as default_459d6b6f5ead73c736013da63a5ace3f } from '@/components/static/GoToFrontendLink'
|
||||
import { InstructionsProvider as InstructionsProvider_4490b89d4413c1ffaecdacfe72efaf73 } from '@ai-stack/payloadcms/client'
|
||||
import { default as default_2b34d0df0cf91f4442ca2cd62ae7cd94 } from '@/components/admin/tech-tree/TechTreeView'
|
||||
import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } from '@payloadcms/next/rsc'
|
||||
|
||||
/** @type import('payload').ImportMap */
|
||||
|
|
@ -84,11 +86,13 @@ export const importMap = {
|
|||
"@ai-stack/payloadcms/client#SelectField": SelectField_4490b89d4413c1ffaecdacfe72efaf73,
|
||||
"@ai-stack/payloadcms/client#PromptEditorField": PromptEditorField_4490b89d4413c1ffaecdacfe72efaf73,
|
||||
"@/components/admin/shims/ShimContentField#default": default_b16af798585cda7cfed92f7b1dd0c707,
|
||||
"@/components/admin/tech-tree/TechTreeNav#default": default_a6bf792526e9f56202161f190c57e1c6,
|
||||
"@/components/static/VersionOverlay#default": default_2f6c866ab4d4d51b3789f090b84b85c7,
|
||||
"@/components/graphics/AppIcon#default": default_508743824696caae2894ebf34c2e68bb,
|
||||
"@/components/graphics/AppLogo#default": default_e752fee78378294ff03f91dba0a75a04,
|
||||
"@/components/static/BeforeDashboardText#default": default_05548cb43495e62d80b80ec4d9f0f7e9,
|
||||
"@/components/static/GoToFrontendLink#default": default_459d6b6f5ead73c736013da63a5ace3f,
|
||||
"@ai-stack/payloadcms/client#InstructionsProvider": InstructionsProvider_4490b89d4413c1ffaecdacfe72efaf73,
|
||||
"@/components/admin/tech-tree/TechTreeView#default": default_2b34d0df0cf91f4442ca2cd62ae7cd94,
|
||||
"@payloadcms/next/rsc#CollectionCards": CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1
|
||||
}
|
||||
|
|
|
|||
58
src/collections/intelligence/TechCategories.ts
Normal file
58
src/collections/intelligence/TechCategories.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import { CollectionConfig } from "payload";
|
||||
|
||||
import { requireIntelligencePermission } from "@/utils/access-control/divisionAccess";
|
||||
|
||||
/** Validates an optional hex color like the map feature styling (`src/lib/map/style.ts`). */
|
||||
function validateHexColor(value: unknown): true | string {
|
||||
if (!value) return true;
|
||||
const str = String(value).trim();
|
||||
if (!str) return true;
|
||||
return /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(str)
|
||||
? true
|
||||
: "Enter a hex color like #22d3ee, or leave empty for the default.";
|
||||
}
|
||||
|
||||
export const TechCategories: CollectionConfig = {
|
||||
slug: "tech-categories",
|
||||
admin: {
|
||||
group: "Intelligence",
|
||||
useAsTitle: "name",
|
||||
},
|
||||
access: {
|
||||
create: requireIntelligencePermission("tech-categories:create"),
|
||||
update: requireIntelligencePermission("tech-categories:update"),
|
||||
delete: requireIntelligencePermission("tech-categories:delete"),
|
||||
read: requireIntelligencePermission("tech-categories:read"),
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "name",
|
||||
type: "text",
|
||||
required: true,
|
||||
unique: true,
|
||||
admin: {
|
||||
description:
|
||||
"Category label shown as a column band on the Tech Tree (e.g. Tier 1, Tier 2).",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "position",
|
||||
type: "number",
|
||||
required: true,
|
||||
min: 1,
|
||||
defaultValue: 1,
|
||||
admin: {
|
||||
description:
|
||||
"Timeline position: lower numbers sit further left on the Tech Tree. Categories with the same position are ordered alphabetically.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "color",
|
||||
type: "text",
|
||||
validate: validateHexColor,
|
||||
admin: {
|
||||
description: "Optional hex accent color for the band on the Tech Tree (e.g. #22d3ee).",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
@ -26,6 +26,34 @@ export const Technologies: CollectionConfig = {
|
|||
type: "text",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "category",
|
||||
type: "relationship",
|
||||
relationTo: "tech-categories",
|
||||
admin: {
|
||||
description:
|
||||
"Tech Tree column this technology belongs to. Uncategorized technologies are auto-placed on the Tech Tree by prerequisite depth.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "treePosition",
|
||||
type: "group",
|
||||
label: "Tech Tree Position",
|
||||
admin: {
|
||||
description:
|
||||
"Manual position on the Tech Tree canvas (set by dragging a node). Leave empty to use the automatic layout.",
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "x",
|
||||
type: "number",
|
||||
},
|
||||
{
|
||||
name: "y",
|
||||
type: "number",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "approvalStatus",
|
||||
type: "select",
|
||||
|
|
|
|||
35267
src/migrations/20260930_230747_add_tech_categories.json
Normal file
35267
src/migrations/20260930_230747_add_tech_categories.json
Normal file
File diff suppressed because it is too large
Load diff
54
src/migrations/20260930_230747_add_tech_categories.ts
Normal file
54
src/migrations/20260930_230747_add_tech_categories.ts
Normal file
File diff suppressed because one or more lines are too long
35279
src/migrations/20261001_000320_add_tech_tree_position.json
Normal file
35279
src/migrations/20261001_000320_add_tech_tree_position.json
Normal file
File diff suppressed because it is too large
Load diff
13
src/migrations/20261001_000320_add_tech_tree_position.ts
Normal file
13
src/migrations/20261001_000320_add_tech_tree_position.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||
|
||||
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
ALTER TABLE "technologies" ADD COLUMN "tree_position_x" numeric;
|
||||
ALTER TABLE "technologies" ADD COLUMN "tree_position_y" numeric;`)
|
||||
}
|
||||
|
||||
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
ALTER TABLE "technologies" DROP COLUMN "tree_position_x";
|
||||
ALTER TABLE "technologies" DROP COLUMN "tree_position_y";`)
|
||||
}
|
||||
|
|
@ -95,6 +95,8 @@ import * as migration_20260926_030859_add_mission_role_description from './20260
|
|||
import * as migration_20260926_044319_add_mission_role_description_richtext from './20260926_044319_add_mission_role_description_richtext';
|
||||
import * as migration_20260928_021138_change_ai_model from './20260928_021138_change_ai_model';
|
||||
import * as migration_20260930_162200_add_documentation_wiki_category from './20260930_162200_add_documentation_wiki_category';
|
||||
import * as migration_20260930_230747_add_tech_categories from './20260930_230747_add_tech_categories';
|
||||
import * as migration_20261001_000320_add_tech_tree_position from './20261001_000320_add_tech_tree_position';
|
||||
|
||||
export const migrations = [
|
||||
{
|
||||
|
|
@ -575,11 +577,21 @@ export const migrations = [
|
|||
{
|
||||
up: migration_20260928_021138_change_ai_model.up,
|
||||
down: migration_20260928_021138_change_ai_model.down,
|
||||
name: '20260928_021138_change_ai_model'
|
||||
name: '20260928_021138_change_ai_model',
|
||||
},
|
||||
{
|
||||
up: migration_20260930_162200_add_documentation_wiki_category.up,
|
||||
down: migration_20260930_162200_add_documentation_wiki_category.down,
|
||||
name: '20260930_162200_add_documentation_wiki_category'
|
||||
name: '20260930_162200_add_documentation_wiki_category',
|
||||
},
|
||||
{
|
||||
up: migration_20260930_230747_add_tech_categories.up,
|
||||
down: migration_20260930_230747_add_tech_categories.down,
|
||||
name: '20260930_230747_add_tech_categories',
|
||||
},
|
||||
{
|
||||
up: migration_20261001_000320_add_tech_tree_position.up,
|
||||
down: migration_20261001_000320_add_tech_tree_position.down,
|
||||
name: '20261001_000320_add_tech_tree_position'
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -283,6 +283,11 @@ export const enum_roles_permissions = pgEnum("enum_roles_permissions", [
|
|||
"technologies:update",
|
||||
"technologies:delete",
|
||||
"admin:technologies:manage",
|
||||
"tech-categories:create",
|
||||
"tech-categories:read",
|
||||
"tech-categories:update",
|
||||
"tech-categories:delete",
|
||||
"admin:tech-categories:manage",
|
||||
"assets:create",
|
||||
"assets:read",
|
||||
"assets:update",
|
||||
|
|
@ -3317,6 +3322,11 @@ export const technologies = pgTable(
|
|||
{
|
||||
id: serial("id").primaryKey(),
|
||||
name: varchar("name").notNull(),
|
||||
category: integer("category_id").references(() => tech_categories.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
treePosition_x: numeric("tree_position_x", { mode: "number" }),
|
||||
treePosition_y: numeric("tree_position_y", { mode: "number" }),
|
||||
approvalStatus: enum_technologies_approval_status("approval_status")
|
||||
.notNull()
|
||||
.default("in_progress"),
|
||||
|
|
@ -3339,6 +3349,7 @@ export const technologies = pgTable(
|
|||
.notNull(),
|
||||
},
|
||||
(columns) => [
|
||||
index("technologies_category_idx").on(columns.category),
|
||||
index("technologies_updated_at_idx").on(columns.updatedAt),
|
||||
index("technologies_created_at_idx").on(columns.createdAt),
|
||||
],
|
||||
|
|
@ -3371,6 +3382,27 @@ export const technologies_rels = pgTable(
|
|||
],
|
||||
);
|
||||
|
||||
export const tech_categories = pgTable(
|
||||
"tech_categories",
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
name: varchar("name").notNull(),
|
||||
position: numeric("position", { mode: "number" }).notNull().default(1),
|
||||
color: varchar("color"),
|
||||
updatedAt: timestamp("updated_at", { mode: "string", withTimezone: true, precision: 3 })
|
||||
.defaultNow()
|
||||
.notNull(),
|
||||
createdAt: timestamp("created_at", { mode: "string", withTimezone: true, precision: 3 })
|
||||
.defaultNow()
|
||||
.notNull(),
|
||||
},
|
||||
(columns) => [
|
||||
uniqueIndex("tech_categories_name_idx").on(columns.name),
|
||||
index("tech_categories_updated_at_idx").on(columns.updatedAt),
|
||||
index("tech_categories_created_at_idx").on(columns.createdAt),
|
||||
],
|
||||
);
|
||||
|
||||
export const assets_skin_configuration_applies_to_asset_types = pgTable(
|
||||
"assets_skin_configuration_applies_to_asset_types",
|
||||
{
|
||||
|
|
@ -6856,6 +6888,10 @@ export const payload_mcp_api_keys = pgTable(
|
|||
technologies_create: boolean("technologies_create").default(false),
|
||||
technologies_update: boolean("technologies_update").default(false),
|
||||
technologies_delete: boolean("technologies_delete").default(false),
|
||||
techCategories_find: boolean("tech_categories_find").default(false),
|
||||
techCategories_create: boolean("tech_categories_create").default(false),
|
||||
techCategories_update: boolean("tech_categories_update").default(false),
|
||||
techCategories_delete: boolean("tech_categories_delete").default(false),
|
||||
assets_find: boolean("assets_find").default(false),
|
||||
assets_create: boolean("assets_create").default(false),
|
||||
assets_update: boolean("assets_update").default(false),
|
||||
|
|
@ -7128,6 +7164,7 @@ export const payload_locked_documents_rels = pgTable(
|
|||
campaignsID: integer("campaigns_id"),
|
||||
factionsID: integer("factions_id"),
|
||||
technologiesID: integer("technologies_id"),
|
||||
"tech-categoriesID": integer("tech_categories_id"),
|
||||
assetsID: integer("assets_id"),
|
||||
resourcesID: integer("resources_id"),
|
||||
vehiclesID: integer("vehicles_id"),
|
||||
|
|
@ -7226,6 +7263,7 @@ export const payload_locked_documents_rels = pgTable(
|
|||
index("payload_locked_documents_rels_campaigns_id_idx").on(columns.campaignsID),
|
||||
index("payload_locked_documents_rels_factions_id_idx").on(columns.factionsID),
|
||||
index("payload_locked_documents_rels_technologies_id_idx").on(columns.technologiesID),
|
||||
index("payload_locked_documents_rels_tech_categories_id_idx").on(columns["tech-categoriesID"]),
|
||||
index("payload_locked_documents_rels_assets_id_idx").on(columns.assetsID),
|
||||
index("payload_locked_documents_rels_resources_id_idx").on(columns.resourcesID),
|
||||
index("payload_locked_documents_rels_vehicles_id_idx").on(columns.vehiclesID),
|
||||
|
|
@ -7454,6 +7492,11 @@ export const payload_locked_documents_rels = pgTable(
|
|||
foreignColumns: [technologies.id],
|
||||
name: "payload_locked_documents_rels_technologies_fk",
|
||||
}).onDelete("cascade"),
|
||||
foreignKey({
|
||||
columns: [columns["tech-categoriesID"]],
|
||||
foreignColumns: [tech_categories.id],
|
||||
name: "payload_locked_documents_rels_tech_categories_fk",
|
||||
}).onDelete("cascade"),
|
||||
foreignKey({
|
||||
columns: [columns["assetsID"]],
|
||||
foreignColumns: [assets.id],
|
||||
|
|
@ -8870,7 +8913,12 @@ export const relations_technologies_rels = relations(technologies_rels, ({ one }
|
|||
relationName: "technologies",
|
||||
}),
|
||||
}));
|
||||
export const relations_technologies = relations(technologies, ({ many }) => ({
|
||||
export const relations_technologies = relations(technologies, ({ one, many }) => ({
|
||||
category: one(tech_categories, {
|
||||
fields: [technologies.category],
|
||||
references: [tech_categories.id],
|
||||
relationName: "category",
|
||||
}),
|
||||
requirements_prerequisiteTechnologies: many(technologies_requirements_prerequisite_technologies, {
|
||||
relationName: "requirements_prerequisiteTechnologies",
|
||||
}),
|
||||
|
|
@ -8881,6 +8929,7 @@ export const relations_technologies = relations(technologies, ({ many }) => ({
|
|||
relationName: "_rels",
|
||||
}),
|
||||
}));
|
||||
export const relations_tech_categories = relations(tech_categories, () => ({}));
|
||||
export const relations_assets_skin_configuration_applies_to_asset_types = relations(
|
||||
assets_skin_configuration_applies_to_asset_types,
|
||||
({ one }) => ({
|
||||
|
|
@ -10516,6 +10565,11 @@ export const relations_payload_locked_documents_rels = relations(
|
|||
references: [technologies.id],
|
||||
relationName: "technologies",
|
||||
}),
|
||||
"tech-categoriesID": one(tech_categories, {
|
||||
fields: [payload_locked_documents_rels["tech-categoriesID"]],
|
||||
references: [tech_categories.id],
|
||||
relationName: "tech-categories",
|
||||
}),
|
||||
assetsID: one(assets, {
|
||||
fields: [payload_locked_documents_rels.assetsID],
|
||||
references: [assets.id],
|
||||
|
|
@ -11075,6 +11129,7 @@ type DatabaseSchema = {
|
|||
technologies_research_costs_resources: typeof technologies_research_costs_resources;
|
||||
technologies: typeof technologies;
|
||||
technologies_rels: typeof technologies_rels;
|
||||
tech_categories: typeof tech_categories;
|
||||
assets_skin_configuration_applies_to_asset_types: typeof assets_skin_configuration_applies_to_asset_types;
|
||||
assets_crafting_crafting_data_inputs: typeof assets_crafting_crafting_data_inputs;
|
||||
assets_crafting_crafting_data_byproducts: typeof assets_crafting_crafting_data_byproducts;
|
||||
|
|
@ -11264,6 +11319,7 @@ type DatabaseSchema = {
|
|||
relations_technologies_research_costs_resources: typeof relations_technologies_research_costs_resources;
|
||||
relations_technologies_rels: typeof relations_technologies_rels;
|
||||
relations_technologies: typeof relations_technologies;
|
||||
relations_tech_categories: typeof relations_tech_categories;
|
||||
relations_assets_skin_configuration_applies_to_asset_types: typeof relations_assets_skin_configuration_applies_to_asset_types;
|
||||
relations_assets_crafting_crafting_data_inputs: typeof relations_assets_crafting_crafting_data_inputs;
|
||||
relations_assets_crafting_crafting_data_byproducts: typeof relations_assets_crafting_crafting_data_byproducts;
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ export interface Config {
|
|||
campaigns: Campaign;
|
||||
factions: Faction;
|
||||
technologies: Technology;
|
||||
'tech-categories': TechCategory;
|
||||
assets: Asset;
|
||||
resources: Resource;
|
||||
vehicles: Vehicle;
|
||||
|
|
@ -188,6 +189,7 @@ export interface Config {
|
|||
campaigns: CampaignsSelect<false> | CampaignsSelect<true>;
|
||||
factions: FactionsSelect<false> | FactionsSelect<true>;
|
||||
technologies: TechnologiesSelect<false> | TechnologiesSelect<true>;
|
||||
'tech-categories': TechCategoriesSelect<false> | TechCategoriesSelect<true>;
|
||||
assets: AssetsSelect<false> | AssetsSelect<true>;
|
||||
resources: ResourcesSelect<false> | ResourcesSelect<true>;
|
||||
vehicles: VehiclesSelect<false> | VehiclesSelect<true>;
|
||||
|
|
@ -656,6 +658,11 @@ export interface Role {
|
|||
| 'technologies:update'
|
||||
| 'technologies:delete'
|
||||
| 'admin:technologies:manage'
|
||||
| 'tech-categories:create'
|
||||
| 'tech-categories:read'
|
||||
| 'tech-categories:update'
|
||||
| 'tech-categories:delete'
|
||||
| 'admin:tech-categories:manage'
|
||||
| 'assets:create'
|
||||
| 'assets:read'
|
||||
| 'assets:update'
|
||||
|
|
@ -1538,6 +1545,17 @@ export interface Resource {
|
|||
export interface Technology {
|
||||
id: number;
|
||||
name: string;
|
||||
/**
|
||||
* Tech Tree column this technology belongs to. Uncategorized technologies are auto-placed on the Tech Tree by prerequisite depth.
|
||||
*/
|
||||
category?: (number | null) | TechCategory;
|
||||
/**
|
||||
* Manual position on the Tech Tree canvas (set by dragging a node). Leave empty to use the automatic layout.
|
||||
*/
|
||||
treePosition?: {
|
||||
x?: number | null;
|
||||
y?: number | null;
|
||||
};
|
||||
/**
|
||||
* Mark whether this technology is ready for developer approval and implementation into the live environment.
|
||||
*/
|
||||
|
|
@ -1598,6 +1616,27 @@ export interface Technology {
|
|||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "tech-categories".
|
||||
*/
|
||||
export interface TechCategory {
|
||||
id: number;
|
||||
/**
|
||||
* Category label shown as a column band on the Tech Tree (e.g. Tier 1, Tier 2).
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Timeline position: lower numbers sit further left on the Tech Tree. Categories with the same position are ordered alphabetically.
|
||||
*/
|
||||
position: number;
|
||||
/**
|
||||
* Optional hex accent color for the band on the Tech Tree (e.g. #22d3ee).
|
||||
*/
|
||||
color?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "labor-classifications".
|
||||
|
|
@ -5732,6 +5771,24 @@ export interface PayloadMcpApiKey {
|
|||
*/
|
||||
delete?: boolean | null;
|
||||
};
|
||||
techCategories?: {
|
||||
/**
|
||||
* Allow clients to find tech-categories.
|
||||
*/
|
||||
find?: boolean | null;
|
||||
/**
|
||||
* Allow clients to create tech-categories.
|
||||
*/
|
||||
create?: boolean | null;
|
||||
/**
|
||||
* Allow clients to update tech-categories.
|
||||
*/
|
||||
update?: boolean | null;
|
||||
/**
|
||||
* Allow clients to delete tech-categories.
|
||||
*/
|
||||
delete?: boolean | null;
|
||||
};
|
||||
assets?: {
|
||||
/**
|
||||
* Allow clients to find assets.
|
||||
|
|
@ -6735,6 +6792,10 @@ export interface PayloadLockedDocument {
|
|||
relationTo: 'technologies';
|
||||
value: number | Technology;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'tech-categories';
|
||||
value: number | TechCategory;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'assets';
|
||||
value: number | Asset;
|
||||
|
|
@ -7836,6 +7897,13 @@ export interface FactionsSelect<T extends boolean = true> {
|
|||
*/
|
||||
export interface TechnologiesSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
category?: T;
|
||||
treePosition?:
|
||||
| T
|
||||
| {
|
||||
x?: T;
|
||||
y?: T;
|
||||
};
|
||||
approvalStatus?: T;
|
||||
type?: T;
|
||||
summary?: T;
|
||||
|
|
@ -7875,6 +7943,17 @@ export interface TechnologiesSelect<T extends boolean = true> {
|
|||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "tech-categories_select".
|
||||
*/
|
||||
export interface TechCategoriesSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
position?: T;
|
||||
color?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "assets_select".
|
||||
|
|
@ -9513,6 +9592,14 @@ export interface PayloadMcpApiKeysSelect<T extends boolean = true> {
|
|||
update?: T;
|
||||
delete?: T;
|
||||
};
|
||||
techCategories?:
|
||||
| T
|
||||
| {
|
||||
find?: T;
|
||||
create?: T;
|
||||
update?: T;
|
||||
delete?: T;
|
||||
};
|
||||
assets?:
|
||||
| T
|
||||
| {
|
||||
|
|
|
|||
|
|
@ -229,6 +229,16 @@ export const PERMISSION_GROUPS: PermissionGroup[] = [
|
|||
{ value: "admin:technologies:manage", label: "Manage Admin Page" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "Tech Categories",
|
||||
permissions: [
|
||||
{ value: "tech-categories:create", label: "Create" },
|
||||
{ value: "tech-categories:read", label: "Read" },
|
||||
{ value: "tech-categories:update", label: "Update" },
|
||||
{ value: "tech-categories:delete", label: "Delete" },
|
||||
{ value: "admin:tech-categories:manage", label: "Manage Admin Page" },
|
||||
],
|
||||
},
|
||||
|
||||
// ---- Logistics -----------------------------------------------------------
|
||||
{
|
||||
|
|
@ -814,6 +824,11 @@ export const ALL_PERMISSION_VALUES = PERMISSION_GROUPS.flatMap((g) =>
|
|||
"technologies:update",
|
||||
"technologies:delete",
|
||||
"admin:technologies:manage",
|
||||
"tech-categories:create",
|
||||
"tech-categories:read",
|
||||
"tech-categories:update",
|
||||
"tech-categories:delete",
|
||||
"admin:tech-categories:manage",
|
||||
"assets:create",
|
||||
"assets:read",
|
||||
"assets:update",
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ const DIVISION_ADMIN_QUALIFICATIONS: Record<
|
|||
(payload: Payload, user: { id: number | string }) => Promise<boolean>
|
||||
> = {
|
||||
technologies: hasIntelligenceQualification,
|
||||
"tech-categories": hasIntelligenceQualification,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue