feat(awards): add grantConfig permissions to Awards collection with migration
This commit is contained in:
parent
24c5259056
commit
7f19b35b40
5 changed files with 19770 additions and 25 deletions
|
|
@ -84,5 +84,64 @@ export const Awards: CollectionConfig = {
|
||||||
condition: (data) => data?.type === "medal",
|
condition: (data) => data?.type === "medal",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "grantConfig",
|
||||||
|
type: "group",
|
||||||
|
label: "Grant Permissions",
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"Configure who can grant this award and to whom. Only applies to ribbons and commendations.",
|
||||||
|
condition: (data) => data?.type !== "medal",
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "allowedGrantorAssignmentTypes",
|
||||||
|
type: "select",
|
||||||
|
hasMany: true,
|
||||||
|
label: "Eligible Grantor Assignments",
|
||||||
|
options: [
|
||||||
|
{ label: "Division Leader", value: "division" },
|
||||||
|
{ label: "Squad Leader", value: "squad" },
|
||||||
|
{ label: "Team Leader", value: "team" },
|
||||||
|
{ label: "Special Assignment Leader", value: "special" },
|
||||||
|
],
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"Leaders of these assignment types can grant this award. Leave empty for admin/developer only.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "maxGrantsPerGrantor",
|
||||||
|
type: "number",
|
||||||
|
label: "Max Grants Per Leader",
|
||||||
|
min: 1,
|
||||||
|
admin: {
|
||||||
|
description: "Maximum times each grantor can issue this award. Empty = unlimited.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "recipientScope",
|
||||||
|
type: "select",
|
||||||
|
label: "Recipient Eligibility",
|
||||||
|
defaultValue: "same_command",
|
||||||
|
options: [
|
||||||
|
{ label: "Own Command (grantor's assignment tree)", value: "same_command" },
|
||||||
|
{ label: "Whitelist (specific assignments)", value: "whitelist" },
|
||||||
|
{ label: "Anyone (unit-wide)", value: "anyone" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "eligibleRecipientAssignments",
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: "assignments",
|
||||||
|
hasMany: true,
|
||||||
|
label: "Eligible Recipient Assignments",
|
||||||
|
admin: {
|
||||||
|
condition: (data) => data?.grantConfig?.recipientScope === "whitelist",
|
||||||
|
description: "Only members of these assignments can receive this award.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
19611
src/migrations/20260831_142503.json
Normal file
19611
src/migrations/20260831_142503.json
Normal file
File diff suppressed because it is too large
Load diff
43
src/migrations/20260831_142503.ts
Normal file
43
src/migrations/20260831_142503.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||||
|
|
||||||
|
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
CREATE TYPE "public"."enum_awards_grant_config_allowed_grantor_assignment_types" AS ENUM('division', 'squad', 'team', 'special');
|
||||||
|
CREATE TYPE "public"."enum_awards_grant_config_recipient_scope" AS ENUM('same_command', 'whitelist', 'anyone');
|
||||||
|
CREATE TABLE "awards_grant_config_allowed_grantor_assignment_types" (
|
||||||
|
"order" integer NOT NULL,
|
||||||
|
"parent_id" integer NOT NULL,
|
||||||
|
"value" "enum_awards_grant_config_allowed_grantor_assignment_types",
|
||||||
|
"id" serial PRIMARY KEY NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "awards_rels" (
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"order" integer,
|
||||||
|
"parent_id" integer NOT NULL,
|
||||||
|
"path" varchar NOT NULL,
|
||||||
|
"assignments_id" integer
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE "awards" ADD COLUMN "grant_config_max_grants_per_grantor" numeric;
|
||||||
|
ALTER TABLE "awards" ADD COLUMN "grant_config_recipient_scope" "enum_awards_grant_config_recipient_scope" DEFAULT 'same_command';
|
||||||
|
ALTER TABLE "awards_grant_config_allowed_grantor_assignment_types" ADD CONSTRAINT "awards_grant_config_allowed_grantor_assignment_types_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."awards"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "awards_rels" ADD CONSTRAINT "awards_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."awards"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "awards_rels" ADD CONSTRAINT "awards_rels_assignments_fk" FOREIGN KEY ("assignments_id") REFERENCES "public"."assignments"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
CREATE INDEX "awards_grant_config_allowed_grantor_assignment_types_order_idx" ON "awards_grant_config_allowed_grantor_assignment_types" USING btree ("order");
|
||||||
|
CREATE INDEX "awards_grant_config_allowed_grantor_assignment_types_parent_idx" ON "awards_grant_config_allowed_grantor_assignment_types" USING btree ("parent_id");
|
||||||
|
CREATE INDEX "awards_rels_order_idx" ON "awards_rels" USING btree ("order");
|
||||||
|
CREATE INDEX "awards_rels_parent_idx" ON "awards_rels" USING btree ("parent_id");
|
||||||
|
CREATE INDEX "awards_rels_path_idx" ON "awards_rels" USING btree ("path");
|
||||||
|
CREATE INDEX "awards_rels_assignments_id_idx" ON "awards_rels" USING btree ("assignments_id");`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
DROP TABLE "awards_grant_config_allowed_grantor_assignment_types" CASCADE;
|
||||||
|
DROP TABLE "awards_rels" CASCADE;
|
||||||
|
ALTER TABLE "awards" DROP COLUMN "grant_config_max_grants_per_grantor";
|
||||||
|
ALTER TABLE "awards" DROP COLUMN "grant_config_recipient_scope";
|
||||||
|
DROP TYPE "public"."enum_awards_grant_config_allowed_grantor_assignment_types";
|
||||||
|
DROP TYPE "public"."enum_awards_grant_config_recipient_scope";`)
|
||||||
|
}
|
||||||
|
|
@ -1,45 +1,46 @@
|
||||||
import * as migration_20260820_004157 from "./20260820_004157";
|
import * as migration_20260820_004157 from './20260820_004157';
|
||||||
import * as migration_20260825_220000 from "./20260825_220000";
|
import * as migration_20260825_220000 from './20260825_220000';
|
||||||
import * as migration_20260826_050000_repair_shims_auxiliary_tables from "./20260826_050000_repair_shims_auxiliary_tables";
|
import * as migration_20260826_050000_repair_shims_auxiliary_tables from './20260826_050000_repair_shims_auxiliary_tables';
|
||||||
import * as migration_20260826_060000_add_game_servers_event_target from "./20260826_060000_add_game_servers_event_target";
|
import * as migration_20260826_060000_add_game_servers_event_target from './20260826_060000_add_game_servers_event_target';
|
||||||
import * as migration_20260827_005757 from "./20260827_005757";
|
import * as migration_20260827_005757 from './20260827_005757';
|
||||||
import * as migration_20260827_022334_add_eod_minesweeper_best_flags from "./20260827_022334_add_eod_minesweeper_best_flags";
|
import * as migration_20260827_022334_add_eod_minesweeper_best_flags from './20260827_022334_add_eod_minesweeper_best_flags';
|
||||||
import * as migration_20260828_011500_add_background_texture_preference from "./20260828_011500_add_background_texture_preference";
|
|
||||||
import * as migration_20260827_213857_add_evaluations_collection from './20260827_213857_add_evaluations_collection';
|
import * as migration_20260827_213857_add_evaluations_collection from './20260827_213857_add_evaluations_collection';
|
||||||
import * as migration_20260827_233224_add_mission_completed_at from './20260827_233224_add_mission_completed_at';
|
import * as migration_20260827_233224_add_mission_completed_at from './20260827_233224_add_mission_completed_at';
|
||||||
|
import * as migration_20260828_011500_add_background_texture_preference from './20260828_011500_add_background_texture_preference';
|
||||||
import * as migration_20260828_041615_add_campaign_mode from './20260828_041615_add_campaign_mode';
|
import * as migration_20260828_041615_add_campaign_mode from './20260828_041615_add_campaign_mode';
|
||||||
import * as migration_20260828_044506 from './20260828_044506';
|
import * as migration_20260828_044506 from './20260828_044506';
|
||||||
|
import * as migration_20260831_142503 from './20260831_142503';
|
||||||
|
|
||||||
export const migrations = [
|
export const migrations = [
|
||||||
{
|
{
|
||||||
up: migration_20260820_004157.up,
|
up: migration_20260820_004157.up,
|
||||||
down: migration_20260820_004157.down,
|
down: migration_20260820_004157.down,
|
||||||
name: "20260820_004157",
|
name: '20260820_004157',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
up: migration_20260825_220000.up,
|
up: migration_20260825_220000.up,
|
||||||
down: migration_20260825_220000.down,
|
down: migration_20260825_220000.down,
|
||||||
name: "20260825_220000",
|
name: '20260825_220000',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
up: migration_20260826_050000_repair_shims_auxiliary_tables.up,
|
up: migration_20260826_050000_repair_shims_auxiliary_tables.up,
|
||||||
down: migration_20260826_050000_repair_shims_auxiliary_tables.down,
|
down: migration_20260826_050000_repair_shims_auxiliary_tables.down,
|
||||||
name: "20260826_050000_repair_shims_auxiliary_tables",
|
name: '20260826_050000_repair_shims_auxiliary_tables',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
up: migration_20260826_060000_add_game_servers_event_target.up,
|
up: migration_20260826_060000_add_game_servers_event_target.up,
|
||||||
down: migration_20260826_060000_add_game_servers_event_target.down,
|
down: migration_20260826_060000_add_game_servers_event_target.down,
|
||||||
name: "20260826_060000_add_game_servers_event_target",
|
name: '20260826_060000_add_game_servers_event_target',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
up: migration_20260827_005757.up,
|
up: migration_20260827_005757.up,
|
||||||
down: migration_20260827_005757.down,
|
down: migration_20260827_005757.down,
|
||||||
name: "20260827_005757",
|
name: '20260827_005757',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
up: migration_20260827_022334_add_eod_minesweeper_best_flags.up,
|
up: migration_20260827_022334_add_eod_minesweeper_best_flags.up,
|
||||||
down: migration_20260827_022334_add_eod_minesweeper_best_flags.down,
|
down: migration_20260827_022334_add_eod_minesweeper_best_flags.down,
|
||||||
name: "20260827_022334_add_eod_minesweeper_best_flags",
|
name: '20260827_022334_add_eod_minesweeper_best_flags',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
up: migration_20260827_213857_add_evaluations_collection.up,
|
up: migration_20260827_213857_add_evaluations_collection.up,
|
||||||
|
|
@ -54,7 +55,7 @@ export const migrations = [
|
||||||
{
|
{
|
||||||
up: migration_20260828_011500_add_background_texture_preference.up,
|
up: migration_20260828_011500_add_background_texture_preference.up,
|
||||||
down: migration_20260828_011500_add_background_texture_preference.down,
|
down: migration_20260828_011500_add_background_texture_preference.down,
|
||||||
name: "20260828_011500_add_background_texture_preference",
|
name: '20260828_011500_add_background_texture_preference',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
up: migration_20260828_041615_add_campaign_mode.up,
|
up: migration_20260828_041615_add_campaign_mode.up,
|
||||||
|
|
@ -64,6 +65,11 @@ export const migrations = [
|
||||||
{
|
{
|
||||||
up: migration_20260828_044506.up,
|
up: migration_20260828_044506.up,
|
||||||
down: migration_20260828_044506.down,
|
down: migration_20260828_044506.down,
|
||||||
name: '20260828_044506'
|
name: '20260828_044506',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
up: migration_20260831_142503.up,
|
||||||
|
down: migration_20260831_142503.down,
|
||||||
|
name: '20260831_142503'
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1753,16 +1753,24 @@ export interface Award {
|
||||||
| number
|
| number
|
||||||
| boolean
|
| boolean
|
||||||
| null;
|
| null;
|
||||||
updatedAt: string;
|
/**
|
||||||
createdAt: string;
|
* Configure who can grant this award and to whom. Only applies to ribbons and commendations.
|
||||||
}
|
*/
|
||||||
/**
|
grantConfig?: {
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
/**
|
||||||
* via the `definition` "qualifications".
|
* Leaders of these assignment types can grant this award. Leave empty for admin/developer only.
|
||||||
*/
|
*/
|
||||||
export interface Qualification {
|
allowedGrantorAssignmentTypes?: ('division' | 'squad' | 'team' | 'special')[] | null;
|
||||||
id: number;
|
/**
|
||||||
name: string;
|
* Maximum times each grantor can issue this award. Empty = unlimited.
|
||||||
|
*/
|
||||||
|
maxGrantsPerGrantor?: number | null;
|
||||||
|
recipientScope?: ('same_command' | 'whitelist' | 'anyone') | null;
|
||||||
|
/**
|
||||||
|
* Only members of these assignments can receive this award.
|
||||||
|
*/
|
||||||
|
eligibleRecipientAssignments?: (number | Assignment)[] | null;
|
||||||
|
};
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
|
@ -1810,6 +1818,16 @@ export interface Assignment {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "qualifications".
|
||||||
|
*/
|
||||||
|
export interface Qualification {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "experience".
|
* via the `definition` "experience".
|
||||||
|
|
@ -3547,6 +3565,14 @@ export interface AwardsSelect<T extends boolean = true> {
|
||||||
experiencePoints?: T;
|
experiencePoints?: T;
|
||||||
ribbonDesign?: T;
|
ribbonDesign?: T;
|
||||||
medalDesign?: T;
|
medalDesign?: T;
|
||||||
|
grantConfig?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
allowedGrantorAssignmentTypes?: T;
|
||||||
|
maxGrantsPerGrantor?: T;
|
||||||
|
recipientScope?: T;
|
||||||
|
eligibleRecipientAssignments?: T;
|
||||||
|
};
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue