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

Authoring react spellcheckers #4649

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
11 changes: 2 additions & 9 deletions scripts/apps/authoring-react/fields/editor3/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -57,8 +54,6 @@ interface IState {
ready: boolean;

autocompleteSuggestions: Array<string>;

spellcheckerEnabled: boolean;
}

export class Editor extends React.PureComponent<IProps, IState> {
Expand All @@ -71,7 +66,6 @@ export class Editor extends React.PureComponent<IProps, IState> {
this.state = {
ready: false,
autocompleteSuggestions: [],
spellcheckerEnabled: false,
};

this.eventListenersToRemoveBeforeUnmounting = [];
Expand All @@ -95,13 +89,12 @@ export class Editor extends React.PureComponent<IProps, IState> {

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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ interface IState {
actions: Array<IAuthoringAction> | 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<IProps, IState> {
constructor(props: IProps) {
super(props);
Expand Down Expand Up @@ -61,17 +67,26 @@ export class AuthoringActionsMenu extends React.PureComponent<IProps, IState> {
<div>
<Menu items={menuItems}>
{(toggle) => (
<MoreActionsButton
aria-label={gettext('Actions menu')}
<div
ref={(el) => {
// open immediately on mount

if (el != null) {
setTimeout(() => {
el.click();
});
const button = el.querySelector('button');

if (button != null) {
setTimeout(() => {
button.click();
});
}
}
}}
onClick={toggle}
/>
>
<MoreActionsButton
aria-label={gettext('Actions menu')}
onClick={toggle}
/>
</div>
)}
</Menu>
</div>
Expand Down
17 changes: 8 additions & 9 deletions scripts/core/editor3/components/HighlightsPopup.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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<HTMLDivElement>;
highlightsManager: any;
}

/**
* @ngdoc react
* @name HighlightsPopup
Expand All @@ -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<any, any> {
export class HighlightsPopup extends React.Component<IProps> {
static propTypes: any;
static defaultProps: any;
static contextType = ReactContextForEditor3;
Expand Down Expand Up @@ -251,10 +257,3 @@ export class HighlightsPopup extends React.Component<any, any> {
return null;
}
}

HighlightsPopup.propTypes = {
editorState: PropTypes.instanceOf(EditorState),
editorNode: PropTypes.object,
highlightsManager: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired,
};
3 changes: 1 addition & 2 deletions scripts/core/editor3/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@ export function getInitialSpellcheckerData(spellcheck, language: string): IEdito
language: language,
enabled:
!spellcheckerDisabledInConfig &&
spellcheck &&
spellcheck.isAutoSpellchecker,
spellcheck != null,
inProgress: false,
warningsByBlock: {},
};
Expand Down
19 changes: 19 additions & 0 deletions scripts/core/spellcheck/README.md
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 2 additions & 2 deletions scripts/core/spellcheck/spellcheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 0 additions & 1 deletion scripts/core/superdesk-api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2227,7 +2227,6 @@ declare module 'superdesk-api' {

export interface IPropsActionButton {
'aria-label': string;
ref?(event): void;
onClick(event: React.MouseEvent): void;
}

Expand Down
2 changes: 0 additions & 2 deletions scripts/core/ui/components/MoreActionsButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as React from 'react';

interface IProps {
'aria-label': string;
ref?(event): void;
onClick(event: React.MouseEvent): void;
}

Expand All @@ -12,7 +11,6 @@ export class MoreActionsButton extends React.PureComponent<IProps> {
<button
className="sd-navbtn"
aria-label={this.props['aria-label']}
ref={this.props.ref}
onClick={this.props.onClick}
>
<i className="icon-dots-vertical" />
Expand Down
Loading