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: support partial i18n in dashboard #8660

Merged
merged 1 commit into from
Feb 11, 2025
Merged
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
10 changes: 1 addition & 9 deletions packages/dashboard/src/vaadin-dashboard-section.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,7 @@ class DashboardSection extends DashboardItemMixin(ElementMixin(ThemableMixin(Pol
__i18n: {
type: Object,
value: () => {
const i18n = getDefaultI18n();
return {
selectSection: i18n.selectSection,
remove: i18n.remove,
move: i18n.move,
moveApply: i18n.moveApply,
moveForward: i18n.moveForward,
moveBackward: i18n.moveBackward,
};
return getDefaultI18n();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filtering for properties that the component uses doesn't bring much benefit, and is overridden when the dashboard element sets the i18n object on its children.

},
},

Expand Down
4 changes: 1 addition & 3 deletions packages/dashboard/src/vaadin-dashboard-widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,7 @@ class DashboardWidget extends DashboardItemMixin(ElementMixin(ThemableMixin(Poly
__i18n: {
type: Object,
value: () => {
const i18n = getDefaultI18n();
delete i18n.selectSection;
return i18n;
return getDefaultI18n();
},
},

Expand Down
14 changes: 7 additions & 7 deletions packages/dashboard/src/vaadin-dashboard.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import './vaadin-dashboard-widget.js';
import './vaadin-dashboard-section.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import type { I18nMixin, PartialI18n } from '@vaadin/component-base/src/i18n-mixin.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin';
import { DashboardLayoutMixin } from './vaadin-dashboard-layout-mixin.js';

Expand Down Expand Up @@ -133,7 +134,7 @@ export interface DashboardCustomEventMap<TItem extends DashboardItem> {

export type DashboardEventMap<TItem extends DashboardItem> = DashboardCustomEventMap<TItem> & HTMLElementEventMap;

export interface DashboardI18n {
export type DashboardI18n = PartialI18n<{
selectWidget: string;
selectSection: string;
remove: string;
Expand All @@ -147,7 +148,7 @@ export interface DashboardI18n {
moveApply: string;
moveForward: string;
moveBackward: string;
}
}>;

/**
* A responsive, grid-based dashboard layout component
Expand Down Expand Up @@ -217,7 +218,7 @@ export interface DashboardI18n {
* @fires {CustomEvent} dashboard-item-resize-mode-changed - Fired when an item resize mode changed
*/
declare class Dashboard<TItem extends DashboardItem = DashboardItem> extends DashboardLayoutMixin(
ElementMixin(ThemableMixin(HTMLElement)),
I18nMixin({} as DashboardI18n, ElementMixin(ThemableMixin(HTMLElement))),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the way the Dashboard class is defined, applying the I18nMixin required some creativity.

) {
/**
* An array containing the items of the dashboard
Expand All @@ -243,10 +244,9 @@ declare class Dashboard<TItem extends DashboardItem = DashboardItem> extends Das
editable: boolean;

/**
* The object used to localize this component.
*
* To change the default localization, replace the entire
* `i18n` object with a custom one.
* The object used to localize this component. To change the default
* localization, replace this with an object that provides all properties, or
* just the individual properties you want to change.
*
* The object has the following structure and default values:
* ```
Expand Down
81 changes: 42 additions & 39 deletions packages/dashboard/src/vaadin-dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import './vaadin-dashboard-section.js';
import { html, LitElement } from 'lit';
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
import { css, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import {
Expand Down Expand Up @@ -100,9 +101,12 @@ import { WidgetResizeController } from './widget-resize-controller.js';
* @extends HTMLElement
* @mixes ElementMixin
* @mixes DashboardLayoutMixin
* @mixes I18nMixin
* @mixes ThemableMixin
*/
class Dashboard extends DashboardLayoutMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
class Dashboard extends DashboardLayoutMixin(
I18nMixin(getDefaultI18n(), ElementMixin(ThemableMixin(PolylitMixin(LitElement)))),
) {
static get is() {
return 'vaadin-dashboard';
}
Expand Down Expand Up @@ -162,40 +166,6 @@ class Dashboard extends DashboardLayoutMixin(ElementMixin(ThemableMixin(PolylitM
type: Boolean,
},

/**
* The object used to localize this component.
*
* To change the default localization, replace the entire
* `i18n` object with a custom one.
*
* The object has the following structure and default values:
* ```
* {
* selectSection: 'Select section for editing',
* selectWidget: 'Select widget for editing',
* remove: 'Remove',
* resize: 'Resize',
* resizeApply: 'Apply',
* resizeShrinkWidth: 'Shrink width',
* resizeGrowWidth: 'Grow width',
* resizeShrinkHeight: 'Shrink height',
* resizeGrowHeight: 'Grow height',
* move: 'Move',
* moveApply: 'Apply',
* moveForward: 'Move Forward',
* moveBackward: 'Move Backward',
* }
* ```
*/
i18n: {
type: Object,
value: () => {
return {
...getDefaultI18n(),
};
},
},

/** @private */
__childCount: {
type: Number,
Expand All @@ -205,7 +175,40 @@ class Dashboard extends DashboardLayoutMixin(ElementMixin(ThemableMixin(PolylitM
}

static get observers() {
return ['__itemsOrRendererChanged(items, renderer, editable, i18n)'];
return ['__itemsOrRendererChanged(items, renderer, editable, __effectiveI18n)'];
}

/**
* The object used to localize this component. To change the default
* localization, replace this with an object that provides all properties, or
* just the individual properties you want to change.
*
* The object has the following structure and default values:
* ```
* {
* selectSection: 'Select section for editing',
* selectWidget: 'Select widget for editing',
* remove: 'Remove',
* resize: 'Resize',
* resizeApply: 'Apply',
* resizeShrinkWidth: 'Shrink width',
* resizeGrowWidth: 'Grow width',
* resizeShrinkHeight: 'Shrink height',
* resizeGrowHeight: 'Grow height',
* move: 'Move',
* moveApply: 'Apply',
* moveForward: 'Move Forward',
* moveBackward: 'Move Backward',
* }
* ```
* @return {!DashboardI18n}
*/
get i18n() {
return super.i18n;
}

set i18n(value) {
super.i18n = value;
}

constructor() {
Expand Down Expand Up @@ -257,7 +260,7 @@ class Dashboard extends DashboardLayoutMixin(ElementMixin(ThemableMixin(PolylitM
SYNCHRONIZED_ATTRIBUTES.forEach((attr) => {
wrapper.firstElementChild.toggleAttribute(attr, !!wrapper[attr]);
});
wrapper.firstElementChild.__i18n = this.i18n;
wrapper.firstElementChild.__i18n = this.__effectiveI18n;
}
});
}
Expand Down Expand Up @@ -300,7 +303,7 @@ class Dashboard extends DashboardLayoutMixin(ElementMixin(ThemableMixin(PolylitM
}

SYNCHRONIZED_ATTRIBUTES.forEach((attr) => section.toggleAttribute(attr, !!wrapper[attr]));
section.__i18n = this.i18n;
section.__i18n = this.__effectiveI18n;

// Render the subitems
section.__childCount = item.items.length;
Expand Down Expand Up @@ -424,7 +427,7 @@ class Dashboard extends DashboardLayoutMixin(ElementMixin(ThemableMixin(PolylitM
wrapper.dragging = this.__widgetReorderController.draggedItem === item;
wrapper['first-child'] = item === getItemsArrayOfItem(item, this.items)[0];
wrapper['last-child'] = item === getItemsArrayOfItem(item, this.items).slice(-1)[0];
wrapper.i18n = this.i18n;
wrapper.i18n = this.__effectiveI18n;
}

/** @private */
Expand Down
12 changes: 4 additions & 8 deletions packages/dashboard/test/dashboard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import '../vaadin-dashboard.js';
import type { CustomElementType } from '@vaadin/component-base/src/define.js';
import type { DashboardSection } from '../src/vaadin-dashboard-section.js';
import type { DashboardWidget } from '../src/vaadin-dashboard-widget.js';
import type { Dashboard, DashboardItem, DashboardSectionItem } from '../vaadin-dashboard.js';
import type { Dashboard, DashboardI18n, DashboardItem, DashboardSectionItem } from '../vaadin-dashboard.js';
import {
expectLayout,
getColumnWidths,
Expand All @@ -25,7 +25,7 @@ import {
type TestDashboardItem = DashboardItem & { id: string; component?: Element | string };

describe('dashboard', () => {
let dashboard: Dashboard<TestDashboardItem>;
let dashboard: Dashboard<TestDashboardItem> & { __effectiveI18n: DashboardI18n };
const columnWidth = 200;

beforeEach(async () => {
Expand Down Expand Up @@ -199,15 +199,14 @@ describe('dashboard', () => {

it('should localize widget', async () => {
dashboard.i18n = {
...dashboard.i18n,
selectWidget: 'foo',
};

await updateComplete(dashboard);

const widget = getElementFromCell(dashboard, 0, 0) as DashboardWidget & { __i18n: { [key: string]: string } };
expect(widget.__i18n.selectWidget).to.equal('foo');
expect(widget.__i18n).to.eql(dashboard.i18n);
expect(widget.__i18n).to.eql(dashboard.__effectiveI18n);
});

it('should localize focused widget', async () => {
Expand All @@ -229,7 +228,6 @@ describe('dashboard', () => {
widget.focus();

dashboard.i18n = {
...dashboard.i18n,
selectWidget: 'foo',
};
await updateComplete(dashboard);
Expand All @@ -249,7 +247,6 @@ describe('dashboard', () => {
await updateComplete(dashboard);

dashboard.i18n = {
...dashboard.i18n,
selectWidget: 'foo',
};
await updateComplete(dashboard);
Expand Down Expand Up @@ -399,7 +396,6 @@ describe('dashboard', () => {
describe('i18n', () => {
it('should localize section', async () => {
dashboard.i18n = {
...dashboard.i18n,
selectSection: 'foo',
};

Expand All @@ -410,7 +406,7 @@ describe('dashboard', () => {
__i18n: { [key: string]: string };
};
expect(section.__i18n.selectSection).to.equal('foo');
expect(section.__i18n).to.eql(dashboard.i18n);
expect(section.__i18n).to.eql(dashboard.__effectiveI18n);
});
});
});
Expand Down
29 changes: 16 additions & 13 deletions packages/dashboard/test/typings/dashboard.types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
import type { I18nMixinClass } from '@vaadin/component-base/src/i18n-mixin.js';
import type { DashboardLayoutMixinClass } from '../../src/vaadin-dashboard-layout-mixin.js';
import type {
Dashboard,
DashboardI18n,
DashboardItem,
DashboardItemMovedEvent,
DashboardItemMoveModeChangedEvent,
Expand Down Expand Up @@ -32,25 +34,26 @@ assertType<{ items: DashboardItem[]; title?: string }>(
);

assertType<ElementMixinClass>(genericDashboard);
assertType<I18nMixinClass<DashboardI18n>>(genericDashboard);
assertType<DashboardLayoutMixinClass>(genericDashboard);
assertType<Array<DashboardItem | DashboardSectionItem<DashboardItem>> | null | undefined>(genericDashboard.items);
assertType<boolean>(genericDashboard.editable);
assertType<boolean>(genericDashboard.denseLayout);

assertType<{
selectWidget: string;
selectSection: string;
remove: string;
resize: string;
move: string;
resizeApply: string;
resizeShrinkWidth: string;
resizeGrowWidth: string;
resizeShrinkHeight: string;
resizeGrowHeight: string;
moveApply: string;
moveForward: string;
moveBackward: string;
selectWidget?: string;
selectSection?: string;
remove?: string;
resize?: string;
move?: string;
resizeApply?: string;
resizeShrinkWidth?: string;
resizeGrowWidth?: string;
resizeShrinkHeight?: string;
resizeGrowHeight?: string;
moveApply?: string;
moveForward?: string;
moveBackward?: string;
}>(genericDashboard.i18n);

const narrowedDashboard = document.createElement('vaadin-dashboard') as unknown as Dashboard<TestDashboardItem>;
Expand Down