From 9342c82f3a47e1322fa5fa46cc3d4aa9773cd43b Mon Sep 17 00:00:00 2001 From: Maximus Date: Sun, 14 Dec 2025 23:06:35 -0500 Subject: [PATCH 1/9] fix: Correctly load schedule items for 'Sequence' entities using `loadSequenceScheduleItems`. --- src/components/pages/ProductionSchedule.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/pages/ProductionSchedule.vue b/src/components/pages/ProductionSchedule.vue index d27545647..c5ab7e458 100644 --- a/src/components/pages/ProductionSchedule.vue +++ b/src/components/pages/ProductionSchedule.vue @@ -965,7 +965,9 @@ export default { : this.loadSequenceScheduleItems : taskTypeElement.for_entity === 'Shot' ? this.loadSequenceScheduleItems - : this.loadAssetTypeScheduleItems + : taskTypeElement.for_entity === 'Sequence' + ? this.loadSequenceScheduleItems + : this.loadAssetTypeScheduleItems const parameters = { production: this.currentProduction, taskType: this.taskTypeMap.get(taskTypeElement.task_type_id) From 7c2884dff6119456b4deb7ec0471744946a4bd59 Mon Sep 17 00:00:00 2001 From: Maximus Date: Mon, 15 Dec 2025 02:15:27 -0500 Subject: [PATCH 2/9] feat: Add entity type filtering to the Production Schedule page with UI, logic, and URL synchronization. --- src/components/pages/ProductionSchedule.vue | 128 +++++++++++++++++++- src/locales/en.js | 5 +- 2 files changed, 130 insertions(+), 3 deletions(-) diff --git a/src/components/pages/ProductionSchedule.vue b/src/components/pages/ProductionSchedule.vue index c5ab7e458..2b5f56c41 100644 --- a/src/components/pages/ProductionSchedule.vue +++ b/src/components/pages/ProductionSchedule.vue @@ -65,6 +65,35 @@ /> +
+ +
+ +
+ +
+
+
{ + if (item.for_entity) { + entityTypes.add(item.for_entity) + } + }) + return Array.from(entityTypes).sort().map(type => ({ + label: type, + value: type + })) + }, + + filteredScheduleItems() { + if (this.entityTypeFilter.length === 0) { + return this.scheduleItems + } + return this.scheduleItems.filter(item => + this.entityTypeFilter.includes(item.for_entity) + ) + }, + + entityFilterLabel() { + if (this.entityTypeFilter.length === 0) { + return this.$t('schedule.all_entities') + } + if (this.entityTypeFilter.length === this.availableEntityTypes.length) { + return this.$t('schedule.all_entities') + } + return `${this.entityTypeFilter.length} ${this.$t('schedule.selected')}` } }, @@ -769,7 +832,7 @@ export default { 'updateTask' ]), - updateRoute({ mode, version, zoom }) { + updateRoute({ mode, version, zoom, entityTypes }) { const query = { ...this.$route.query } if (mode !== undefined) { @@ -781,6 +844,9 @@ export default { if (zoom !== undefined) { query.zoom = String(zoom) } + if (entityTypes !== undefined) { + query.entityTypes = entityTypes || undefined + } if (JSON.stringify(query) !== JSON.stringify(this.$route.query)) { this.$router.push({ query }) @@ -888,6 +954,13 @@ export default { this.zoomLevel = this.zoomOptions.map(o => o.value).includes(zoom) ? zoom : DEFAULT_ZOOM + + const entityTypes = this.$route.query.entityTypes + if (entityTypes) { + this.entityTypeFilter = entityTypes.split(',').filter(type => + this.availableEntityTypes.some(et => et.value === type) + ) + } }, convertScheduleItems(taskTypeElement, scheduleItems) { @@ -1853,6 +1926,13 @@ export default { this.refreshSchedule() }, + onEntityFilterChanged() { + const entityTypes = this.entityTypeFilter.length > 0 + ? this.entityTypeFilter.join(',') + : undefined + this.updateRoute({ entityTypes }) + }, + refreshSchedule() { this.scheduleItems.forEach(item => { if (!item.expanded) { @@ -2429,5 +2509,49 @@ export default { width: 90px; } } + + .entity-filter-dropdown { + position: relative; + + .entity-filter-menu { + position: absolute; + top: 100%; + left: 0; + background: white; + border: 1px solid #ddd; + border-radius: 4px; + box-shadow: 0 2px 8px rgba(0,0,0,0.1); + padding: 0.5em; + z-index: 100; + min-width: 150px; + margin-top: 0.25em; + + .entity-filter-item { + display: block; + padding: 0.25em 0.5em; + cursor: pointer; + user-select: none; + + &:hover { + background: #f5f5f5; + } + + input { + margin-right: 0.5em; + } + } + } + } +} + +.dark { + .entity-filter-menu { + background: $dark-grey-light; + border-color: $dark-grey; + + .entity-filter-item:hover { + background: $dark-grey; + } + } } diff --git a/src/locales/en.js b/src/locales/en.js index fab34dbc9..9cfbaea48 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -1584,7 +1584,10 @@ export default { new: 'new schedule', name: 'version name', locked: 'locked version' - } + }, + entities: 'Entities', + all_entities: 'All', + selected: 'selected' }, team_schedule: { From 1ee0c78864052756ce325e83a5e564b40700d41a Mon Sep 17 00:00:00 2001 From: Maximus Date: Mon, 15 Dec 2025 02:32:19 -0500 Subject: [PATCH 3/9] refactor: Update Production Schedule entity filter dropdown to a select-like UI with refactored selection logic. --- src/components/pages/ProductionSchedule.vue | 172 +++++++++++++++----- 1 file changed, 127 insertions(+), 45 deletions(-) diff --git a/src/components/pages/ProductionSchedule.vue b/src/components/pages/ProductionSchedule.vue index 2b5f56c41..d9eac9327 100644 --- a/src/components/pages/ProductionSchedule.vue +++ b/src/components/pages/ProductionSchedule.vue @@ -32,6 +32,35 @@ :options="modeOptions" @update:model-value="onModeChanged" /> +
+ +
+ +
+ +
+
+
-
- -
- -
- -
-
-
+
-1) { + // Remove from filter + this.entityTypeFilter.splice(index, 1) + } else { + // Add to filter + this.entityTypeFilter.push(entityType) + } + + // If all types are now selected, clear the filter (show all) + if (this.entityTypeFilter.length === this.availableEntityTypes.length) { + this.entityTypeFilter = [] + } + + this.onEntityFilterChanged() + }, + refreshSchedule() { this.scheduleItems.forEach(item => { if (!item.expanded) { @@ -2512,32 +2539,72 @@ export default { .entity-filter-dropdown { position: relative; + display: inline-block; + + .select-input { + appearance: none; + background-color: transparent; + border: 1px solid $green; + border-radius: 4px; + color: inherit; + cursor: pointer; + font-size: 1rem; + height: 3em; + padding: 0 2.5em 0 1em; + min-width: 120px; + + &:hover { + border-color: $light-green; + } + + &:focus { + outline: none; + border-color: $light-green; + } + } + + &::after { + content: ''; + position: absolute; + right: 1em; + top: 50%; + transform: translateY(-50%); + width: 0; + height: 0; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid $green; + pointer-events: none; + } .entity-filter-menu { position: absolute; - top: 100%; + top: calc(100% + 4px); left: 0; background: white; - border: 1px solid #ddd; + border: 1px solid $light-grey; border-radius: 4px; - box-shadow: 0 2px 8px rgba(0,0,0,0.1); - padding: 0.5em; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + padding: 0.25em 0; z-index: 100; - min-width: 150px; - margin-top: 0.25em; + min-width: 100%; .entity-filter-item { - display: block; - padding: 0.25em 0.5em; + display: flex; + align-items: center; + padding: 0.4em 1em; cursor: pointer; user-select: none; + white-space: nowrap; + transition: background-color 0.1s ease; &:hover { - background: #f5f5f5; + background: $light-grey-light; } - input { - margin-right: 0.5em; + input[type="checkbox"] { + margin: 0 0.75em 0 0; + cursor: pointer; } } } @@ -2545,12 +2612,27 @@ export default { } .dark { - .entity-filter-menu { - background: $dark-grey-light; - border-color: $dark-grey; + .entity-filter-dropdown { + .select-input { + border-color: $green; + + &:hover, + &:focus { + border-color: $light-green; + } + } - .entity-filter-item:hover { - background: $dark-grey; + &::after { + border-top-color: $green; + } + + .entity-filter-menu { + background: $dark-grey-light; + border-color: $dark-grey; + + .entity-filter-item:hover { + background: $dark-grey; + } } } } From a2390b6183cd9ffb4306425abd004f06ba9a20f6 Mon Sep 17 00:00:00 2001 From: Maximus Date: Mon, 15 Dec 2025 02:44:44 -0500 Subject: [PATCH 4/9] refactor: update entity filter UI and styling for consistency with navigation menu --- src/components/pages/ProductionSchedule.vue | 160 ++++++++------------ 1 file changed, 62 insertions(+), 98 deletions(-) diff --git a/src/components/pages/ProductionSchedule.vue b/src/components/pages/ProductionSchedule.vue index d9eac9327..3e9cae291 100644 --- a/src/components/pages/ProductionSchedule.vue +++ b/src/components/pages/ProductionSchedule.vue @@ -36,28 +36,30 @@ -
- -
- + + + +

+
+
+ + {{ entityType.label }}
@@ -2537,101 +2539,63 @@ export default { } } - .entity-filter-dropdown { + // Entity filter styling to match navigation menu + .entity-filter-select { position: relative; - display: inline-block; + } + + .entity-filter-menu { + position: absolute; + top: calc(100% + 8px); + left: 0; + background: $dark-grey-light; + border: 1px solid $dark-grey; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + padding: 0.5em 0; + z-index: 200; + min-width: 180px; - .select-input { - appearance: none; - background-color: transparent; - border: 1px solid $green; - border-radius: 4px; - color: inherit; + .entity-filter-item { + display: flex; + align-items: center; + gap: 0.75em; + padding: 0.75em 1.25em; cursor: pointer; + user-select: none; + color: white; font-size: 1rem; - height: 3em; - padding: 0 2.5em 0 1em; - min-width: 120px; + transition: background-color 0.15s ease; &:hover { - border-color: $light-green; + background: rgba(255, 255, 255, 0.1); } - &:focus { - outline: none; - border-color: $light-green; + input[type="checkbox"] { + width: 16px; + height: 16px; + cursor: pointer; + flex-shrink: 0; } - } - - &::after { - content: ''; - position: absolute; - right: 1em; - top: 50%; - transform: translateY(-50%); - width: 0; - height: 0; - border-left: 5px solid transparent; - border-right: 5px solid transparent; - border-top: 5px solid $green; - pointer-events: none; - } - - .entity-filter-menu { - position: absolute; - top: calc(100% + 4px); - left: 0; - background: white; - border: 1px solid $light-grey; - border-radius: 4px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); - padding: 0.25em 0; - z-index: 100; - min-width: 100%; - .entity-filter-item { - display: flex; - align-items: center; - padding: 0.4em 1em; - cursor: pointer; - user-select: none; - white-space: nowrap; - transition: background-color 0.1s ease; - - &:hover { - background: $light-grey-light; - } - - input[type="checkbox"] { - margin: 0 0.75em 0 0; - cursor: pointer; - } + span { + flex: 1; } } } } +// Dark mode overrides .dark { - .entity-filter-dropdown { - .select-input { - border-color: $green; - - &:hover, - &:focus { - border-color: $light-green; - } - } + .entity-filter-menu { + background: $dark-grey-light; + border-color: $dark-grey; - &::after { - border-top-color: $green; - } - - .entity-filter-menu { - background: $dark-grey-light; - border-color: $dark-grey; + .entity-filter-item { + color: white; - .entity-filter-item:hover { - background: $dark-grey; + &:hover { + background: rgba(255, 255, 255, 0.1); } } } From fccee5419ac10ce5510df334123c89761f331a42 Mon Sep 17 00:00:00 2001 From: Maximus Date: Mon, 15 Dec 2025 02:56:41 -0500 Subject: [PATCH 5/9] feat: Refactor entity type filter UI to a combobox structure and add a `ComboboxMask` component. --- src/components/pages/ProductionSchedule.vue | 54 ++++++++++++--------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/components/pages/ProductionSchedule.vue b/src/components/pages/ProductionSchedule.vue index 3e9cae291..ac00423ce 100644 --- a/src/components/pages/ProductionSchedule.vue +++ b/src/components/pages/ProductionSchedule.vue @@ -36,32 +36,41 @@ -

- - - -

-
+
+
+
+ {{ entityFilterLabel }} +
+ +
- - {{ entityType.label }} +
+ + {{ entityType.label }} +
+