Skip to content

Commit

Permalink
Widget state persistance (#4574)
Browse files Browse the repository at this point in the history
  • Loading branch information
thecalcc authored Jul 31, 2024
1 parent 777d1af commit 49ef9c2
Show file tree
Hide file tree
Showing 36 changed files with 401 additions and 186 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
"sass-loader": "6.0.6",
"shortid": "2.2.8",
"style-loader": "0.20.2",
"superdesk-ui-framework": "^3.1.15",
"superdesk-ui-framework": "^3.1.17",
"ts-loader": "3.5.0",
"typescript": "4.9.5",
"uuid": "8.3.1",
Expand Down Expand Up @@ -163,7 +163,7 @@
"test": "npm run lint && npm run unit && node tasks/verify-client-api-changes.js",
"debug-unit-tests": "karma start --reporters=progress --browsers=Chrome",
"unit": "karma start --single-run",
"lint": "tsc -p scripts --noEmit && eslint --parser=@typescript-eslint/parser --ext .js --ext .jsx --ext .ts --ext .tsx scripts e2e/client tasks",
"lint": "tsc -p scripts --noEmit && eslint --quiet --parser=@typescript-eslint/parser --ext .js --ext .jsx --ext .ts --ext .tsx scripts e2e/client tasks",
"lint-fix": "eslint --fix --parser=@typescript-eslint/parser --ext .js --ext .jsx --ext .ts --ext .tsx scripts e2e/client tasks",
"server": "grunt server",
"dev": "npm run server"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
/* eslint-disable react/no-multi-comp */
import React from 'react';
import {IArticleSideWidget, IComment, IExtensionActivationResult, IRestApiResponse} from 'superdesk-api';
import {IArticleSideWidget, IArticleSideWidgetComponentType, IComment, IRestApiResponse} from 'superdesk-api';
import {gettext} from 'core/utils';
import CommentsWidget from '../../generic-widgets/comments/CommentsWidget';
import {httpRequestJsonLocal} from 'core/helpers/network';
// Can't call `gettext` in the top level
const getLabel = () => gettext('Comments');

type IProps = React.ComponentProps<
IExtensionActivationResult['contributions']['authoringSideWidgets'][0]['component']
>;

class Component extends React.PureComponent<IProps> {
class Component extends React.PureComponent<IArticleSideWidgetComponentType> {
render() {
return (
<CommentsWidget
initialState={this.props.initialState}
entityId={this.props.article._id}
readOnly={this.props.readOnly}
contentProfile={this.props.contentProfile}
Expand Down
12 changes: 5 additions & 7 deletions scripts/apps/authoring-react/article-widgets/demo-widget.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {IArticleSideWidget, IArticle, IExtensionActivationResult} from 'superdesk-api';
import {IArticleSideWidget, IArticleSideWidgetComponentType} from 'superdesk-api';
import {Button} from 'superdesk-ui-framework';
import {sdApi} from 'api';
import {gettext} from 'core/utils';
Expand All @@ -8,17 +8,15 @@ import {AuthoringWidgetLayout} from 'apps/dashboard/widget-layout';

// Can't call `gettext` in the top level
const getLabel = () => gettext('Demo widget');
const DEMO_WIDGET_ID = 'demo-widget';

type IProps = React.ComponentProps<
IExtensionActivationResult['contributions']['authoringSideWidgets'][0]['component']
>;

class DemoWidget extends React.PureComponent<IProps> {
class DemoWidget extends React.PureComponent<IArticleSideWidgetComponentType> {
render() {
return (
<AuthoringWidgetLayout
header={(
<AuthoringWidgetHeading
widgetId={DEMO_WIDGET_ID}
widgetName={getLabel()}
editMode={false}
/>
Expand Down Expand Up @@ -47,7 +45,7 @@ class DemoWidget extends React.PureComponent<IProps> {

export function getDemoWidget() {
const metadataWidget: IArticleSideWidget = {
_id: 'demo-widget',
_id: DEMO_WIDGET_ID,
label: getLabel(),
order: 2,
icon: 'info',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {IArticleSideWidget, IArticle, IExtensionActivationResult} from 'superdesk-api';
import {IArticleSideWidget, IArticleSideWidgetComponentType} from 'superdesk-api';
import {gettext} from 'core/utils';
import {AuthoringWidgetHeading} from 'apps/dashboard/widget-heading';
import {AuthoringWidgetLayout} from 'apps/dashboard/widget-layout';
Expand All @@ -10,10 +10,7 @@ import {throttle} from 'lodash';

// Can't call `gettext` in the top level
const getLabel = () => gettext('Find and Replace');

type IProps = React.ComponentProps<
IExtensionActivationResult['contributions']['authoringSideWidgets'][0]['component']
>;
const FIND_AND_REPLACE_WIDGET_ID = 'find-and-replace-widget';

interface IState {
findValue: string;
Expand All @@ -26,13 +23,13 @@ interface IState {
*/
export const editorId = 'body_html';

class FindAndReplaceWidget extends React.PureComponent<IProps, IState> {
class FindAndReplaceWidget extends React.PureComponent<IArticleSideWidgetComponentType, IState> {
private scheduleHighlightingOfMatches: () => void;

constructor(props: IProps) {
constructor(props: IArticleSideWidgetComponentType) {
super(props);

this.state = {
this.state = this.props.initialState ?? {
findValue: '',
replaceValue: '',
caseSensitive: false,
Expand Down Expand Up @@ -69,6 +66,7 @@ class FindAndReplaceWidget extends React.PureComponent<IProps, IState> {
<AuthoringWidgetLayout
header={(
<AuthoringWidgetHeading
widgetId={FIND_AND_REPLACE_WIDGET_ID}
widgetName={getLabel()}
editMode={false}
/>
Expand Down Expand Up @@ -165,7 +163,7 @@ class FindAndReplaceWidget extends React.PureComponent<IProps, IState> {

export function getFindAndReplaceWidget() {
const metadataWidget: IArticleSideWidget = {
_id: 'find-and-replace-widget',
_id: FIND_AND_REPLACE_WIDGET_ID,
label: getLabel(),
order: 1,
icon: 'find-replace',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
/* eslint-disable react/no-multi-comp */

import React from 'react';
import {IArticleSideWidget, IExtensionActivationResult, IArticle} from 'superdesk-api';
import {IArticleSideWidget, IExtensionActivationResult, IArticle, IArticleSideWidgetComponentType} from 'superdesk-api';
import {gettext} from 'core/utils';
import {InlineCommentsWidget} from '../generic-widgets/inline-comments';

// Can't call `gettext` in the top level
const getLabel = () => gettext('Inline comments');

type IProps = React.ComponentProps<
IExtensionActivationResult['contributions']['authoringSideWidgets'][0]['component']
>;

class InlineCommentsWidgetWrapper extends React.PureComponent<IProps> {
class InlineCommentsWidgetWrapper extends React.PureComponent<IArticleSideWidgetComponentType> {
render() {
return (
<InlineCommentsWidget<IArticle>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {Fragment} from 'react';
import {IArticleSideWidget, IExtensionActivationResult, IVocabularyItem} from 'superdesk-api';
import {IArticleSideWidget, IArticleSideWidgetComponentType} from 'superdesk-api';
import {gettext} from 'core/utils';
import {AuthoringWidgetHeading} from 'apps/dashboard/widget-heading';
import {AuthoringWidgetLayout} from 'apps/dashboard/widget-layout';
Expand All @@ -17,17 +17,14 @@ import {AnnotationsPreview} from './AnnotationsPreview';

// Can't call `gettext` in the top level
const getLabel = () => gettext('Metadata');

type IProps = React.ComponentProps<
IExtensionActivationResult['contributions']['authoringSideWidgets'][0]['component']
>;
const METADATA_WIDGET_ID = 'metadata-widget';

interface IState {
languages: Array<ILanguage>;
}

class MetadataWidget extends React.PureComponent<IProps, IState> {
constructor(props: IProps) {
class MetadataWidget extends React.PureComponent<IArticleSideWidgetComponentType, IState> {
constructor(props: IArticleSideWidgetComponentType) {
super(props);

this.state = {
Expand Down Expand Up @@ -99,6 +96,7 @@ class MetadataWidget extends React.PureComponent<IProps, IState> {
<AuthoringWidgetLayout
header={(
<AuthoringWidgetHeading
widgetId={METADATA_WIDGET_ID}
widgetName={getLabel()}
editMode={false}
/>
Expand Down Expand Up @@ -148,7 +146,7 @@ class MetadataWidget extends React.PureComponent<IProps, IState> {
label={gettext('Usage terms').toUpperCase()}
inlineLabel
type="text"
value={usageterms}
value={usageterms ?? ''}
onChange={(value) => {
onItemChange({
...article,
Expand Down Expand Up @@ -465,7 +463,7 @@ class MetadataWidget extends React.PureComponent<IProps, IState> {

export function getMetadataWidget() {
const metadataWidget: IArticleSideWidget = {
_id: 'metadata-widget',
_id: METADATA_WIDGET_ID,
label: getLabel(),
order: 1,
icon: 'info',
Expand Down
14 changes: 6 additions & 8 deletions scripts/apps/authoring-react/article-widgets/suggestions.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable react/no-multi-comp */

import React from 'react';
import {IArticleSideWidget, IExtensionActivationResult, IUser, IEditor3ValueOperational} from 'superdesk-api';
import {IArticleSideWidget, IUser, IEditor3ValueOperational, IArticleSideWidgetComponentType} from 'superdesk-api';
import {gettext} from 'core/utils';
import {AuthoringWidgetHeading} from 'apps/dashboard/widget-heading';
import {AuthoringWidgetLayout} from 'apps/dashboard/widget-layout';
Expand All @@ -16,10 +16,7 @@ import {getLocalizedTypeText} from 'apps/authoring/track-changes/suggestions';

// Can't call `gettext` in the top level
const getLabel = () => gettext('Resolved suggestions');

type IProps = React.ComponentProps<
IExtensionActivationResult['contributions']['authoringSideWidgets'][0]['component']
>;
const SUGGESTIONS_WIDGET_ID = 'editor3-suggestions-widget';

interface ISuggestion {
resolutionInfo: {
Expand Down Expand Up @@ -139,8 +136,8 @@ class Suggestion extends React.PureComponent<{suggestion: ISuggestion}> {
}
}

class SuggestionsWidget extends React.PureComponent<IProps> {
constructor(props: IProps) {
class SuggestionsWidget extends React.PureComponent<IArticleSideWidgetComponentType> {
constructor(props: IArticleSideWidgetComponentType) {
super(props);

this.getEditor3Fields = this.getEditor3Fields.bind(this);
Expand Down Expand Up @@ -217,6 +214,7 @@ class SuggestionsWidget extends React.PureComponent<IProps> {
<AuthoringWidgetLayout
header={(
<AuthoringWidgetHeading
widgetId={SUGGESTIONS_WIDGET_ID}
widgetName={getLabel()}
editMode={false}
/>
Expand All @@ -230,7 +228,7 @@ class SuggestionsWidget extends React.PureComponent<IProps> {

export function getSuggestionsWidget() {
const metadataWidget: IArticleSideWidget = {
_id: 'editor3-suggestions-widget',
_id: SUGGESTIONS_WIDGET_ID,
label: getLabel(),
order: 3,
icon: 'suggestion',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface IProps {
item: IArticle;
wrapperTemplate: React.ComponentType<{children: Array<JSX.Element>}>;
translationTemplate: React.ComponentType<{translation: IArticle, getTranslatedFromLanguage: () => string}>;
initialState?: IState;
}

interface IState {
Expand All @@ -14,7 +15,20 @@ interface IState {
}

export class TranslationsBody extends React.PureComponent<IProps, IState> {
constructor(props: IProps) {
super(props);

this.state = this.props.initialState ?? {
translations: null,
translationsLookup: {},
};
}

componentDidMount() {
if (this.props.initialState != null) {
return;
}

const {item} = this.props;

ng.get('TranslationService').getTranslations(item)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import {RelativeDate} from 'core/datetime/relativeDate';
import {state as State} from 'apps/search/components/fields/state';
import {IArticle, IArticleSideWidget, IExtensionActivationResult} from 'superdesk-api';
import {IArticleSideWidget, IArticleSideWidgetComponentType} from 'superdesk-api';
import {gettext} from 'core/utils';
import {openArticle} from 'core/get-superdesk-api-implementation';
import {AuthoringWidgetLayout} from 'apps/dashboard/widget-layout';
Expand All @@ -12,23 +12,22 @@ import {Label} from 'superdesk-ui-framework';
import {TranslationsBody} from './TranslationsBody';

const getLabel = () => gettext('Translations');
const TRANSLATIONS_WIDGET_ID = 'translation-widget';

type IProps = React.ComponentProps<
IExtensionActivationResult['contributions']['authoringSideWidgets'][0]['component']
>;

class Translations extends React.Component<IProps> {
class Translations extends React.Component<IArticleSideWidgetComponentType> {
render() {
return (
<AuthoringWidgetLayout
header={(
<AuthoringWidgetHeading
widgetId={TRANSLATIONS_WIDGET_ID}
widgetName={getLabel()}
editMode={false}
/>
)}
body={(
<TranslationsBody
initialState={this.props.initialState}
item={this.props.article}
wrapperTemplate={
({children}) =>
Expand Down Expand Up @@ -90,7 +89,7 @@ class Translations extends React.Component<IProps> {

export function getTranslationsWidget() {
const metadataWidget: IArticleSideWidget = {
_id: 'translation-widget',
_id: TRANSLATIONS_WIDGET_ID,
label: getLabel(),
order: 2,
icon: 'web',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import {
IArticleSideWidget,
IExtensionActivationResult,
IArticleSideWidgetComponentType,
} from 'superdesk-api';
import {gettext} from 'core/utils';
import {AuthoringWidgetHeading} from 'apps/dashboard/widget-heading';
Expand All @@ -14,28 +14,24 @@ import {VersionsTab} from './versions-tab';
// Can't call `gettext` in the top level
const getLabel = () => gettext('Versions and item history');

type IProps = React.ComponentProps<
IExtensionActivationResult['contributions']['authoringSideWidgets'][0]['component']
>;

interface IState {
selectedTab: 'versions' | 'history';
}
const VERSIONS_AND_HISTORY_WIDGET_ID = 'versions-and-item-history';

class VersionsAndItemHistoryWidget extends React.PureComponent<IProps, IState> {
constructor(props: IProps) {
class VersionsAndItemHistoryWidget extends React.PureComponent<IArticleSideWidgetComponentType, IState> {
constructor(props: IArticleSideWidgetComponentType) {
super(props);

this.state = {
selectedTab: 'versions',
};
this.state = this.props.initialState ?? {selectedTab: 'versions'};
}

render() {
return (
<AuthoringWidgetLayout
header={(
<AuthoringWidgetHeading
widgetId={VERSIONS_AND_HISTORY_WIDGET_ID}
widgetName={getLabel()}
editMode={false}
customContent={(
Expand Down Expand Up @@ -73,7 +69,7 @@ class VersionsAndItemHistoryWidget extends React.PureComponent<IProps, IState> {

export function getVersionsAndItemHistoryWidget() {
const widget: IArticleSideWidget = {
_id: 'versions-and-item-history',
_id: VERSIONS_AND_HISTORY_WIDGET_ID,
label: getLabel(),
order: 4,
icon: 'history',
Expand Down
Loading

0 comments on commit 49ef9c2

Please sign in to comment.