added project scope opacity defaults configuration

This commit is contained in:
Dmitri 2026-07-02 08:15:19 +02:00
parent ed328ee06c
commit 10bb6da35f
6 changed files with 65 additions and 11 deletions

View File

@ -9,6 +9,12 @@ import type {
DbRelationFilterConfig, DbRelationFilterConfig,
} from '../../types/index.ts'; } from '../../types/index.ts';
function mapProjectId(data: AssetData): string | null | undefined {
if (data.projectId !== undefined) return data.projectId;
if (data.project !== undefined) return data.project;
return undefined;
}
class AssetsDBApi extends GenericDBApi { class AssetsDBApi extends GenericDBApi {
declare static findBy: AssetsDbApi['findBy']; declare static findBy: AssetsDbApi['findBy'];
@ -105,7 +111,7 @@ class AssetsDBApi extends GenericDBApi {
embed_provider: data.embed_provider || null, embed_provider: data.embed_provider || null,
checksum: data.checksum || null, checksum: data.checksum || null,
is_public: data.is_public || false, is_public: data.is_public || false,
projectId: data.projectId || data.project || null, projectId: mapProjectId(data),
}; };
} }
} }

View File

@ -46,6 +46,14 @@ function isElementSettingsJson(value: unknown): value is ElementSettingsJson {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value); return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
} }
function mapProjectId(
data: ProjectElementDefaultsData,
): string | null | undefined {
if (data.projectId !== undefined) return data.projectId;
if (data.project !== undefined) return data.project;
return undefined;
}
function isGlobalElementDefaultRecord( function isGlobalElementDefaultRecord(
value: EntityRecord, value: EntityRecord,
): value is GlobalElementDefaultRecord { ): value is GlobalElementDefaultRecord {
@ -206,7 +214,7 @@ class Project_element_defaultsDBApi extends GenericDBApi {
settings_json: stringifySettings(data.settings_json), settings_json: stringifySettings(data.settings_json),
source_element_id: data.source_element_id ?? null, source_element_id: data.source_element_id ?? null,
snapshot_version: data.snapshot_version ?? 1, snapshot_version: data.snapshot_version ?? 1,
projectId: data.projectId || data.project || null, projectId: mapProjectId(data),
}; };
} }

View File

@ -69,7 +69,7 @@ export interface AssetFieldMapping {
embed_provider: string | null; embed_provider: string | null;
checksum: string | null; checksum: string | null;
is_public: boolean; is_public: boolean;
projectId: string | null; projectId: string | null | undefined;
} }
export interface AssetVariantData { export interface AssetVariantData {

View File

@ -46,7 +46,7 @@ export interface ProjectElementDefaultsFieldMapping {
settings_json: string | null; settings_json: string | null;
source_element_id: string | null; source_element_id: string | null;
snapshot_version: number; snapshot_version: number;
projectId: string | null; projectId: string | null | undefined;
} }
export interface ProjectElementDefaultsListFilter { export interface ProjectElementDefaultsListFilter {

View File

@ -2,7 +2,9 @@ import assert from 'node:assert/strict';
import test from 'node:test'; import test from 'node:test';
import db from '../src/db/models/index.ts'; import db from '../src/db/models/index.ts';
import AssetsDBApi from '../src/db/api/assets.ts';
import GenericDBApi from '../src/db/api/base.api.ts'; import GenericDBApi from '../src/db/api/base.api.ts';
import ProjectElementDefaultsDBApi from '../src/db/api/project_element_defaults.ts';
import { createEntityService } from '../src/factories/service.factory.ts'; import { createEntityService } from '../src/factories/service.factory.ts';
import type { import type {
CurrentUser, CurrentUser,
@ -377,6 +379,48 @@ void test('GenericDBApi.partialUpdate rejects positional signature', async () =>
); );
}); });
void test('ProjectElementDefaultsDBApi mapping preserves project relation when omitted', () => {
const mapped = ProjectElementDefaultsDBApi.getFieldMapping({
element_type: 'navigation_next',
name: 'Navigation Forward Button',
sort_order: 1,
settings_json: { opacity: '0.5' },
});
assert.equal(mapped.projectId, undefined);
});
void test('ProjectElementDefaultsDBApi mapping keeps explicit project relation', () => {
const mapped = ProjectElementDefaultsDBApi.getFieldMapping({
element_type: 'navigation_next',
projectId: 'project-1',
settings_json: { opacity: '0.5' },
});
assert.equal(mapped.projectId, 'project-1');
});
void test('AssetsDBApi mapping preserves project relation when omitted', () => {
const mapped = AssetsDBApi.getFieldMapping({
name: 'Lobby image',
asset_type: 'image',
storage_key: 'assets/lobby.jpg',
});
assert.equal(mapped.projectId, undefined);
});
void test('AssetsDBApi mapping keeps explicit project relation', () => {
const mapped = AssetsDBApi.getFieldMapping({
name: 'Lobby image',
asset_type: 'image',
projectId: 'project-1',
storage_key: 'assets/lobby.jpg',
});
assert.equal(mapped.projectId, 'project-1');
});
void test('createEntityService update uses object signature and manages own transaction', async () => { void test('createEntityService update uses object signature and manages own transaction', async () => {
const calls: UpdateContractCalls = {}; const calls: UpdateContractCalls = {};
const transaction: TestManagedTransaction = { const transaction: TestManagedTransaction = {

View File

@ -240,6 +240,7 @@ export const ELEMENT_STYLE_PROPS = [
'fontWeight', 'fontWeight',
'border', 'border',
'borderRadius', 'borderRadius',
'opacity',
'boxShadow', 'boxShadow',
'display', 'display',
'position', 'position',
@ -251,11 +252,6 @@ export const ELEMENT_STYLE_PROPS = [
'color', 'color',
] as const; ] as const;
/**
* Properties that need numeric conversion
*/
const NUMERIC_PROPS = ['opacity', 'zIndex'] as const;
/** /**
* Get trimmed CSS value from unknown input. * Get trimmed CSS value from unknown input.
* Returns empty string for null/undefined, but preserves '0' for explicit zero values. * Returns empty string for null/undefined, but preserves '0' for explicit zero values.
@ -343,9 +339,9 @@ export function buildElementStyle(
} }
/** /**
* All style property names including numeric ones. * All style property names.
* Used for form state management in element-type-defaults admin. * Used for form state management in element-type-defaults admin.
*/ */
export const ALL_STYLE_PROPS = [...ELEMENT_STYLE_PROPS, 'opacity'] as const; export const ALL_STYLE_PROPS = ELEMENT_STYLE_PROPS;
export type StylePropName = (typeof ALL_STYLE_PROPS)[number]; export type StylePropName = (typeof ALL_STYLE_PROPS)[number];