Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable custom sections #3963

Draft
wants to merge 47 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
21e36f4
initial commit
sircharlo Jan 16, 2025
b20932d
initial implementation of dialog and custom color logic
sircharlo Jan 16, 2025
961ea8d
Merge branch 'master' into feat/section-management
sircharlo Jan 16, 2025
07990c7
fix lint errors
sircharlo Jan 16, 2025
bef22d5
Merge branch 'master' into feat/section-management
mtdvlpr Jan 17, 2025
706ab85
Allow sorting of custom sections; Add color picker; Create dialog to …
sircharlo Jan 17, 2025
cd25a05
allow label change, delete section and set random color when creating…
sircharlo Jan 17, 2025
28e8617
Merge branch 'master' into feat/section-management
mtdvlpr Jan 17, 2025
a13270d
Add extra media button and actually show media in custom sections
sircharlo Jan 17, 2025
ed106f0
Merge branch 'master' into feat/section-management
sircharlo Jan 17, 2025
53eedac
Properly persist drag/drop reordering and list changing for custom se…
sircharlo Jan 17, 2025
caecc66
Update DialogCustomSectionEdit.vue
sircharlo Jan 18, 2025
c6aa393
Merge branch 'master' into feat/section-management
sircharlo Jan 18, 2025
cce021c
fix: mediaList.uniqueId is possibly undefined
sircharlo Jan 18, 2025
59a777c
Merge branch 'master' into feat/section-management
sircharlo Jan 18, 2025
d701da0
fix for empty list glitch
sircharlo Jan 18, 2025
694b821
fix for extra media button colors
sircharlo Jan 18, 2025
992ead6
add animation while sorting
sircharlo Jan 18, 2025
3fe4bef
fix scroll behaviour
sircharlo Jan 18, 2025
2912c65
add delete section button to header
sircharlo Jan 19, 2025
dff28d5
import deleteSection properly
sircharlo Jan 19, 2025
b35a245
Merge branch 'master' into feat/section-management
sircharlo Jan 19, 2025
8761d56
Merge branch 'master' into feat/section-management
mtdvlpr Jan 19, 2025
575f451
Merge branch 'master' into feat/section-management
mtdvlpr Jan 19, 2025
d2a8fb7
Merge branch 'master' into feat/section-management
sircharlo Jan 20, 2025
0c09686
Merge branch 'master' into feat/section-management
mtdvlpr Jan 20, 2025
a8584c4
add color changer to media section header
sircharlo Jan 20, 2025
1293847
Merge branch 'master' into feat/section-management
sircharlo Jan 21, 2025
0e5df23
Show media items in standard "additional" section if the referenced s…
sircharlo Jan 21, 2025
179c195
Merge branch 'feat/section-management' of https://github.com/sircharl…
sircharlo Jan 21, 2025
b2219fc
Add new section button to bottom of media list
sircharlo Jan 21, 2025
830bfff
Merge branch 'master' into feat/section-management
mtdvlpr Jan 21, 2025
e6d9b2d
Add reorder grabber to dialog
sircharlo Jan 21, 2025
21847d5
fix media list keys and reset sort button
sircharlo Jan 21, 2025
175c745
remove unused key
sircharlo Jan 21, 2025
5d858a9
fix labels
sircharlo Jan 21, 2025
f64d3bc
Merge branch 'master' into feat/section-management
mtdvlpr Jan 22, 2025
49f6d98
remove items from customsections to prevent needless deduplication
sircharlo Jan 22, 2025
73d2a5b
Allow renaming the standard "additional" section, changing its color …
sircharlo Jan 22, 2025
db0bbf5
Merge branch 'master' into feat/section-management
sircharlo Jan 22, 2025
7622265
Merge branch 'master' into feat/section-management
sircharlo Jan 22, 2025
70ac4e2
Merge branch 'master' into feat/section-management
mtdvlpr Jan 26, 2025
2884934
Merge branch 'master' into feat/section-management
mtdvlpr Jan 28, 2025
f8af03c
Merge branch 'master' into feat/section-management
mtdvlpr Jan 29, 2025
3c83f54
Merge branch 'master' into feat/section-management
mtdvlpr Jan 31, 2025
844e0b9
Merge branch 'master' into feat/section-management
mtdvlpr Feb 6, 2025
94fc9a8
Merge branch 'master' into feat/section-management
sircharlo Feb 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build/icons/gradient.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions build/icons/style.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions build/icons/tune.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
197 changes: 197 additions & 0 deletions src/components/dialog/DialogCustomSectionEdit.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
<template>
<q-dialog v-model="open" persistent>
<div
class="bg-secondary-contrast flex medium-overlay q-px-none"
style="flex-flow: column"
>
<div class="text-h6 row q-px-md q-pt-lg q-pb-md">
{{ t('custom-sections') }}
</div>
<div class="row q-px-md overflow-auto">
<q-list bordered class="full-width" separator>
<Sortable
item-key="uniqueId"
:list="selectedDateObject?.customSections"
@end="handleMediaSectionSort"
>
<template #item="{ element }: { element: DynamicMediaSection }">
<q-item
:key="element.uniqueId"
clickable
:style="{
'--bg-color': element.bgColor,
'--text-color': element.textColor,
}"
>
<q-item-section>
<q-item-label>
<q-input v-model="element.label" outlined />
</q-item-label>
</q-item-section>
<q-item-section side>
<q-chip class="custom-bg-color custom-text-color" round>
{{ t('color') }}
<q-popup-proxy
cover
transition-hide="scale"
transition-show="scale"
>
<q-color
v-model="element.bgColor"
format-model="rgb"
@update:model-value="setTextColor(element)"
/>
</q-popup-proxy>
</q-chip>
</q-item-section>
<q-item-section side>
<q-btn
color="negative"
flat
icon="mmm-delete"
round
size="sm"
@click="deleteSection(element.uniqueId)"
/>
</q-item-section>
</q-item>
</template>
</Sortable>
</q-list>
</div>
<div class="row q-px-md q-pb-md">
<q-btn color="primary" label="Add section" @click="addSection" />
</div>
<!-- <div class="row q-px-md"></div>
<div class="row q-px-md q-pt-md"></div> -->
<div class="row q-px-md q-py-md justify-end">
<q-btn v-close-popup color="primary" flat :label="t('close')" />
</div>
</div>
</q-dialog>
</template>

