From 2bbc6e87867feaf22544dfbf11f80f333588d0c0 Mon Sep 17 00:00:00 2001 From: ALA-NSIDE Date: Mon, 9 Nov 2026 13:26:44 +0100 Subject: [PATCH 1/4] feat: allow configurable gantt shaded dates --- .../GanttChartComponent.mdx | 8 +++++ .../GanttChartComponent.spec.ts | 34 +++++++++++++++++++ .../GanttChartComponent.stories.ts | 1 + .../GanttChartComponent.vue | 4 +++ .../GanttChartComponent/GanttChartRowGrid.vue | 28 ++++++++++++++- 5 files changed, 74 insertions(+), 1 deletion(-) diff --git a/vue/src/components/GanttChartComponent/GanttChartComponent.mdx b/vue/src/components/GanttChartComponent/GanttChartComponent.mdx index 8fdc86a5..99cfe13c 100644 --- a/vue/src/components/GanttChartComponent/GanttChartComponent.mdx +++ b/vue/src/components/GanttChartComponent/GanttChartComponent.mdx @@ -348,3 +348,11 @@ Set an activity's `linkOffsetYPx` to adjust both incoming and outgoing dependenc endpoints from the chart's calculated activity center. Positive values move down, negative values move up, and omission means zero adjustment. This changes arrow geometry only; it does not change bars, row heights, or transitions. + +### Additional shaded dates + +Pass `shadedDates` as date-only strings (`YYYY-MM-DD`) to shade selected day columns using the weekend colour. Dates are matched to the chart's displayed local calendar dates. Duplicates and dates outside the visible range have no effect. This layer is non-interactive and remains behind activities, selection and dependency links. It works independently of `showWeekendShading`. Like weekend shading, it is disabled in weekly view because a weekly column contains multiple dates. The component does not calculate public holidays; the application supplies its calendar. + +```vue + +``` diff --git a/vue/src/components/GanttChartComponent/GanttChartComponent.spec.ts b/vue/src/components/GanttChartComponent/GanttChartComponent.spec.ts index 6e929d59..af58e257 100644 --- a/vue/src/components/GanttChartComponent/GanttChartComponent.spec.ts +++ b/vue/src/components/GanttChartComponent/GanttChartComponent.spec.ts @@ -84,6 +84,40 @@ const baseRows: GanttChartRowData[] = [ ] describe('GanttChartComponent', () => { + it('keeps weekend shading enabled by default and forwards optional shaded dates', async () => { + const wrapper = mount(GanttChartComponent, { + props: { + startDate: new Date(2026, 0, 1), + endDate: new Date(2026, 0, 8), + rows: baseRows, + }, + }) + const row = wrapper.findComponent(GanttChartRowGrid) + expect(row.props('showWeekendShading')).toBe(true) + expect(row.props('shadedDates')).toEqual([]) + await wrapper.setProps({ shadedDates: ['2026-01-02'] }) + expect(row.props('shadedDates')).toEqual(['2026-01-02']) + }) + + it('shades only supplied visible day columns without intercepting interactions', async () => { + const wrapper = mount(GanttChartRowGrid, { + props: { + dateRange: [new Date(2026, 0, 1), new Date(2026, 0, 2), new Date(2026, 0, 3)], + columnWidthPx: 40, + activities: [], + showWeekendShading: false, + shadedDates: ['2026-01-02', '2026-01-02', '2027-01-01'], + }, + }) + expect(wrapper.get('.box-border').attributes('style')).toContain('rgb(248, 250, 252) 40px') + expect(wrapper.get('.box-border').attributes('style')).toContain('rgb(248, 250, 252) 80px') + expect(wrapper.findAll('.cursor-pointer')).toHaveLength(0) + await wrapper.setProps({ shadedDates: [] }) + expect(wrapper.get('.box-border').attributes('style')).not.toContain('rgb(248, 250, 252)') + await wrapper.setProps({ shadedDates: ['2026-01-02'], viewMode: 'week' }) + expect(wrapper.get('.box-border').attributes('style')).not.toContain('rgb(248, 250, 252)') + }) + it('applies explicit link offsets without changing row geometry', () => { const rows = ref( baseRows.map((row, index) => ({ diff --git a/vue/src/components/GanttChartComponent/GanttChartComponent.stories.ts b/vue/src/components/GanttChartComponent/GanttChartComponent.stories.ts index aba62d1c..c2a35abe 100644 --- a/vue/src/components/GanttChartComponent/GanttChartComponent.stories.ts +++ b/vue/src/components/GanttChartComponent/GanttChartComponent.stories.ts @@ -134,6 +134,7 @@ const meta: Meta = { headerLabel: 'gantt_chart.header', viewMode: 'day', showWeekendShading: true, + shadedDates: ['2026-01-01'], stackMiniActivities: true, leftHeaderWidthPx: 320, baseRowHeightPx: 30, diff --git a/vue/src/components/GanttChartComponent/GanttChartComponent.vue b/vue/src/components/GanttChartComponent/GanttChartComponent.vue index 87c96d78..458f2fd0 100644 --- a/vue/src/components/GanttChartComponent/GanttChartComponent.vue +++ b/vue/src/components/GanttChartComponent/GanttChartComponent.vue @@ -109,6 +109,7 @@ :row-height-px="rowHeights[item.index]" :view-mode="viewMode" :show-weekend-shading="showWeekendShading" + :shaded-dates="shadedDates" :stack-mini-activities="stackMiniActivities" :activity-tooltip="activityTooltip" :activity-hover="handleActivityHover" @@ -214,6 +215,8 @@ interface GanttChartComponentProps { viewMode?: 'day' | 'week' /** Enables weekend background shading in day view. */ showWeekendShading?: boolean + /** Additional date-only (YYYY-MM-DD) columns shaded like weekends in day view. */ + shadedDates?: string[] /** Stacks overlapping mini activities into separate vertical lanes. */ stackMiniActivities?: boolean /** Returns PrimeVue tooltip text for an activity when no popover slot is used. */ @@ -271,6 +274,7 @@ const { headerLabel = 'gantt_chart.header', viewMode: viewModeProp = 'day', showWeekendShading = true, + shadedDates = [], stackMiniActivities = true, activityTooltip = undefined, activityClick = undefined, diff --git a/vue/src/components/GanttChartComponent/GanttChartRowGrid.vue b/vue/src/components/GanttChartComponent/GanttChartRowGrid.vue index 823bea06..4fd4d3a5 100644 --- a/vue/src/components/GanttChartComponent/GanttChartRowGrid.vue +++ b/vue/src/components/GanttChartComponent/GanttChartRowGrid.vue @@ -164,6 +164,7 @@ export interface GanttChartRowGridProps { activityColorClass?: string stripeColor?: string showWeekendShading?: boolean + shadedDates?: string[] stackMiniActivities?: boolean rowHeightPx?: number rowIndex?: number @@ -205,6 +206,7 @@ const { activityColorClass = 'bg-emerald-400/80', stripeColor = 'rgba(59, 130, 246, 0.2)', showWeekendShading = true, + shadedDates = [], stackMiniActivities = true, rowHeightPx = undefined, rowIndex = undefined, @@ -300,7 +302,24 @@ const weekPattern = computed(() => { return `linear-gradient(90deg, ${stops.join(', ')})` }) -// Grid background style with optional weekend shading. +// Additional dates are an irregular, non-repeating layer below grid lines and activities. +const shadedDatePattern = computed(() => { + if (isWeekView.value || shadedDates.length === 0) return '' + const dates = new Set(shadedDates) + const stops = dateRange.flatMap((date, index) => + dates.has(DateTime.fromJSDate(date).toISODate() ?? '') + ? [ + `transparent ${index * columnWidthPx}px`, + `rgb(248 250 252) ${index * columnWidthPx}px`, + `rgb(248 250 252) ${(index + 1) * columnWidthPx}px`, + `transparent ${(index + 1) * columnWidthPx}px`, + ] + : [] + ) + return stops.length ? `linear-gradient(90deg, ${stops.join(', ')})` : '' +}) + +// Grid background style with optional weekend and additional date shading. const gridStyle = computed(() => { const firstDate = dateRange[0] const weekStart = firstDate @@ -328,6 +347,13 @@ const gridStyle = computed(() => { baseStyle.backgroundRepeat = 'repeat-x, repeat-x' } + if (shadedDatePattern.value) { + baseStyle.backgroundImage += `, ${shadedDatePattern.value}` + baseStyle.backgroundSize += `, ${lineWidth.value} 100%` + baseStyle.backgroundPosition = `${baseStyle.backgroundPosition ?? '0 0'}, 0 0` + baseStyle.backgroundRepeat += ', no-repeat' + } + return baseStyle }) From 6f2b0cb5924fdf9c7e648bcbbf9150a1dd8daec6 Mon Sep 17 00:00:00 2001 From: ALA-NSIDE Date: Mon, 9 Nov 2026 13:31:06 +0100 Subject: [PATCH 2/4] ci: pin Playwright jobs to compatible Ubuntu image --- .github/workflows/vue.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/vue.yml b/.github/workflows/vue.yml index cc376183..cbd7cd6e 100644 --- a/.github/workflows/vue.yml +++ b/.github/workflows/vue.yml @@ -63,7 +63,7 @@ jobs: unit-tests: name: Unit Tests - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v7 - uses: ./.github/actions/setup-node @@ -71,7 +71,7 @@ jobs: uses: actions/cache@v6 with: path: ~/.cache/ms-playwright - key: playwright-${{ runner.os }}-${{ hashFiles('vue/package-lock.json') }} + key: playwright-ubuntu-24.04-${{ runner.arch }}-${{ hashFiles('vue/package-lock.json') }} - run: npm ci - name: Install Playwright (browsers and deps) run: node node_modules/playwright/cli.js install --with-deps @@ -85,7 +85,7 @@ jobs: e2e-tests: name: E2E Tests - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v7 - uses: ./.github/actions/setup-node @@ -93,7 +93,7 @@ jobs: uses: actions/cache@v6 with: path: ~/.cache/ms-playwright - key: playwright-${{ runner.os }}-${{ hashFiles('vue/package-lock.json') }} + key: playwright-ubuntu-24.04-${{ runner.arch }}-${{ hashFiles('vue/package-lock.json') }} - run: npm ci - name: Install Playwright (browsers and deps) run: node node_modules/playwright/cli.js install --with-deps From 40b25f9ccc0a8fcb2c62cd444a42c7eb6e37d22e Mon Sep 17 00:00:00 2001 From: ALA-NSIDE Date: Mon, 9 Nov 2026 13:36:18 +0100 Subject: [PATCH 3/4] chore: bump monorepo version to 0.7.2 --- bff/pyproject.toml | 2 +- bff/uv.lock | 2 +- django/nside_wefa/__init__.py | 2 +- django/pyproject.toml | 2 +- django/uv.lock | 2 +- vue/package-lock.json | 4 ++-- vue/package.json | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bff/pyproject.toml b/bff/pyproject.toml index c61acf4c..e6516ac4 100644 --- a/bff/pyproject.toml +++ b/bff/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "backend-for-frontend" -version = "0.7.1" +version = "0.7.2" description = "Flask backend-for-frontend" requires-python = ">=3.12,<3.13" dependencies = [ diff --git a/bff/uv.lock b/bff/uv.lock index c03123f8..bdde6c06 100644 --- a/bff/uv.lock +++ b/bff/uv.lock @@ -34,7 +34,7 @@ wheels = [ [[package]] name = "backend-for-frontend" -version = "0.7.1" +version = "0.7.2" source = { virtual = "." } dependencies = [ { name = "authlib" }, diff --git a/django/nside_wefa/__init__.py b/django/nside_wefa/__init__.py index 5bdd3e63..ba54717a 100644 --- a/django/nside_wefa/__init__.py +++ b/django/nside_wefa/__init__.py @@ -5,4 +5,4 @@ with a focus on Legal Consent compliance, data protection, authentication. """ -__version__ = "0.7.1" +__version__ = "0.7.2" diff --git a/django/pyproject.toml b/django/pyproject.toml index 1a8ee09e..0b2a7016 100644 --- a/django/pyproject.toml +++ b/django/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "nside-wefa" -version = "0.7.1" +version = "0.7.2" description = "Django library with Legal Consent compliance utilities and reusable apps" readme = "README.md" requires-python = ">=3.12" diff --git a/django/uv.lock b/django/uv.lock index b26a1a29..05e2e7ce 100644 --- a/django/uv.lock +++ b/django/uv.lock @@ -667,7 +667,7 @@ wheels = [ [[package]] name = "nside-wefa" -version = "0.7.1" +version = "0.7.2" source = { editable = "." } dependencies = [ { name = "django" }, diff --git a/vue/package-lock.json b/vue/package-lock.json index 25664b83..ab3e1cda 100644 --- a/vue/package-lock.json +++ b/vue/package-lock.json @@ -1,12 +1,12 @@ { "name": "@nside/wefa", - "version": "0.7.1", + "version": "0.7.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@nside/wefa", - "version": "0.7.1", + "version": "0.7.2", "license": "Apache-2.0", "dependencies": { "@primeuix/themes": "^2.0.3", diff --git a/vue/package.json b/vue/package.json index 6ab6a459..f986b1e8 100644 --- a/vue/package.json +++ b/vue/package.json @@ -1,6 +1,6 @@ { "name": "@nside/wefa", - "version": "0.7.1", + "version": "0.7.2", "type": "module", "main": "./dist/lib.umd.cjs", "module": "./dist/lib.js", From e22aa2cca4fce5a657a28e77162c4d00b83f6556 Mon Sep 17 00:00:00 2001 From: ALA-NSIDE Date: Mon, 9 Nov 2026 13:40:35 +0100 Subject: [PATCH 4/4] fix: update vulnerable joserfc dependency --- bff/uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bff/uv.lock b/bff/uv.lock index bdde6c06..f80283a7 100644 --- a/bff/uv.lock +++ b/bff/uv.lock @@ -322,14 +322,14 @@ wheels = [ [[package]] name = "joserfc" -version = "1.7.2" +version = "1.7.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/26/abe1ad855eb334b5ebc9c6495d4798e12bee70e5e8e815d54570710b8312/joserfc-1.7.2.tar.gz", hash = "sha256:537ffb8888b2df039cb5b6d017d7cff6f09d521ce65d89cc9b8ab752b1cff947", size = 233183, upload-time = "2026-06-29T09:03:10.868Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/db/ec5b5fe07a7bda62cd2c2d619daf160eb7442b979c7cd61bbe0262108de9/joserfc-1.7.6.tar.gz", hash = "sha256:fb1cf6d2977318bef976c2ed2ef2167cc5f8ade8fc96f034e38f7abd656907c4", size = 236091, upload-time = "2026-10-18T23:12:18.43Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/80/d1b30336582cced4dce0dae776508a6011723e32f907bc7a702c0b25890a/joserfc-1.7.2-py3-none-any.whl", hash = "sha256:ddd818c0ca9b4f17bbc2d72cb3966e6ded7502be089316c62c3cc64ae86132b5", size = 70426, upload-time = "2026-06-29T09:03:09.393Z" }, + { url = "https://files.pythonhosted.org/packages/98/40/63886ba742c6fd9e6dd222e20b8d54012fbc933465350c7747c4ed5b31e4/joserfc-1.7.6-py3-none-any.whl", hash = "sha256:e2d72e3fa937ed8ddd42ad8c1cc337a43e7ffd02efa572a2aa15e2764a05b506", size = 71588, upload-time = "2026-10-18T23:12:17.085Z" }, ] [[package]]