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

Post fields: move date fields from edit-site to fields package #66938

Merged
merged 7 commits into from
Nov 13, 2024
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
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/date/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ _Parameters_

- _dateFormat_ `string`: PHP-style formatting string. See php.net/date.
- _dateValue_ `Moment | Date | string | undefined`: Date object or string, parsable by moment.js.
- _timezone_ `string | number | boolean | undefined`: Timezone to output result in or a UTC offset. Defaults to timezone from site. Notice: `boolean` is effectively deprecated, but still supported for backward compatibility reasons.
- _timezone_ `string | number | boolean | undefined=`: Timezone to output result in or a UTC offset. Defaults to timezone from site. Notice: `boolean` is effectively deprecated, but still supported for backward compatibility reasons.

_Returns_

Expand Down
18 changes: 9 additions & 9 deletions packages/date/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -525,15 +525,15 @@ export function gmdate( dateFormat, dateValue = new Date() ) {
* Backward Compatibility Notice: if `timezone` is set to `true`, the function
* behaves like `gmdateI18n`.
*
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {Moment | Date | string | undefined} dateValue Date object or string, parsable by
* moment.js.
* @param {string | number | boolean | undefined} timezone Timezone to output result in or a
* UTC offset. Defaults to timezone from
* site. Notice: `boolean` is effectively
* deprecated, but still supported for
* backward compatibility reasons.
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {Moment | Date | string | undefined} dateValue Date object or string, parsable by
* moment.js.
* @param {string | number | boolean | undefined=} timezone Timezone to output result in or a
* UTC offset. Defaults to timezone from
* site. Notice: `boolean` is effectively
* deprecated, but still supported for
* backward compatibility reasons.
*
* @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC
Expand Down
94 changes: 4 additions & 90 deletions packages/edit-site/src/components/post-fields/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import clsx from 'clsx';
/**
* WordPress dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import { __ } from '@wordpress/i18n';
import {
featuredImageField,
slugField,
Expand All @@ -15,24 +15,14 @@ import {
statusField,
commentStatusField,
titleField,
dateField,
} from '@wordpress/fields';
import {
createInterpolateElement,
useMemo,
useState,
} from '@wordpress/element';
import { dateI18n, getDate, getSettings } from '@wordpress/date';
import { useMemo, useState } from '@wordpress/element';
import { commentAuthorAvatar as authorIcon } from '@wordpress/icons';
import { __experimentalHStack as HStack, Icon } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { useEntityRecords, store as coreStore } from '@wordpress/core-data';

const getFormattedDate = ( dateToDisplay ) =>
dateI18n(
getSettings().formats.datetimeAbbreviated,
getDate( dateToDisplay )
);

function PostAuthorField( { item } ) {
const { text, imageUrl } = useSelect(
( select ) => {
Expand Down Expand Up @@ -99,83 +89,7 @@ function usePostFields() {
},
},
statusField,
{
label: __( 'Date' ),
id: 'date',
type: 'datetime',
render: ( { item } ) => {
const isDraftOrPrivate = [ 'draft', 'private' ].includes(
item.status
);
if ( isDraftOrPrivate ) {
return createInterpolateElement(
sprintf(
/* translators: %s: page creation or modification date. */
__( '<span>Modified: <time>%s</time></span>' ),
getFormattedDate( item.date )
),
{
span: <span />,
time: <time />,
}
);
}

const isScheduled = item.status === 'future';
if ( isScheduled ) {
return createInterpolateElement(
sprintf(
/* translators: %s: page creation date */
__( '<span>Scheduled: <time>%s</time></span>' ),
getFormattedDate( item.date )
),
{
span: <span />,
time: <time />,
}
);
}

const isPublished = item.status === 'publish';
if ( isPublished ) {
return createInterpolateElement(
sprintf(
/* translators: %s: page creation time */
__( '<span>Published: <time>%s</time></span>' ),
getFormattedDate( item.date )
),
{
span: <span />,
time: <time />,
}
);
}

// Pending posts show the modified date if it's newer.
const dateToDisplay =
getDate( item.modified ) > getDate( item.date )
? item.modified
: item.date;

const isPending = item.status === 'pending';
if ( isPending ) {
return createInterpolateElement(
sprintf(
/* translators: %s: page creation or modification date. */
__( '<span>Modified: <time>%s</time></span>' ),
getFormattedDate( dateToDisplay )
),
{
span: <span />,
time: <time />,
}
);
}

// Unknow status.
return <time>{ getFormattedDate( item.date ) }</time>;
},
},
dateField,
slugField,
parentField,
commentStatusField,
Expand Down
4 changes: 4 additions & 0 deletions packages/fields/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ npm install @wordpress/fields --save

Comment status field for BasePost.

### dateField

Date field for BasePost.

### deletePost

Undocumented declaration.
Expand Down
1 change: 1 addition & 0 deletions packages/fields/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@wordpress/core-data": "*",
"@wordpress/data": "*",
"@wordpress/dataviews": "*",
"@wordpress/date": "*",
"@wordpress/element": "*",
"@wordpress/hooks": "*",
"@wordpress/html-entities": "*",
Expand Down
92 changes: 92 additions & 0 deletions packages/fields/src/fields/date/date-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* WordPress dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import { createInterpolateElement } from '@wordpress/element';
import { dateI18n, getDate, getSettings } from '@wordpress/date';