<script setup lang="ts">
import type { SortableEvent } from 'sortablejs';
import type { DynamicMediaSection } from 'src/types';

import { storeToRefs } from 'pinia';
import { Sortable } from 'sortablejs-vue3';
import { useCurrentStateStore } from 'src/stores/current-state';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';

const { t } = useI18n();

const currentState = useCurrentStateStore();
const { selectedDateObject } = storeToRefs(currentState);

const open = defineModel<boolean>({ required: true });

const handleMediaSectionSort = (event: SortableEvent) => {
const sections = selectedDateObject.value?.customSections;
if (
!sections ||
event?.oldIndex === undefined ||
event?.newIndex === undefined
)
return;

console.log('Before Move:', [...sections]);
if (event.oldIndex === event.newIndex) return;

const [item] = sections.splice(event.oldIndex, 1);
if (!item) {
console.error('No item found at old index:', event.oldIndex);
return;
}

sections.splice(event.newIndex, 0, item);
console.log('After Move:', [...sections]);
};

const getRandomColor = () => {
const min = 60; // Minimum brightness for each RGB channel
const max = 200; // Maximum brightness for each RGB channel
const randomChannel = () => Math.floor(Math.random() * (max - min + 1)) + min;

const r = randomChannel();
const g = randomChannel();
const b = randomChannel();

return `rgb(${r}, ${g}, ${b})`;
};

const addSection = () => {
if (selectedDateObject.value && !selectedDateObject.value?.customSections)
selectedDateObject.value.customSections = [];
const newSection: DynamicMediaSection = {
alwaysShow: true,
bgColor: getRandomColor(),
extraMediaShortcut: true,
items: [],
label: ref(t('imported-media')).value,
textColor: '#ffffff',
uniqueId: 'custom-' + Date.now().toString(),
};
setTextColor(newSection);
selectedDateObject.value?.customSections?.push(newSection);
};

