(profile) add icon to custom events

This commit is contained in:
Valentyne Stigloher 2024-10-08 00:38:39 +02:00
parent a3b466863d
commit 590e770229
6 changed files with 53 additions and 12 deletions

View File

@ -97,8 +97,8 @@ export default defineComponent({
return `day day-event day-event-${maxLevel}`; return `day day-event day-event-${maxLevel}`;
}, },
getDayFlag(d: Day): string | null { getDayFlag(d: Day): string | null {
for (const event of (this.year.eventsByDate[d.toString()] || []).filter((e) => e.level === EventLevel.Day && e.flag)) { for (const event of (this.year.eventsByDate[d.toString()] || []).filter((e) => e.level === EventLevel.Day && e.display.type === 'flag')) {
return `/flags/${event.flag}.png`; return `/flags/${event.display.name}.png`;
} }
return null; return null;
}, },

View File

@ -11,11 +11,15 @@
</template> </template>
</component> </component>
<Tooltip v-if="event.level === EventLevel.CustomDay" :text="$t('profile.calendar.customEvents.disclaimer')"> <Tooltip v-if="event.level === EventLevel.CustomDay" :text="$t('profile.calendar.customEvents.disclaimer')">
<Icon v="user" /> <Icon :v="event.display.name" />
</Tooltip> </Tooltip>
<template v-else> <template v-else>
<Flag v-if="event.flag" :alt="$t(`flags_alt.${event.flag.replace(/'/g, '*').replace(/ /g, '_')}`) || ''" :img="`/flags/${event.flag}.png`" /> <Flag
<Icon v-else v="arrow-circle-right" /> v-if="event.display.type === 'flag'"
:alt="$t(`flags_alt.${event.display.name.replace(/'/g, '*').replace(/ /g, '_')}`) || ''"
:img="`/flags/${event.display.name}.png`"
/>
<Icon v-else :v="event.display.name" />
</template> </template>
<T v-if="$te(`calendar.events.${eventName}`, true)" :params="{ param: eventParam }">calendar.events.{{ eventName }}</T> <T v-if="$te(`calendar.events.${eventName}`, true)" :params="{ param: eventParam }">calendar.events.{{ eventName }}</T>
<LinkedText v-else :text="eventName" /> <LinkedText v-else :text="eventName" />

View File

