Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions config/locales/js-en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,13 @@ en:
title: "Share work package"
table:
configure_button: "Configure work package table"
grid_actions_header: "Actions"
grid_baseline_header: "Comparison status"
relations_button: "Relations in %{column} for %{work_package}"
sort_criterion_ascending: "%{column} ascending"
sort_criterion_descending: "%{column} descending"
sorted_by: "Sorted by %{criteria}."
sorted_manually: "Sorted manually."
summary: "Table with rows of work package and columns of work package attributes."
text_inline_edit: "Most cells of this table are buttons that activate inline-editing functionality of that attribute."
text_select_hint: "Select boxes should be opened with 'ALT' and arrow keys."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import { QueryColumn } from 'core-app/features/work-packages/components/wp-query
import { octiconElement } from 'core-app/shared/helpers/op-icon-builder';
import { SchemaCacheService } from 'core-app/core/schemas/schema-cache.service';
import { I18nService } from 'core-app/core/i18n/i18n.service';
import { WorkPackageTableConfiguration } from 'core-app/features/work-packages/components/wp-table/wp-table-configuration';
import { keyboardNavigationEnabled } from 'core-app/features/work-packages/components/wp-fast-table/handlers/state/keyboard/roving-tabindex';
import { getBaselineState } from '../../../wp-baseline/baseline-helpers';
import {
opArrowInIconData,
Expand All @@ -44,6 +46,24 @@ import {

export const baselineCellName = 'op-table-baseline--column-cell';

const baselineChanges = {
added: {
icon: opArrowInIconData,
className: 'op-table-baseline--icon-added',
label: 'js.work_packages.baseline.addition_label',
},
removed: {
icon: replyIconData,
className: 'op-table-baseline--icon-removed',
label: 'js.work_packages.baseline.removal_label',
},
updated: {
icon: opTriangleDeltaIconData,
className: 'op-table-baseline--icon-changed',
label: 'js.work_packages.baseline.modification_label',
},
};

export class BaselineColumnBuilder {
@LazyInject() states:States;

Expand All @@ -53,7 +73,10 @@ export class BaselineColumnBuilder {

@LazyInject() I18n:I18nService;

constructor(public readonly injector:Injector) {
constructor(
public readonly injector:Injector,
private readonly configuration:WorkPackageTableConfiguration,
) {
}

public build(workPackage:WorkPackageResource, column:QueryColumn) {
Expand All @@ -68,40 +91,22 @@ export class BaselineColumnBuilder {
return td;
}

// Check if added
const icon = this.changeIcon(workPackage);
if (icon) {
td.appendChild(icon);
}

return td;
}

private changeIcon(
workPackage:WorkPackageResource,
):HTMLElement|null {
const state = getBaselineState(workPackage, this.schemaCache);
if (state === 'added') {
return octiconElement(opArrowInIconData,
'small',
'op-table-baseline--icon-added',
this.I18n.t('js.work_packages.baseline.addition_label'));
if (!state) {
return td;
}

if (state === 'removed') {
return octiconElement(replyIconData,
'small',
'op-table-baseline--icon-removed',
this.I18n.t('js.work_packages.baseline.removal_label'));
}
const { icon, className, label } = baselineChanges[state];
const text = this.I18n.t(label);
td.appendChild(octiconElement(icon, 'small', className, text));

if (state === 'updated') {
return octiconElement(opTriangleDeltaIconData,
'small',
'op-table-baseline--icon-changed',
this.I18n.t('js.work_packages.baseline.modification_label'));
if (keyboardNavigationEnabled(this.configuration)) {
const status = document.createElement('span');
status.classList.add('sr-only');
status.textContent = text;
td.appendChild(status);
}

return null;
return td;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { WorkPackageViewColumnsService } from 'core-app/features/work-packages/r
import { WorkPackageNotificationService } from 'core-app/features/work-packages/services/notifications/work-package-notification.service';
import { LazyInject } from 'core-app/shared/helpers/angular/lazy-inject.decorator';
import { QueryOrder } from 'core-app/core/apiv3/endpoints/queries/apiv3-query-order';
import { keyboardNavigationEnabled } from 'core-app/features/work-packages/components/wp-fast-table/handlers/state/keyboard/roving-tabindex';
import { PrimaryRenderPass } from '../primary-render-pass';

export class DragDropHandleRenderPass {
Expand Down Expand Up @@ -75,6 +76,9 @@ public readonly injector:Injector,
const handle = this.dragDropHandleBuilder.build(latestWorkPackage, positions[workPackage.id!]);

if (handle && element) {
if (keyboardNavigationEnabled(this.table.configuration)) {
handle.setAttribute('role', 'gridcell');
}
element.replaceChild(handle, element.firstElementChild!);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,33 +52,43 @@ export class GroupSumsBuilder extends SingleRowBuilder {
const tr:HTMLTableRowElement = document.createElement('tr');
tr.classList.add('wp-table--sums-row', 'wp-table--row', groupedRowClassName(group.index));

this.renderColumns(group.sums, tr);
this.renderColumns(group.sums, tr, group.index);

return tr;
}

public renderColumns(sums:GroupObject['sums'], tr:HTMLTableRowElement) {
public renderColumns(sums:GroupObject['sums'], tr:HTMLTableRowElement, labelSuffix:number|'total') {
const { configuration } = this.workPackageTable;
const labelId = keyboardNavigationEnabled(configuration) ? `${this.workPackageTable.domId}-sum-${labelSuffix}` : null;

this.augmentedColumns.forEach((column, i:number) => {
const td = document.createElement('td');
const { configuration } = this.workPackageTable;
if (keyboardNavigationEnabled(configuration) && isNavigableColumn(column, configuration)) {
const navigable = keyboardNavigationEnabled(configuration) && isNavigableColumn(column, configuration);
if (navigable) {
td.classList.add(navigableCellClassName);
}
const div = this.renderContent(sums, column.id, this.sumsSchema[column.id] as IFieldSchema);

if (navigable && labelId && div.hasChildNodes()) {
td.setAttribute('aria-describedby', labelId);
}

if (i === 0) {
this.appendFirstLabel(div);
this.appendFirstLabel(div, labelId);
}

td.appendChild(div);
tr.append(td);
});
}

private appendFirstLabel(div:HTMLElement) {
private appendFirstLabel(div:HTMLElement, id:string|null) {
const span = document.createElement('span');
span.textContent = `${this.text.sum}`;
span.title = `${this.text.sum}`;
if (id) {
span.id = id;
}
div.prepend(span);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,36 @@ describe('Grouped table collapse', () => {
expect(harness.table.ledger.keyAt(0)).toBe(firstKey);
});
});

describe('Grouped table collapse on a keyboard-enabled table', () => {
let harness:TableHarness;

afterEach(() => harness.destroy());

it('projects the collapse onto row expansion and hidden state', async () => {
harness = buildTable({
workPackages: [
{ id: '1', attributes: { status: newStatus } },
{ id: '2', attributes: { status: inProgressStatus } },
],
groups: [
{ value: 'New', href: newStatus.href, count: 1 },
{ value: 'In progress', href: inProgressStatus.href, count: 1 },
],
configuration: { keyboardNavigationEnabled: true },
});
await harness.render();
expect(harness.groupHeader(0)).toHaveAttribute('aria-expanded', 'true');

fireEvent.click(harness.groupHeader(0).querySelector('.expander')!);

await waitFor(() => expect(harness.groupHeader(0)).toHaveAttribute('aria-expanded', 'false'));
expect(harness.row('1')).toHaveAttribute('aria-hidden', 'true');
expect(harness.row('2')).not.toHaveAttribute('aria-hidden');

fireEvent.click(harness.groupHeader(0).querySelector('.expander')!);

await waitFor(() => expect(harness.groupHeader(0)).toHaveAttribute('aria-expanded', 'true'));
expect(harness.row('1')).not.toHaveAttribute('aria-hidden');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
import {
GroupHeaderBuilder,
} from 'core-app/features/work-packages/components/wp-fast-table/builders/modes/grouped/group-header-builder';
import { buildTable, TableHarness } from 'core-app/features/work-packages/components/wp-fast-table/testing/table-harness';
import { RenderedOccurrenceLedger } from 'core-app/features/work-packages/components/wp-fast-table/rendered-occurrence-ledger';

class TestGroupedRenderPass extends GroupedRenderPass {
Expand Down Expand Up @@ -116,6 +117,27 @@ describe('GroupedRenderPass', () => {
});
});

describe('GroupedRenderPass levels', () => {
let harness:TableHarness;

afterEach(() => harness.destroy());

it('assigns semantic levels to every occurrence', async () => {
const status = { href: '/api/v3/statuses/1' };
harness = buildTable({
workPackages: [{ id: '1', attributes: { status } }],
groups: [{ value: 'New', href: status.href, count: 1, sums: { storyPoints: 13 } }],
});

await harness.render();

const { ledger } = harness.table;
expect(ledger.byKey('group:0:header')!.level).toBe(1);
expect(ledger.byKey('wp:1')!.level).toBe(2);
expect(ledger.byKey('group:0:sums')!.level).toBe(2);
});
});

function buildRenderPass(rows:WorkPackageTableRow[], groups:GroupObject[]):TestGroupedRenderPass {
const pass = new TestGroupedRenderPass(
buildInjector(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export class GroupedRenderPass extends PlainRenderPass {
const [tr, _] = this.rowBuilder.buildEmpty(row.object);

tr.classList.add(...additionalClasses);
this.appendRow(row.object, tr, additionalClasses, hidden);
this.appendRow(row.object, tr, additionalClasses, hidden, 2);
}

/**
Expand All @@ -184,7 +184,7 @@ export class GroupedRenderPass extends PlainRenderPass {
const { additionalClasses, hidden } = this.groupRowState(group);

rowElement.classList.add(...additionalClasses);
this.appendNonWorkPackageRow(groupOccurrenceKey(group.index, 'sums'), rowElement, groupClass, additionalClasses, hidden, group.identifier);
this.appendNonWorkPackageRow(groupOccurrenceKey(group.index, 'sums'), rowElement, groupClass, additionalClasses, hidden, group.identifier, 2);
}

private groupRowState(group:GroupObject):{ additionalClasses:string[], hidden:boolean } {
Expand Down
Loading
Loading