Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

Authors widget: localize the untracked-authors label; center the chart empty state.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
justify-content: center;
height: 100%;
width: 100%;
margin-inline: auto;
gap: var(--wpds-dimension-gap-lg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,13 @@ describe( 'buildTopAuthorsData', () => {
const bob = result.find( author => author.label === 'Bob' );
expect( bob ).toMatchObject( { previousValue: 0, delta: 100 } );
} );

it( 'localizes the untracked-authors sentinel produced by the sanitizer', () => {
const result = buildTopAuthorsData(
makeReport( [ { label: 'Untracked Authors', views: 5 } ] ),
undefined
);

expect( result[ 0 ].label ).toBe( 'Untracked authors' );
} );
} );
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,26 @@ import {
import { __ } from '@wordpress/i18n';
import type { StatsNormalizedReport, StatsTopAuthorsItem } from '@jetpack-premium-analytics/data';

// The Stats sanitizer substitutes this untranslated sentinel for authors with
// no name (see `sanitizeStatsTopAuthorsResponse`), so match it here to surface a
// localized label.
const UNTRACKED_AUTHORS_SENTINEL = 'Untracked Authors';

/**
* Resolve a display label for an author, falling back to a translated
* "Untracked authors" label when the API provides none.
* Resolve a display label for an author, translating the untracked-authors
* sentinel (and any empty label) into a localized string.
*
* @param author - The top-authors item.
* @return The author's display label.
*/
function getAuthorLabel( author: StatsTopAuthorsItem ) {
return typeof author.label === 'string' && author.label
? author.label
: __( 'Untracked authors', 'jetpack-premium-analytics' );
const label = typeof author.label === 'string' ? author.label : '';

if ( ! label || label === UNTRACKED_AUTHORS_SENTINEL ) {
return __( 'Untracked authors', 'jetpack-premium-analytics' );
}

return label;
}

/**
Expand Down
18 changes: 11 additions & 7 deletions projects/packages/premium-analytics/widgets/authors/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
useWidgetRootContext,
type LeaderboardChartData,
type LegendLabels,
type ReportParamsFieldAttributes,
} from '@jetpack-premium-analytics/widgets-toolkit';
import { __ } from '@wordpress/i18n';
import { postAuthor } from '@wordpress/icons';
Expand All @@ -19,16 +20,17 @@ import { useMemo } from 'react';
* Internal dependencies
*/
import { buildTopAuthorsData } from './build-top-authors-data';
import type { AuthorsAttributes } from './widget';
import type { WidgetRenderProps } from '@wordpress/widget-primitives';
import type { ComponentProps } from 'react';

const DEFAULT_MAX = 7;

type AuthorsAttributes = NonNullable< ComponentProps< typeof WidgetRoot >[ 'attributes' ] > & {
max?: string | number;
};
// Report params are usually URL-driven (WidgetRoot's fallback), but callers may
// also pass them via `attributes`. Compose the render-only shape to cover both.
type AuthorsRenderAttributes = AuthorsAttributes & Partial< ReportParamsFieldAttributes >;

type AuthorsRenderProps = WidgetRenderProps< AuthorsAttributes > & {
type AuthorsRenderProps = WidgetRenderProps< AuthorsRenderAttributes > & {
setError?: ComponentProps< typeof WidgetRoot >[ 'setError' ];
};

Expand Down Expand Up @@ -169,9 +171,11 @@ function AuthorsReport( { max }: { max: number } ) {
/**
* Authors widget render entry point.
*
* WidgetRoot provides the analytics query client, chart theme, and the report
* params consumed by the inner leaderboard — resolved from the dashboard date
* range via context, the same way the other Stats widgets read them.
* Passes host `attributes` into `WidgetRoot`, which resolves the report params:
* the dashboard leaves `reportParams` out of `attributes`, so it falls back to
* the date-range URL search params the picker writes to; Storybook injects
* `attributes.reportParams` directly. The widget's own `max` is forwarded to
* the inner component.
*
* @param props - Render props.
* @param props.attributes - Widget attributes.
Expand Down
14 changes: 13 additions & 1 deletion projects/packages/premium-analytics/widgets/authors/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
import { __ } from '@wordpress/i18n';
import { postAuthor } from '@wordpress/icons';

/**
* Configurable attributes for the Authors widget. Mirrors the `attributes`
* declared on the widget definition below; the host passes the selected values
* through to `render.tsx`.
*/
export type AuthorsAttributes = {
/**
* Maximum number of authors to display.
*/
max?: number;
};

/**
* Widget type definition.
*/
Expand All @@ -20,7 +32,7 @@ export default {
],
example: {
attributes: {
max: '7',
max: 7,
},
},
};
Loading