Skip to content

Commit c332703

Browse files
authored
feat: collection color image management (#3904)
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
1 parent a472d8b commit c332703

File tree

6 files changed

+87
-20
lines changed

6 files changed

+87
-20
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE collections DROP COLUMN IF EXISTS "imageUrl";
2+
ALTER TABLE collections DROP COLUMN IF EXISTS "color";
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE collections ADD COLUMN IF NOT EXISTS "imageUrl" VARCHAR(1024);
2+
ALTER TABLE collections ADD COLUMN IF NOT EXISTS "color" VARCHAR(30);

frontend/src/modules/admin/modules/collections/components/lf-collection-add.vue

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,69 @@
5656
</lf-field>
5757
</article>
5858

59-
<!-- Logo URL -->
60-
<article class="mb-6">
61-
<lf-field label-text="Logo URL">
62-
<lf-input
63-
v-model="form.logoUrl"
64-
class="h-10"
65-
placeholder="https://example.com/logo.png"
66-
:invalid="$v.logoUrl.$invalid && $v.logoUrl.$dirty"
67-
@blur="$v.logoUrl.$touch()"
68-
@change="$v.logoUrl.$touch()"
69-
/>
70-
<lf-field-messages
71-
:validation="$v.logoUrl"
72-
:error-messages="{ url: 'Please enter a valid URL' }"
73-
/>
74-
</lf-field>
75-
</article>
59+
<!-- Appearance section -->
60+
<div class="mb-6">
61+
<h6 class="text-sm font-semibold text-gray-500 mb-4 border-b border-gray-100 pb-2">
62+
Appearance
63+
</h6>
64+
65+
<!-- Card image URL -->
66+
<article class="mb-6">
67+
<lf-field label-text="Card image URL" :required="true">
68+
<lf-input
69+
v-model="form.imageUrl"
70+
class="h-10"
71+
placeholder="https://example.com/card-image.png"
72+
:invalid="$v.imageUrl.$invalid && $v.imageUrl.$dirty"
73+
@blur="$v.imageUrl.$touch()"
74+
@change="$v.imageUrl.$touch()"
75+
/>
76+
<lf-field-messages
77+
:validation="$v.imageUrl"
78+
:error-messages="{ url: 'Please enter a valid URL' }"
79+
/>
80+
<span class="text-2xs text-gray-400">Recommended image size: 800×240px</span>
81+
</lf-field>
82+
</article>
83+
84+
<!-- Collection logo URL -->
85+
<article class="mb-6">
86+
<lf-field label-text="Collection logo URL" :required="true">
87+
<lf-input
88+
v-model="form.logoUrl"
89+
class="h-10"
90+
placeholder="https://example.com/logo.png"
91+
:invalid="$v.logoUrl.$invalid && $v.logoUrl.$dirty"
92+
@blur="$v.logoUrl.$touch()"
93+
@change="$v.logoUrl.$touch()"
94+
/>
95+
<lf-field-messages
96+
:validation="$v.logoUrl"
97+
:error-messages="{ url: 'Please enter a valid URL' }"
98+
/>
99+
<span class="text-2xs text-gray-400">Recommended image size: 400×400px</span>
100+
</lf-field>
101+
</article>
102+
103+
<!-- Collection color -->
104+
<article class="mb-6">
105+
<lf-field label-text="Collection color">
106+
<div class="flex items-center gap-2">
107+
<span
108+
class="w-6 h-6 rounded-full flex-shrink-0 border border-gray-200"
109+
:style="{ backgroundColor: form.color || '#009AFF' }"
110+
/>
111+
<lf-input
112+
v-model="form.color"
113+
class="h-10 flex-grow"
114+
placeholder="#FE9A00"
115+
type="color"
116+
/>
117+
</div>
118+
<span class="text-2xs text-gray-400">Leave blank to use the default color #009AFF</span>
119+
</lf-field>
120+
</article>
121+
</div>
76122

77123
<!-- Category -->
78124
<article class="mb-5">
@@ -204,6 +250,8 @@ const form = reactive<CollectionFormModel>({
204250
type: '',
205251
categoryId: null,
206252
logoUrl: '',
253+
imageUrl: '',
254+
color: '',
207255
projects: [],
208256
starred: false,
209257
});
@@ -214,6 +262,7 @@ const rules = {
214262
maxLength,
215263
},
216264
description: { required: (value: string) => value.trim().length },
265+
imageUrl: { url },
217266
logoUrl: { url },
218267
projects: { required: (value: any) => value.length > 0 },
219268
};
@@ -239,6 +288,8 @@ const fillForm = (record?: CollectionModel) => {
239288
form.type = record.category?.categoryGroupType;
240289
form.categoryId = record.categoryId || null;
241290
form.logoUrl = record.logoUrl || '';
291+
form.imageUrl = record.imageUrl || '';
292+
form.color = record.color || '';
242293
}
243294
244295
formSnapshot();
@@ -263,6 +314,8 @@ const onSubmit = () => {
263314
name: form.name,
264315
description: form.description,
265316
logoUrl: form.logoUrl || undefined,
317+
imageUrl: form.imageUrl || undefined,
318+
color: form.color || undefined,
266319
projects: form.projects.map((project: any) => ({
267320
id: project.id,
268321
starred: project?.starred || false,

frontend/src/modules/admin/modules/collections/models/collection.model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export interface CollectionModel {
88
slug: string;
99
categoryId?: string;
1010
logoUrl?: string;
11+
imageUrl?: string;
12+
color?: string;
1113
ssoUserId?: string;
1214
projects: InsightsProjectModel[];
1315
category: Category & {categoryGroupType: string, categoryGroupName: string};
@@ -19,6 +21,8 @@ export interface CollectionRequest {
1921
description: string;
2022
categoryId: string | null;
2123
logoUrl?: string;
24+
imageUrl?: string;
25+
color?: string;
2226
slug: string;
2327
starred: boolean;
2428
projects: {
@@ -32,6 +36,8 @@ export interface CollectionFormModel {
3236
type: string | null;
3337
categoryId: string | null;
3438
logoUrl: string;
39+
imageUrl: string;
40+
color: string;
3541
projects: InsightsProjectModel[];
3642
starred: boolean;
3743
}

scripts/cli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,7 @@ while test $# -gt 0; do
10581058
exit
10591059
;;
10601060
clean-start-fe-dev)
1061-
IGNORED_SERVICES=("frontend" "python-worker" "job-generator" "discord-ws" "webhook-api" "profiles-worker" "organizations-enrichment-worker" "merge-suggestions-worker" "members-enrichment-worker" "exports-worker" "entity-merging-worker")
1061+
IGNORED_SERVICES=("frontend" "python-worker" "job-generator" "discord-ws" "webhook-api" "profiles-worker" "organizations-enrichment-worker" "merge-suggestions-worker" "members-enrichment-worker" "exports-worker" "entity-merging-worker" "cache-worker" "categorization-worker" "cron-service" "data-sink-worker" "git-integration" "integration-run-worker" "integration-stream-worker" "nango-webhook-api" "nango-worker" "script-executor-worker" "search-sync-api" "search-sync-worker" "security-best-practices-worker" "snowflake-connectors-worker")
10621062
CLEAN_START=1
10631063
DEV=1
10641064
start

services/libs/data-access-layer/src/collections/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ import { QueryOptions } from '../utils'
1515

1616
export interface ICreateCollection {
1717
categoryId: string
18+
color?: string | null
1819
description?: string
20+
imageUrl?: string | null
1921
name: string
2022
slug?: string
2123
starred: boolean
@@ -80,9 +82,11 @@ export interface ICollectionInsightProject {
8082

8183
export enum CollectionField {
8284
CATEGORY_ID = 'categoryId',
85+
COLOR = 'color',
8386
CREATED_AT = 'createdAt',
8487
DESCRIPTION = 'description',
8588
ID = 'id',
89+
IMAGE_URL = 'imageUrl',
8690
IS_PRIVATE = 'isPrivate',
8791
LOGO_URL = 'logoUrl',
8892
NAME = 'name',
@@ -136,8 +140,8 @@ export async function createCollection(
136140
): Promise<ICollection> {
137141
return qx.selectOne(
138142
`
139-
INSERT INTO collections (name, description, slug, "categoryId", starred, "logoUrl")
140-
VALUES ($(name), $(description), $(slug), $(categoryId), $(starred), $(logoUrl))
143+
INSERT INTO collections (name, description, slug, "categoryId", starred, "logoUrl", "imageUrl", color)
144+
VALUES ($(name), $(description), $(slug), $(categoryId), $(starred), $(logoUrl), $(imageUrl), $(color))
141145
RETURNING *
142146
`,
143147
collection,

0 commit comments

Comments
 (0)