From 62a11283afb188db8e0db1bc2fb43cc395c0a547 Mon Sep 17 00:00:00 2001 From: Wingy Date: Mon, 23 Oct 2023 11:38:41 -0700 Subject: [PATCH] feat(web): custom stylesheets (#4602) * add initial ui and api definitions for stylesheets * proper saving * make custom css work * add textarea * rebuild api * run prettier * add typecast * update typings * move css accordion to be sorted alphabetically * set content-type properly * rename stylesheets to theme * fix server test --- cli/src/api/open-api/api.ts | 19 ++++ mobile/openapi/.openapi-generator/FILES | 3 + mobile/openapi/README.md | Bin 21859 -> 21915 bytes mobile/openapi/doc/SystemConfigDto.md | Bin 1201 -> 1271 bytes mobile/openapi/doc/SystemConfigThemeDto.md | Bin 0 -> 419 bytes mobile/openapi/lib/api.dart | Bin 7116 -> 7159 bytes mobile/openapi/lib/api_client.dart | Bin 21278 -> 21370 bytes .../openapi/lib/model/system_config_dto.dart | Bin 5438 -> 5671 bytes .../lib/model/system_config_theme_dto.dart | Bin 0 -> 2898 bytes .../openapi/test/system_config_dto_test.dart | Bin 1678 -> 1787 bytes .../test/system_config_theme_dto_test.dart | Bin 0 -> 586 bytes server/immich-openapi-specs.json | 17 ++- .../dto/system-config-theme.dto.ts | 6 ++ .../system-config/dto/system-config.dto.ts | 6 ++ .../system-config/system-config.core.ts | 3 + .../system-config.service.spec.ts | 3 + .../infra/entities/system-config.entity.ts | 5 + web/src/api/open-api/api.ts | 19 ++++ .../settings/setting-textarea.svelte | 53 ++++++++++ .../settings/theme/theme-settings.svelte | 98 ++++++++++++++++++ web/src/routes/+layout.svelte | 1 + .../routes/admin/system-settings/+page.svelte | 5 + web/src/routes/custom.css/+server.ts | 9 ++ 23 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 mobile/openapi/doc/SystemConfigThemeDto.md create mode 100644 mobile/openapi/lib/model/system_config_theme_dto.dart create mode 100644 mobile/openapi/test/system_config_theme_dto_test.dart create mode 100644 server/src/domain/system-config/dto/system-config-theme.dto.ts create mode 100644 web/src/lib/components/admin-page/settings/setting-textarea.svelte create mode 100644 web/src/lib/components/admin-page/settings/theme/theme-settings.svelte create mode 100644 web/src/routes/custom.css/+server.ts diff --git a/cli/src/api/open-api/api.ts b/cli/src/api/open-api/api.ts index 8d278b44ce..2133d04113 100644 --- a/cli/src/api/open-api/api.ts +++ b/cli/src/api/open-api/api.ts @@ -3307,6 +3307,12 @@ export interface SystemConfigDto { * @memberof SystemConfigDto */ 'storageTemplate': SystemConfigStorageTemplateDto; + /** + * + * @type {SystemConfigThemeDto} + * @memberof SystemConfigDto + */ + 'theme': SystemConfigThemeDto; /** * * @type {SystemConfigThumbnailDto} @@ -3741,6 +3747,19 @@ export interface SystemConfigTemplateStorageOptionDto { */ 'yearOptions': Array; } +/** + * + * @export + * @interface SystemConfigThemeDto + */ +export interface SystemConfigThemeDto { + /** + * + * @type {string} + * @memberof SystemConfigThemeDto + */ + 'customCss': string; +} /** * * @export diff --git a/mobile/openapi/.openapi-generator/FILES b/mobile/openapi/.openapi-generator/FILES index 85b96e6473..747c435dd3 100644 --- a/mobile/openapi/.openapi-generator/FILES +++ b/mobile/openapi/.openapi-generator/FILES @@ -135,6 +135,7 @@ doc/SystemConfigPasswordLoginDto.md doc/SystemConfigReverseGeocodingDto.md doc/SystemConfigStorageTemplateDto.md doc/SystemConfigTemplateStorageOptionDto.md +doc/SystemConfigThemeDto.md doc/SystemConfigThumbnailDto.md doc/SystemConfigTrashDto.md doc/TagApi.md @@ -302,6 +303,7 @@ lib/model/system_config_password_login_dto.dart lib/model/system_config_reverse_geocoding_dto.dart lib/model/system_config_storage_template_dto.dart lib/model/system_config_template_storage_option_dto.dart +lib/model/system_config_theme_dto.dart lib/model/system_config_thumbnail_dto.dart lib/model/system_config_trash_dto.dart lib/model/tag_response_dto.dart @@ -456,6 +458,7 @@ test/system_config_password_login_dto_test.dart test/system_config_reverse_geocoding_dto_test.dart test/system_config_storage_template_dto_test.dart test/system_config_template_storage_option_dto_test.dart +test/system_config_theme_dto_test.dart test/system_config_thumbnail_dto_test.dart test/system_config_trash_dto_test.dart test/tag_api_test.dart diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 47d04b9bd2d6f15c66ed5071d20a712233aedf9f..07d2cf402fe02b8fdc9cba55f9f41908f00f6d80 100644 GIT binary patch delta 32 mcmaF7igEU8#tr@f%&EDllOOnrv4&)TSQGsvHv0yMu>t_wa10~> delta 14 VcmbQen(^@}#tr@fo7)3KSOGEe1;_vZ diff --git a/mobile/openapi/doc/SystemConfigDto.md b/mobile/openapi/doc/SystemConfigDto.md index a5b8db773c5b67612fa5318172d16102ee73cbb6..d426bef34564b45e9173e6933d329929f85a0794 100644 GIT binary patch delta 34 ncmdnU`JHn^1v67>?qmgKQPz-*)ZEm`4;h77K&;KF%sz|&$|ef` delta 12 Tcmey)xsh{21@q>8%$AG*BMStS diff --git a/mobile/openapi/doc/SystemConfigThemeDto.md b/mobile/openapi/doc/SystemConfigThemeDto.md new file mode 100644 index 0000000000000000000000000000000000000000..bcdbb690cb99114be44ec6577fba49b2e45c149a GIT binary patch literal 419 zcma)&v2Fq}42JhSg{2!PkrMWHq8vk|f>2>YNEcnq5tYPIVg{r>e3L6uX_wZE^*O(P z$8LZk1{0n3Wbv%G*Uab_6pn7#ozP>;Bt+A|D;W!XLKt-rP5*8N6kXR@lUO((DKSiL z^~am*tU6c0l>H?$ z`9;oB7PXXHPA&{16c%E?e=dsv6Rhg`aCVswhX<`^Z_9bRT54|_OZ~-TU{gP)j+E4R ff;@%q?)m2BpS|TE3WJU00{^i18u)AYR0#12F@1rf literal 0 HcmV?d00001 diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart index e72c1da168fb575c404a1f968703ec20fd668ae2..091a38e36d25dc67a14d31842cd67dcfeb7e7904 100644 GIT binary patch delta 23 ecmX?O{@r{-r8rY+?&LsWsmTdqyqn9#Ls~GIAxz?FybFA}0egJSF5HJ7$ delta 14 WcmeyhjB(yF#tp&Fo7X#^<_7>Zg9fYs diff --git a/mobile/openapi/lib/model/system_config_dto.dart b/mobile/openapi/lib/model/system_config_dto.dart index 932e68466b7d70aac79cfdb5057dcadebe362fe8..8e15d7e21996579bd0ad8fdf5cd41c47410e341a 100644 GIT binary patch delta 150 zcmdm|wOnUIEfaHUZt7$OCXvn6Ox276K#ogEzCuX`kYUZmr7+o=PjVB>c}8v^U%}QE zEU|enYY`(;YVKw!c0EQ;poFaoNd0DKj)#nbK(2bM0!U$Iu^w1hh)a=03@B`+5L{VY glA7zBpO==I9s;sqav+}=$RH)YzidEyvWTb_00EsZe*gdg delta 46 zcmV+}0MY-aEWRqReFC$V0(k+mE(F;Dvm^#!0kfM283D7x2;2d)!3qxqvkwpK29pRD EAB;Q?ng9R* diff --git a/mobile/openapi/lib/model/system_config_theme_dto.dart b/mobile/openapi/lib/model/system_config_theme_dto.dart new file mode 100644 index 0000000000000000000000000000000000000000..f34234952deb4b88a64e776cf697b3f722defe69 GIT binary patch literal 2898 zcmbVOVQM z8JdyhtAc5pzD$04IiXvzl}huhR5~j~%`c&qt>Hz+Yrf;s#{Iq6HA>r{2dnq&V6vvQ zndbkrLZiE6JN#{!#(>!Qk42-E$?4WzuG%zzszyxOVO)xLGYEH(9OZ7R_wMWcKrq zSza-1CKKGwf+|5ZT(U+a_`RA;@|qa~9}mXz-L;aX*sdz9?Zzs2m;lTWgb&=dS{h&= z`5x9G+YJbpX3i6I3Ry%H4WNerY$Z&Rx5ld7wJ|Y1JYHZr=xnu+TNoa>#aHSx*BT)} zgL|cFDnc`>G^A;?y#K^=EX`J2UqCts4^__Uh<1tlCttq!D-ho(`25`E=&c@;!#$oz zM@S1>ZlPkPx>g0p1YDFsJtP{*b8ZaN2O=GLthf=znMFgPNgu)EFfO^n#43Lgxhkh2 znAbzN^oQYcGj$-oXU#7@Kn%qJH7N2qSoPK@i4i?NrI4(KPq+jrd}aM`yz&S+i?yB( zTTC}-f6A#h)lNLlo)(To@qZQ-Fj;`_F$2OH_{{2-8z{Bfb@A4233XVa!IZ?h#(Fm~ z$hJngkT&+hIC+kkX*4gfQ(TkjHb+63jHH%f&smXY*q)Uth$+7il=iPK4+mohtIw~; z6jO>^b|gGZs$T~XelfqOX4}U1JY@TtpkkMbw2?dz@I# z^znJmhvzB{Vw{lVTvb>=2NZ$z$nja~BsUIAV~@&7SW$Q-j66NeJ=`atcV1ReX;BZ^ zCG=M=itDJ3k#UEIi9tC8dFj*j@SxSW{ez+USumym_kWTBM^)+>`j*gfI&{bGB@8EI zhKCfM#dPNSv3bHKuIfY2XF_*^o4z7q$5-_{UR|)n*^XHH4!;Q4+B^Qu4>Ss$zt<=w z@C3=|Iy4rRj<+;hwVe_kVkIHU1_(#OiiZ|{Z02}S zn-|N;B*5)PBAEfcqYZi(Ua3%e2G3xIl;e99+;hO=&EU4w8VufkT;9>!S*HYd<_+&- XzmxB9;?Ex(B%|Zqy`Wu9aM=6{SG=@5 literal 0 HcmV?d00001 diff --git a/mobile/openapi/test/system_config_dto_test.dart b/mobile/openapi/test/system_config_dto_test.dart index 1a3e38a9e9d4ad25c538bf5bda356b364f99d6af..30dbe6860b02898d12493933c9f4b610efdafe90 100644 GIT binary patch delta 38 ocmeC<{mr{!Gb>MOZmLU3zCuX`kTKbiMUfT4`p9ZEc@yg$02Ln&lK=n! delta 11 Scmey(+sC_MGwWmpw%Y(5Y6PGF diff --git a/mobile/openapi/test/system_config_theme_dto_test.dart b/mobile/openapi/test/system_config_theme_dto_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..98e283559e42bfb951f62fb9d983c93f312bc1ea GIT binary patch literal 586 zcmZutPfNov6u;+FJWt(VuDX+K3><4G16@Ju!BZC6v<5_F=H8c1-ZY+u$J5Dc@ zw2nzfMTv%@65Is39W`r(^&HdKV z>L0{$>tbIn0B`DN3wRQE8LZ>oR>?}#d4m^8oFbn}l+ZCDCsX()0LZ9>WG#rWNWoz} zN}Nnr1mU$&y`DtgWE2+7;8!?Ezc?dg4MlIA>bBOR0)&Jpp+W<$;h+s}Yuo_GKjiVO Z#Oxr85Y#g SystemConfigThemeDto) + @ValidateNested() + @IsObject() + theme!: SystemConfigThemeDto; } export function mapConfig(config: SystemConfig): SystemConfigDto { diff --git a/server/src/domain/system-config/system-config.core.ts b/server/src/domain/system-config/system-config.core.ts index 66c72fc92e..4fd2faa295 100644 --- a/server/src/domain/system-config/system-config.core.ts +++ b/server/src/domain/system-config/system-config.core.ts @@ -114,6 +114,9 @@ export const defaults = Object.freeze({ enabled: true, days: 30, }, + theme: { + customCss: '', + }, }); export enum FeatureFlag { diff --git a/server/src/domain/system-config/system-config.service.spec.ts b/server/src/domain/system-config/system-config.service.spec.ts index 0444217c09..36cdb6543e 100644 --- a/server/src/domain/system-config/system-config.service.spec.ts +++ b/server/src/domain/system-config/system-config.service.spec.ts @@ -115,6 +115,9 @@ const updatedConfig = Object.freeze({ enabled: true, days: 10, }, + theme: { + customCss: '', + }, }); describe(SystemConfigService.name, () => { diff --git a/server/src/infra/entities/system-config.entity.ts b/server/src/infra/entities/system-config.entity.ts index 47b1f69fd9..6bd552111a 100644 --- a/server/src/infra/entities/system-config.entity.ts +++ b/server/src/infra/entities/system-config.entity.ts @@ -90,6 +90,8 @@ export enum SystemConfigKey { TRASH_ENABLED = 'trash.enabled', TRASH_DAYS = 'trash.days', + + THEME_CUSTOM_CSS = 'theme.customCss', } export enum TranscodePolicy { @@ -221,4 +223,7 @@ export interface SystemConfig { enabled: boolean; days: number; }; + theme: { + customCss: string; + }; } diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 8d278b44ce..2133d04113 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -3307,6 +3307,12 @@ export interface SystemConfigDto { * @memberof SystemConfigDto */ 'storageTemplate': SystemConfigStorageTemplateDto; + /** + * + * @type {SystemConfigThemeDto} + * @memberof SystemConfigDto + */ + 'theme': SystemConfigThemeDto; /** * * @type {SystemConfigThumbnailDto} @@ -3741,6 +3747,19 @@ export interface SystemConfigTemplateStorageOptionDto { */ 'yearOptions': Array; } +/** + * + * @export + * @interface SystemConfigThemeDto + */ +export interface SystemConfigThemeDto { + /** + * + * @type {string} + * @memberof SystemConfigThemeDto + */ + 'customCss': string; +} /** * * @export diff --git a/web/src/lib/components/admin-page/settings/setting-textarea.svelte b/web/src/lib/components/admin-page/settings/setting-textarea.svelte new file mode 100644 index 0000000000..99a672c472 --- /dev/null +++ b/web/src/lib/components/admin-page/settings/setting-textarea.svelte @@ -0,0 +1,53 @@ + + +
+
+ + {#if required} +
*
+ {/if} + + {#if isEdited} +
+ Unsaved change +
+ {/if} +
+ + {#if desc} +

+ {desc} +

+ {:else} + + {/if} + +