diff --git a/scripts/apps/authoring-react/fields/editor3/editor.tsx b/scripts/apps/authoring-react/fields/editor3/editor.tsx index a71d936ddf..6c7065db2e 100644 --- a/scripts/apps/authoring-react/fields/editor3/editor.tsx +++ b/scripts/apps/authoring-react/fields/editor3/editor.tsx @@ -5,10 +5,7 @@ import { IEditor3Config, } from 'superdesk-api'; import {gettextPlural} from 'core/utils'; -import { - initializeSpellchecker, - getInitialSpellcheckerData, -} from 'core/editor3/store'; +import {getInitialSpellcheckerData} from 'core/editor3/store'; import ng from 'core/services/ng'; import {Provider} from 'react-redux'; import {Editor3} from 'core/editor3/components'; @@ -57,8 +54,6 @@ interface IState { ready: boolean; autocompleteSuggestions: Array; - - spellcheckerEnabled: boolean; } export class Editor extends React.PureComponent { @@ -71,7 +66,6 @@ export class Editor extends React.PureComponent { this.state = { ready: false, autocompleteSuggestions: [], - spellcheckerEnabled: false, }; this.eventListenersToRemoveBeforeUnmounting = []; @@ -95,13 +89,12 @@ export class Editor extends React.PureComponent { syncPropsWithReduxStore() { const store = this.props.value.store; - const spellcheck = this.state.spellcheckerEnabled ? ng.get('spellcheck') : null; store.dispatch(setExternalOptions({ editorFormat: this.props.config.editorFormat ?? [], singleLine: this.props.config.singleLine ?? false, readOnly: this.props.readOnly || this.props.config.readOnly, - spellchecking: getInitialSpellcheckerData(spellcheck, this.props.language), + spellchecking: getInitialSpellcheckerData(ng.get('spellcheck'), this.props.language), limitConfig: this.getCharacterLimitPreference(), item: { language: this.props.language, // required for annotations to work diff --git a/scripts/apps/authoring-react/subcomponents/authoring-actions-menu.tsx b/scripts/apps/authoring-react/subcomponents/authoring-actions-menu.tsx index 3730505f3e..189f10bdd0 100644 --- a/scripts/apps/authoring-react/subcomponents/authoring-actions-menu.tsx +++ b/scripts/apps/authoring-react/subcomponents/authoring-actions-menu.tsx @@ -14,6 +14,12 @@ interface IState { actions: Array | null; } +/** + * Menu component requires providing actions up-front + * while here we don't want to compute them unless user initiates opening of the menu. + * To work around this, we render a button, when it is clicked we fetch the items + * and replace the button with an actual Menu component. + */ export class AuthoringActionsMenu extends React.PureComponent { constructor(props: IProps) { super(props); @@ -61,10 +67,26 @@ export class AuthoringActionsMenu extends React.PureComponent {
{(toggle) => ( - +
{ + // open immediately on mount + + if (el != null) { + const button = el.querySelector('button'); + + if (button != null) { + setTimeout(() => { + button.click(); + }); + } + } + }} + > + +
)}
diff --git a/scripts/core/editor3/components/HighlightsPopup.tsx b/scripts/core/editor3/components/HighlightsPopup.tsx index c3cf43bf30..ef07efd36a 100644 --- a/scripts/core/editor3/components/HighlightsPopup.tsx +++ b/scripts/core/editor3/components/HighlightsPopup.tsx @@ -1,7 +1,6 @@ import React from 'react'; import {EditorState} from 'draft-js'; import {render, unmountComponentAtNode} from 'react-dom'; -import PropTypes from 'prop-types'; import {Provider} from 'react-redux'; import {List} from 'immutable'; @@ -12,6 +11,13 @@ import {getSuggestionsTypes} from '../highlightsConfig'; import * as Highlights from '../helpers/highlights'; import {ReactContextForEditor3} from '../directive'; +interface IProps { + editorState: EditorState; + onChange(editorState: EditorState): void; + editorNode: React.RefObject; + highlightsManager: any; +} + /** * @ngdoc react * @name HighlightsPopup @@ -21,7 +27,7 @@ import {ReactContextForEditor3} from '../directive'; * also handles positioning the popup relative to the editor's position and hiding * it when a user clicks outside the editor/popup context. */ -export class HighlightsPopup extends React.Component { +export class HighlightsPopup extends React.Component { static propTypes: any; static defaultProps: any; static contextType = ReactContextForEditor3; @@ -251,10 +257,3 @@ export class HighlightsPopup extends React.Component { return null; } } - -HighlightsPopup.propTypes = { - editorState: PropTypes.instanceOf(EditorState), - editorNode: PropTypes.object, - highlightsManager: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, -}; diff --git a/scripts/core/editor3/store/index.ts b/scripts/core/editor3/store/index.ts index 3f3caf3c87..da4f128cd9 100644 --- a/scripts/core/editor3/store/index.ts +++ b/scripts/core/editor3/store/index.ts @@ -155,8 +155,7 @@ export function getInitialSpellcheckerData(spellcheck, language: string): IEdito language: language, enabled: !spellcheckerDisabledInConfig && - spellcheck && - spellcheck.isAutoSpellchecker, + spellcheck != null, inProgress: false, warningsByBlock: {}, }; diff --git a/scripts/core/spellcheck/README.md b/scripts/core/spellcheck/README.md new file mode 100644 index 0000000000..67b4d7438b --- /dev/null +++ b/scripts/core/spellcheck/README.md @@ -0,0 +1,19 @@ +# List of available spellcheckers + +### Dictionary-based + +Fetches language dictionaries once and performs spellchecking synchronously. + +### API based + +API is called to fetch and display spellchecker suggestions. 3rd party spellchecking services can be integrated using this method. + +### Tansa spellchecker integration + +Tansa spellchecker can't be integrated on top of our API-based spellchecker because it requires a custom user interface to handle spellchecker suggestions. It can only be invoked to check the entire text and doesn't support highlighting issues while typing. + +# How is it decided which spellchecker will get used? + +If tansa spellchecker integration is enabled - no other spellchecker will be used. + +Otherwise it depends on article's language. If there is an API based spellchecker configured for that language(`appConfig.spellcheckers`) - it will be used. If API based spellchecker is not available, dictionary based spellchecking will be used - given there's a dictionary for that language. \ No newline at end of file diff --git a/scripts/core/spellcheck/spellcheck.ts b/scripts/core/spellcheck/spellcheck.ts index a31982cb5e..8034fdb2b8 100644 --- a/scripts/core/spellcheck/spellcheck.ts +++ b/scripts/core/spellcheck/spellcheck.ts @@ -3,7 +3,7 @@ import {gettext} from 'core/utils'; import {debounce, once} from 'lodash'; import {getStores, unsetStore} from '../editor3/store'; import {setAbbreviations} from 'core/editor3/actions'; -import {getUserInterfaceLanguage} from 'appConfig'; +import {appConfig, getUserInterfaceLanguage} from 'appConfig'; /** * Spellcheck module @@ -544,7 +544,7 @@ function SpellcheckMenuController($rootScope, editorResolver, spellcheck, notify * check if tansa is activated */ function useTansaProofing() { - return $rootScope.config.features && $rootScope.config.features.useTansaProofing; + return appConfig.features?.useTansaProofing === true; } function dispatchAbbreviation(abbreviation) { diff --git a/scripts/core/superdesk-api.d.ts b/scripts/core/superdesk-api.d.ts index a303c51c82..7ec82a1a8b 100644 --- a/scripts/core/superdesk-api.d.ts +++ b/scripts/core/superdesk-api.d.ts @@ -2246,7 +2246,6 @@ declare module 'superdesk-api' { export interface IPropsActionButton { 'aria-label': string; - ref?(event): void; onClick(event: React.MouseEvent): void; } diff --git a/scripts/core/ui/components/MoreActionsButton.tsx b/scripts/core/ui/components/MoreActionsButton.tsx index 7b58482c6d..aa1bb24890 100644 --- a/scripts/core/ui/components/MoreActionsButton.tsx +++ b/scripts/core/ui/components/MoreActionsButton.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; interface IProps { 'aria-label': string; - ref?(event): void; onClick(event: React.MouseEvent): void; } @@ -12,7 +11,6 @@ export class MoreActionsButton extends React.PureComponent {