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 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..f80283a7 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" }, @@ -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]] 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", 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 })