@ -122,11 +122,11 @@ export default defineComponent({
return null; return null;
} }
return new ImmutableArray(...events) return new ImmutableArray(...events)
.filter((e) => e.flag && !e.flag.startsWith('_')) .filter((e) => e.display.type === 'flag' && !e.display.name.startsWith('_'))
.sorted((a, b) => b.level - a.level) .sorted((a, b) => b.level - a.level)
.groupBy((e) => e.level) .groupBy((e) => e.level)
.indexOrFallback(0, ['0', new ImmutableArray()])[1] .indexOrFallback(0, ['0', new ImmutableArray()])[1]
.map((e) => e.flag) .map((e) => e.display.name)
.randomElement(); .randomElement();
}, },
resetFlagIfNotOverwritten(): void { resetFlagIfNotOverwritten(): void {

View File

@ -14,6 +14,8 @@ const today = new Date();
const modelValue = defineModel<CustomEvent[]>(); const modelValue = defineModel<CustomEvent[]>();
const showIconSelector = ref<number | false>(false);
const maxDaysInMonths: Record<number, number> = { const maxDaysInMonths: Record<number, number> = {
1: 31, 1: 31,
2: 29, 2: 29,
@ -79,6 +81,13 @@ const validation = (v: CustomEvent): string | null => {
s.val.day = date.getDate(); s.val.day = date.getDate();
}" }"
/> />
<button
type="button"
:class="['btn', 'btn-outline-secondary', showIconSelector === s.i ? 'btn-secondary text-white border' : '']"
@click="showIconSelector = showIconSelector === s.i ? false : s.i"
>
<Icon :v="s.val.icon" />
</button>
<input <input
v-model="s.val.name" v-model="s.val.name"
class="form-control" class="form-control"
@ -98,6 +107,12 @@ const validation = (v: CustomEvent): string | null => {
@paste="$nextTick(() => s.update(s.val))" @paste="$nextTick(() => s.update(s.val))"
@change="s.update(s.val)" @change="s.update(s.val)"
> >
<IconSelector
v-if="showIconSelector === s.i"
class="hanging shadow shadow-lg border"
@change="s.update({ ...s.val, icon: $event }); showIconSelector = false"
/>
</template> </template>
<template #validation="s"> <template #validation="s">
<p v-if="validation(s.val)" class="small text-danger"> <p v-if="validation(s.val)" class="small text-danger">
@ -107,3 +122,14 @@ const validation = (v: CustomEvent): string | null => {
</template> </template>
</ListInput> </ListInput>
</template> </template>
<style lang="scss" scoped>
.hanging {
position: absolute;
top: 100%;
left: 0;
width: 100%;
max-width: 500px;
z-index: 5000;
}
</style>

View File

@ -352,7 +352,11 @@ const fetchProfiles = async (
sensitive: propv('sensitive', () => JSON.parse(profile.sensitive)), sensitive: propv('sensitive', () => JSON.parse(profile.sensitive)),
markdown: propv('markdown', () => !!profile.markdown), markdown: propv('markdown', () => !!profile.markdown),
events: propv('sensitive', () => JSON.parse(profile.events || '[]')), events: propv('sensitive', () => JSON.parse(profile.events || '[]')),
customEvents: propv('sensitive', () => JSON.parse(profile.customEvents || '[]')), customEvents: propv('sensitive', () => {
return JSON.parse(profile.customEvents || '[]').map((customEvent: Partial<CustomEvent>) => {
return { icon: 'user', ...customEvent };
});
}),
lastUpdate: propv('lastUpdate', () => profile.lastUpdate), lastUpdate: propv('lastUpdate', () => profile.lastUpdate),
}; };
p[profile.locale] = profile_obj; p[profile.locale] = profile_obj;

View File

@ -77,7 +77,7 @@ type EventLevelValue = typeof EventLevel[keyof typeof EventLevel];
export class Event { export class Event {
name: string; name: string;
flag: string | null; display: { type: 'flag' | 'icon', name: string };
month: number; month: number;
generator: (monthDays: Generator<Day, void>) => Generator<Day, void>; generator: (monthDays: Generator<Day, void>) => Generator<Day, void>;
level: EventLevelValue; level: EventLevelValue;
@ -89,7 +89,7 @@ export class Event {
constructor( constructor(
name: string, name: string,
flag: string | null, display: { type: 'flag' | 'icon', name: string } | string | null,
month: number, month: number,
generator: (monthDays: Generator<Day, void>) => Generator<Day, void>, generator: (monthDays: Generator<Day, void>) => Generator<Day, void>,
level: EventLevelValue, level: EventLevelValue,
@ -99,7 +99,13 @@ export class Event {
yearCondition: ((year: number) => boolean) | null = null, yearCondition: ((year: number) => boolean) | null = null,
) { ) {
this.name = name; this.name = name;
this.flag = flag; if (typeof display === 'string') {
this.display = { type: 'flag', name: display };
} else if (display === null) {
this.display = { type: 'icon', name: 'arrow-circle-right' };
} else {
this.display = display;
}
this.month = month; this.month = month;
this.generator = generator; this.generator = generator;
this.level = level; this.level = level;
@ -196,7 +202,7 @@ export class Event {
static fromCustom(customSettings: CustomEvent): Event { static fromCustom(customSettings: CustomEvent): Event {
return new Event( return new Event(
customSettings.name, customSettings.name,
null, { type: 'icon', name: customSettings.icon },
customSettings.month, customSettings.month,
day(customSettings.day), day(customSettings.day),
EventLevel.CustomDay, EventLevel.CustomDay,
@ -316,6 +322,7 @@ export function dayYear(day: number, year: number): (monthDays: Generator<Day, v
export interface CustomEvent { export interface CustomEvent {
month: number; month: number;
day: number; day: number;
icon: string;
name: string; name: string;
comment: string; comment: string;
} }