/**
* Internal dependencies
*/
import type { BasePost } from '../../types';

const getFormattedDate = ( dateToDisplay: string | null ) =>
dateI18n(
Copy link
Member Author

Choose a reason for hiding this comment

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

One interesting thing from migrating this to TypeScript is that it forces you to pass the last parameter. Despite what the docs say, there's no default value and cannot be undefined.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this can be solved by slightly changing the type definition of the function and making the argument optional =something rather than something | undefined

Copy link
Member Author

Choose a reason for hiding this comment

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

I pushed 9e44b6f and 012a507

Copy link
Member Author

Choose a reason for hiding this comment

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

Reverted the default parameter and modified the JSDoc instead at 544bf3e

getSettings().formats.datetimeAbbreviated,
getDate( dateToDisplay )
);

const DateView = ( { item }: { item: BasePost } ) => {
const isDraftOrPrivate = [ 'draft', 'private' ].includes(
item.status ?? ''
);
if ( isDraftOrPrivate ) {
return createInterpolateElement(
sprintf(
/* translators: %s: page creation or modification date. */
__( '<span>Modified: <time>%s</time></span>' ),
getFormattedDate( item.date ?? null )
),
{
span: <span />,
time: <time />,
}
);
}

const isScheduled = item.status === 'future';
if ( isScheduled ) {
return createInterpolateElement(
sprintf(
/* translators: %s: page creation date */
__( '<span>Scheduled: <time>%s</time></span>' ),
getFormattedDate( item.date ?? null )
),
{
span: <span />,
time: <time />,
}
);
}

const isPublished = item.status === 'publish';
if ( isPublished ) {
return createInterpolateElement(
sprintf(
/* translators: %s: page creation time */
__( '<span>Published: <time>%s</time></span>' ),
getFormattedDate( item.date ?? null )
),
{
span: <span />,
time: <time />,
}
);
}

// Pending posts show the modified date if it's newer.
const dateToDisplay =
getDate( item.modified ?? null ) > getDate( item.date ?? null )
? item.modified
: item.date;

const isPending = item.status === 'pending';
if ( isPending ) {
return createInterpolateElement(
sprintf(
/* translators: %s: page creation or modification date. */
__( '<span>Modified: <time>%s</time></span>' ),
getFormattedDate( dateToDisplay ?? null )
),
{
span: <span />,
time: <time />,
}
);
}

// Unknow status.
return <time>{ getFormattedDate( item.date ?? null ) }</time>;
};

export default DateView;
23 changes: 23 additions & 0 deletions packages/fields/src/fields/date/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* WordPress dependencies
*/
import type { Field } from '@wordpress/dataviews';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import type { BasePost } from '../../types';
import DateView from './date-view';

const dateField: Field< BasePost > = {
id: 'date',
type: 'datetime',
label: __( 'Date' ),
render: DateView,
};

/**
* Date field for BasePost.
*/
export default dateField;
1 change: 1 addition & 0 deletions packages/fields/src/fields/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { default as parentField } from './parent';
export { default as passwordField } from './password';
export { default as statusField } from './status';
export { default as commentStatusField } from './comment-status';
export { default as dateField } from './date';
4 changes: 3 additions & 1 deletion packages/fields/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
type PostStatus =
| 'published'
| 'publish'
Copy link
Member Author

Choose a reason for hiding this comment

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

This was the wrong value.

| 'draft'
| 'pending'
| 'private'
Expand Down Expand Up @@ -37,6 +37,8 @@ export interface BasePost extends CommonPost {
link?: string;
slug?: string;
permalink_template?: string;
date?: string;
modified?: string;
}

export interface Template extends CommonPost {
Expand Down
19 changes: 10 additions & 9 deletions packages/fields/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,25 @@
},
"references": [
{ "path": "../api-fetch" },
{ "path": "../blob" },
{ "path": "../components" },
{ "path": "../compose" },
{ "path": "../core-data" },
{ "path": "../data" },
{ "path": "../dataviews" },
{ "path": "../date" },
Copy link
Member Author

Choose a reason for hiding this comment

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

Sorted alphabetically, like the package.json, and added date as a reference. A bit obscure to see, but, without this, npm run lint:tsconfig would cause the lint job to fail (see):

npm run lint:tsconfig exited with code 1

{ "path": "../element" },
{ "path": "../hooks" },
{ "path": "../html-entities" },
{ "path": "../i18n" },
{ "path": "../icons" },
{ "path": "../media-utils" },
{ "path": "../notices" },
{ "path": "../primitives" },
{ "path": "../private-apis" },
{ "path": "../warning" },
{ "path": "../router" },
{ "path": "../url" },
{ "path": "../notices" },
{ "path": "../dataviews" },
{ "path": "../blob" },
{ "path": "../core-data" },
{ "path": "../hooks" },
{ "path": "../html-entities" },
{ "path": "../media-utils" },
{ "path": "../router" }
{ "path": "../warning" }
],
"include": [ "src" ]
}
Loading