const deleteSection = (uniqueId: string) => {
selectedDateObject.value?.customSections?.splice(
selectedDateObject.value?.customSections.findIndex(
(s) => s.uniqueId === uniqueId,
),
1,
);
};

const setTextColor = (section: DynamicMediaSection) => {
const bgColor = section.bgColor;
if (!bgColor) return;
// Convert HEX to RGB
let b, g, r;
if (bgColor.startsWith('#')) {
const hex = bgColor.replace('#', '');
[r, g, b] = [0, 1, 2].map((i) =>
parseInt(
hex.length === 3
? hex.charAt(i) + hex.charAt(i)
: hex.slice(i * 2, i * 2 + 2),
16,
),
);
} else if (bgColor.startsWith('rgb')) {
[r, g, b] = bgColor
.replace(/rgba?|\(|\)|\s/g, '')
.split(',')
.map(Number);
} else {
console.warn('Invalid color format');
section.textColor = '#000000'; // Default to black if invalid input
}

// Calculate relative luminance
const luminance = (val: number | undefined) => {
if (val === undefined) return 0;
val /= 255;
return val <= 0.03928 ? val / 12.92 : Math.pow((val + 0.055) / 1.055, 2.4);
};

const lum =
0.2126 * luminance(r) + 0.7152 * luminance(g) + 0.0722 * luminance(b);

// Return white or black based on contrast
section.textColor = lum > 0.179 ? '#000000' : '#ffffff';
};
</script>
<style lang="scss" scoped>
.custom-text-color {
color: var(--bg-color);
}
.custom-bg-color {
background-color: var(--bg-color);
color: var(--text-color);
}
</style>
36 changes: 26 additions & 10 deletions src/components/header/HeaderCalendar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -462,10 +462,10 @@ const mediaSortCanBeReset = computed<boolean>(() => {
}

const mediaToConsider = [
...getVisibleMediaForSection.value.tgw,
...getVisibleMediaForSection.value.ayfm,
...getVisibleMediaForSection.value.lac,
...getVisibleMediaForSection.value.wt,
...(getVisibleMediaForSection.value.tgw || []),
...(getVisibleMediaForSection.value.ayfm || []),
...(getVisibleMediaForSection.value.lac || []),
...(getVisibleMediaForSection.value.wt || []),
];

for (let i = 0; i < mediaToConsider.length - 1; i++) {
Expand Down Expand Up @@ -507,10 +507,10 @@ const resetSort = () => {

// Combine all media items into one array
const mediaToSort = [
...getAllMediaForSection.value.tgw,
...getAllMediaForSection.value.ayfm,
...getAllMediaForSection.value.lac,
...getAllMediaForSection.value.wt,
...(getAllMediaForSection.value.tgw || []),
...(getAllMediaForSection.value.ayfm || []),
...(getAllMediaForSection.value.lac || []),
...(getAllMediaForSection.value.wt || []),
];

// Sort the media array in ascending order by `sortOrderOriginal`
Expand All @@ -521,13 +521,29 @@ const resetSort = () => {
),
);

const customSections = [
...new Set(
selectedDateObject.value?.customSections?.map(
(section) => section.uniqueId,
) ?? [],
),
];

const mediaFromCustomSections = customSections.flatMap(
(sectionId) =>
selectedDateObject.value?.dynamicMedia?.filter(
(item) => item.section === sectionId,
) || [],
);

selectedDateObject.value.dynamicMedia = [
...getAllMediaForSection.value.additional,
...mediaFromCustomSections,
...(getAllMediaForSection.value.additional || []),
...sortedMedia.filter((item) => item.section === 'tgw'),
...sortedMedia.filter((item) => item.section === 'ayfm'),
...sortedMedia.filter((item) => item.section === 'lac'),
...sortedMedia.filter((item) => item.section === 'wt'),
...getAllMediaForSection.value.circuitOverseer,
...(getAllMediaForSection.value.circuitOverseer || []),
];
};
</script>
2 changes: 1 addition & 1 deletion src/components/media/MediaEmptyState.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div
v-if="
!currentSettings?.disableMediaFetching ||
!getVisibleMediaForSection.additional.length
!getVisibleMediaForSection.additional?.length
"
class="row justify-center"
>
Expand Down
Loading
Loading