Skip to content

Commit

Permalink
Merge pull request #130 from ckeditor/i/121
Browse files Browse the repository at this point in the history
Feature: Introduced editor quick actions toolbar (see #38) to log editor data, toggle editor read-only, and destroy editor. Closes #121. Closes #104.
  • Loading branch information
pomek authored Nov 30, 2021
2 parents f533976 + c079a3a commit 9417d93
Show file tree
Hide file tree
Showing 43 changed files with 940 additions and 143 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^2.0.2",
"karma-firefox-launcher": "^1.3.0",
"karma-coveralls": "^2.1.0",
"karma-firefox-launcher": "^1.3.0",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"karma-sinon": "^1.0.5",
Expand All @@ -84,6 +84,7 @@
"react-dom": "^16.8.1",
"react-redux": "^7.2.0",
"react-rnd": "^10.0.0",
"react-svg-loader": "^3.0.3",
"redux": "^4.0.5",
"sinon": "^7.2.3",
"style-loader": "^1.2.1",
Expand Down
1 change: 1 addition & 0 deletions src/assets/img/arrow-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/img/console.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/img/eye.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/img/play.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/img/read-only.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/img/source.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/img/trash.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion src/ckeditorinspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import { createStore } from 'redux';
import { Provider } from 'react-redux';

import { reducer } from './data/reducer';
import { setEditors } from './data/actions';
import {
setEditors,
updateCurrentEditorIsReadOnly
} from './data/actions';
import { updateModelState } from './model/data/actions';
import { updateViewState } from './view/data/actions';
import { updateCommandsState } from './commands/data/actions';
Expand Down Expand Up @@ -214,6 +217,9 @@ export default class CKEditorInspector {
}

store.dispatch( updateViewState() );
},
onReadOnlyChange() {
CKEditorInspector._store.dispatch( updateCurrentEditorIsReadOnly() );
}
} );

Expand All @@ -222,6 +228,7 @@ export default class CKEditorInspector {
CKEditorInspector._store = createStore( reducer, {
editors: CKEditorInspector._editors,
currentEditorName: getFirstEditorName( CKEditorInspector._editors ),
currentEditorGlobals: {},
ui: {
isCollapsed: options.isCollapsed
}
Expand Down
7 changes: 5 additions & 2 deletions src/commands/commandinspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import ObjectInspector from '../components/objectinspector';

import Logger from '../logger';

import ConsoleIcon from '../assets/img/console.svg';
import PlayIcon from '../assets/img/play.svg';

class CommandInspector extends Component {
constructor( props ) {
super( props );
Expand Down Expand Up @@ -47,13 +50,13 @@ class CommandInspector extends Component {
</span>,
<Button
key="exec"
type="exec"
icon={<PlayIcon />}
text="Execute command"
onClick={this.handleCommandExecuteButtonClick}
/>,
<Button
key="log"
type="log"
icon={<ConsoleIcon />}
text="Log in console"
onClick={this.handleCommandLogButtonClick}
/>
Expand Down
46 changes: 30 additions & 16 deletions src/components/button.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,47 @@
* For licensing, see LICENSE.md.
*/

.ck-inspector {
--ck-inspector-icon-size: 19px;
--ck-inspector-button-size: calc( 4px + var(--ck-inspector-icon-size) );
--ck-inspector-color-button: #777;
--ck-inspector-color-button-hover: #222;
--ck-inspector-color-button-on: #0F79E2;
}

.ck-inspector .ck-inspector-button {
width: 16px;
height: 16px;
width: var(--ck-inspector-button-size);
height: var(--ck-inspector-button-size);
border: 0;
text-indent: 100px;
overflow: hidden;
opacity: .8;
margin-left: .7em;
flex: 0 0 auto;
border-radius: 2px;
padding: 2px;
color: var(--ck-inspector-color-button);

&:first-of-type {
margin-left: auto;
&.ck-inspector-button_on,
&.ck-inspector-button_on:hover {
color: var(--ck-inspector-color-button-on);
opacity: 1;
}

&:hover {
opacity: 1;
&.ck-inspector-button_disabled {
opacity: .3;
}

&.ck-inspector-button_log {
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZT0iIzZFNkU2RSIgc3Ryb2tlLXdpZHRoPSIxLjUiPjxwYXRoIGQ9Ik0xLjUgNC4xNjVsNS43IDQuMTItNS43IDMuMTUzTTkuNDQ5IDExLjVoNS42NTUiLz48L2c+PC9zdmc+);
& > span {
display: none;
}

&.ck-inspector-button_exec {
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48Y2lyY2xlIHN0cm9rZT0iIzZFNkU2RSIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSI4IiBjeT0iOCIgcj0iNy4yNSIvPjxwYXRoIGZpbGw9IiM2RTZFNkUiIGQ9Ik02LjA5NCA1LjIzNUwxMS4wNzQgOGwtNC45OCAzLjAxOHoiLz48L2c+PC9zdmc+);
&:hover {
color: var(--ck-inspector-color-button-hover);
}

&.ck-inspector-button_scroll {
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAxNiAxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHRpdGxlPnNlZTwvdGl0bGU+CjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CjxwYXRoIGQ9Im04IDMuNWMtMS44ODM4IDAtMy42MDY5IDAuNjEzNDItNC45MzM5IDEuNDQyOC0xLjUwNTcgMC45NDEwNC0yLjU2NjEgMi4xNjMzLTIuNTY2MSAzLjA1NzJzMS4wNjA0IDIuMTE2MiAyLjU2NjEgMy4wNTcyYzEuMzI3IDAuODI5MzggMy4wNTAxIDEuNDQyOCA0LjkzMzkgMS40NDI4czMuNjA2OS0wLjYxMzQyIDQuOTMzOS0xLjQ0MjhjMS41MDU3LTAuOTQxMDQgMi41NjYxLTIuMTYzMyAyLjU2NjEtMy4wNTcycy0xLjA2MDQtMi4xMTYyLTIuNTY2MS0zLjA1NzJjLTEuMzI3LTAuODI5MzgtMy4wNTAxLTEuNDQyOC00LjkzMzktMS40NDI4eiIgc3Ryb2tlPSIjNkU2RTZFIi8+CjxwYXRoIGQ9Im04IDRjMi4yMDkxIDAgNCAxLjc5MDkgNCA0cy0xLjc5MDkgNC00IDQtNC0xLjc5MDktNC00IDEuNzkwOS00IDQtNHptLTEuNSAxYy0wLjgyODQzIDAtMS41IDAuNjcxNTctMS41IDEuNXMwLjY3MTU3IDEuNSAxLjUgMS41IDEuNS0wLjY3MTU3IDEuNS0xLjUtMC42NzE1Ny0xLjUtMS41LTEuNXoiIGZpbGw9IiM2RTZFNkUiLz4KPC9nPgo8L3N2Zz4K);
& svg {
width: var(--ck-inspector-icon-size);
height: var(--ck-inspector-icon-size);

&, & * {
fill: currentColor;
}
}
}
17 changes: 13 additions & 4 deletions src/components/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,26 @@
*/

import React, { PureComponent } from 'react';

import './button.css';

export default class Button extends PureComponent {
render() {
const classes = [
'ck-inspector-button',
this.props.className || '',
this.props.isOn ? 'ck-inspector-button_on' : '',
this.props.isEnabled === false ? 'ck-inspector-button_disabled' : ''
].filter( className => className ).join( ' ' );

return <button
className={`ck-inspector-button ck-inspector-button_${ this.props.type }`}
className={classes}
type="button"
onClick={this.props.onClick}
title={this.props.text}
onClick={this.props.isEnabled === false ? () => {} : this.props.onClick}
title={this.props.title || this.props.text}
>
{this.props.text}
<span>{this.props.text}</span>
{this.props.icon}
</button>;
}
}
17 changes: 13 additions & 4 deletions src/components/objectinspector.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,22 @@
}

& h2 {
display: flex;
align-items: center;
padding: 1em;
overflow: hidden;
text-overflow: ellipsis;

& span {
& > span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
margin-right: 1em;
margin-right: auto;
}

& > .ck-inspector-button {
margin-left: .5em;
}

& a {
Expand All @@ -40,20 +46,23 @@
}

& h3 {
display: flex;
align-items: center;
font-size: 12px;
padding: .4em .7em;

& a {
color: inherit;
font-weight: bold;
margin-right: auto;
}

& .ck-inspector-button {
display: none;
visibility: hidden;
}

&:hover .ck-inspector-button {
display: block
visibility: visible;
}
}

Expand Down
12 changes: 0 additions & 12 deletions src/components/pane.css
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,6 @@
}

& .ck-inspector-tree__config {
& + .ck-inspector-tree__config {
&::before {
content: "";
border-right: 1px solid var(--ck-inspector-color-border);
display: inline-block;
width: 0px;
height: 20px;
margin: 0 1em;
vertical-align: middle;
}
}

& label {
margin: 0 .5em;
}
Expand Down
5 changes: 5 additions & 0 deletions src/data/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const SET_HEIGHT = 'SET_HEIGHT';
export const SET_SIDE_PANE_WIDTH = 'SET_SIDE_PANE_WIDTH';
export const SET_EDITORS = 'SET_EDITORS';
export const SET_CURRENT_EDITOR_NAME = 'SET_CURRENT_EDITOR_NAME';
export const UPDATE_CURRENT_EDITOR_IS_READ_ONLY = 'UPDATE_CURRENT_EDITOR_IS_READ_ONLY';
export const SET_ACTIVE_INSPECTOR_TAB = 'SET_ACTIVE_INSPECTOR_TAB';

export function toggleIsCollapsed() {
Expand All @@ -33,3 +34,7 @@ export function setCurrentEditorName( editorName ) {
export function setActiveTab( tabName ) {
return { type: SET_ACTIVE_INSPECTOR_TAB, tabName };
}

export function updateCurrentEditorIsReadOnly() {
return { type: UPDATE_CURRENT_EDITOR_IS_READ_ONLY };
}
33 changes: 33 additions & 0 deletions src/data/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import {
SET_SIDE_PANE_WIDTH,
SET_EDITORS,
SET_CURRENT_EDITOR_NAME,
UPDATE_CURRENT_EDITOR_IS_READ_ONLY,
SET_ACTIVE_INSPECTOR_TAB
} from './actions';

import { getFirstEditorName } from '../utils';
import { getCurrentEditor } from './utils';

import LocalStorageManager from '../localstoragemanager';

Expand All @@ -28,6 +30,7 @@ export const LOCAL_STORAGE_SIDE_PANE_WIDTH = 'side-pane-width';
export function reducer( state, action ) {
const newState = appReducer( state, action );

newState.currentEditorGlobals = currentEditorGlobalsReducer( newState, newState.currentEditorGlobals, action );
newState.ui = appUIReducer( newState.ui, action );
newState.model = modelReducer( newState, newState.model, action );
newState.view = viewReducer( newState, newState.view, action );
Expand All @@ -50,6 +53,18 @@ function appReducer( state, action ) {
}
}

function currentEditorGlobalsReducer( state, globalsState, action ) {
switch ( action.type ) {
case SET_EDITORS:
case SET_CURRENT_EDITOR_NAME:
return getCurrentEditorGlobalState( state );
case UPDATE_CURRENT_EDITOR_IS_READ_ONLY:
return getNewCurrentEditorIsReadOnlyState( state, globalsState );
default:
return globalsState;
}
}

function appUIReducer( UIState, action ) {
// This happens when the inspector store is created for the first time only.
// Only #isCollapsed is passed then because it's configurable in inspector options.
Expand Down Expand Up @@ -96,6 +111,24 @@ function getNewCurrentEditorNameState( appState, action ) {
};
}

function getCurrentEditorGlobalState( appState ) {
const isReadOnlyState = getNewCurrentEditorIsReadOnlyState( appState, {} );

return {
...isReadOnlyState
};
}

function getNewCurrentEditorIsReadOnlyState( appState, globalsState ) {
const editor = getCurrentEditor( appState );

return {
...globalsState,

isReadOnly: editor ? editor.isReadOnly : false
};
}

function getNewEditorsState( appState, action ) {
const newState = {
editors: new Map( action.editors )
Expand Down
6 changes: 6 additions & 0 deletions src/data/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ export default class EditorListener {
startListening( currentEditor ) {
currentEditor.model.document.on( 'change', this._config.onModelChange );
currentEditor.editing.view.on( 'render', this._config.onViewRender );
currentEditor.on( 'change:isReadOnly', this._config.onReadOnlyChange );
}

stopListening( currentEditor ) {
currentEditor.model.document.off( 'change', this._config.onModelChange );
currentEditor.editing.view.off( 'render', this._config.onViewRender );
currentEditor.off( 'change:isReadOnly', this._config.onReadOnlyChange );
}
}

export function getCurrentEditor( globalState ) {
return globalState.editors.get( globalState.currentEditorName );
}
17 changes: 17 additions & 0 deletions src/editorquickactions.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

.ck-inspector .ck-inspector-editor-quick-actions {
display: flex;
align-content: center;
justify-content: center;
align-items: center;
flex-direction: row;
flex-wrap: nowrap;

& > .ck-inspector-button {
margin-left: .3em;
}
}
Loading

0 comments on commit 9417d93

Please sign in to comment.