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

Read Only Mode in Canvas #23304

Merged
merged 27 commits into from
Oct 22, 2018
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
58ca391
Added readOnly to transient state
cqliu1 Sep 17, 2018
37bb076
Added check that user has permission to edit when loading workpads
cqliu1 Sep 17, 2018
e3717b7
Shows toolbar in readOnly mode
cqliu1 Sep 17, 2018
0ab8152
Disables page controls in read only mode
cqliu1 Sep 17, 2018
8b5252d
Disables add page button when editing disabled
cqliu1 Sep 19, 2018
2264d50
Added comment to workpad routes
cqliu1 Sep 19, 2018
4ae0cd5
Cleaned up page manager styles
cqliu1 Sep 19, 2018
585a769
Added a comment to es_persist
cqliu1 Sep 19, 2018
aea0b81
Merge branch 'master' into feat/read-only-mode
cqliu1 Sep 26, 2018
2118571
Renamed transient.readOnly to transient.readOnlyUser
cqliu1 Sep 26, 2018
e6f3c2f
Replaced isEditing in transient state with readOnly in workpad state
cqliu1 Sep 26, 2018
f9fd32c
Cleaned up workpad_header
cqliu1 Sep 26, 2018
6c20700
Fixed logic in workpad_header
cqliu1 Sep 26, 2018
a1a0a70
Merge branch 'master' into feat/read-only-mode
cqliu1 Sep 26, 2018
67aa2e4
Merge branch 'master' into feat/read-only-mode
cqliu1 Oct 2, 2018
6220531
Disables workpad controls instead of hiding them and adds tooltips
cqliu1 Oct 2, 2018
d417157
Merge branch 'master' into feat/read-only-mode
cqliu1 Oct 4, 2018
4d5ecf3
Switched eye icon to lock icon in workpad header
cqliu1 Oct 4, 2018
01c0b3b
Merge branch 'master' into feat/read-only-mode
cqliu1 Oct 16, 2018
3acc54e
Merge branch 'master' into feat/read-only-mode
cqliu1 Oct 18, 2018
6a7ee14
Renamed readOnly and readOnlyUser variables and functions
cqliu1 Oct 18, 2018
bcf9e30
Added dispatch to update canUserWrite in create/clone/delete workpads
cqliu1 Oct 18, 2018
d429466
Fixed typo
cqliu1 Oct 18, 2018
6990d12
Removed unnecessary prop from workpad
cqliu1 Oct 18, 2018
b8ce43d
Refactored tooltips in workpad_loader
cqliu1 Oct 18, 2018
2ef216a
Added workpad selector tests
cqliu1 Oct 18, 2018
238a3a1
Merge branch 'master' into feat/read-only-mode
cqliu1 Oct 18, 2018
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
12 changes: 12 additions & 0 deletions x-pack/plugins/canvas/public/apps/workpad/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { setWorkpad } from '../../state/actions/workpad';
import { setAssets, resetAssets } from '../../state/actions/assets';
import { gotoPage } from '../../state/actions/pages';
import { getWorkpad } from '../../state/selectors/workpad';
import { setCanUserWrite } from '../../state/actions/transient';
import { WorkpadApp } from './workpad_app';

export const routes = [
Expand All @@ -29,6 +30,10 @@ export const routes = [
router.redirectTo('loadWorkpad', { id: newWorkpad.id, page: 1 });
} catch (err) {
notify.error(err, { title: `Couldn't create workpad` });
// TODO: remove this and switch to checking user privileges when canvas loads when granular app privileges are introduced
// https://github.com/elastic/kibana/issues/20277
if (err.response.status === 403) dispatch(setCanUserWrite(false));
router.redirectTo('home');
}
},
meta: {
Expand All @@ -48,6 +53,13 @@ export const routes = [
const { assets, ...workpad } = fetchedWorkpad;
dispatch(setWorkpad(workpad));
dispatch(setAssets(assets));

// tests if user has permissions to write to workpads
// TODO: remove this and switch to checking user privileges when canvas loads when granular app privileges are introduced
// https://github.com/elastic/kibana/issues/20277
workpadService.update(params.id, fetchedWorkpad).catch(err => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since you mentioned there will be a new permissions API forthcoming, consider adding a TODO comment here with a follow-up task?

if (err.response.status === 403) dispatch(setCanUserWrite(false));
});
} catch (err) {
notify.error(err, { title: `Couldn't load workpad with ID` });
return router.redirectTo('home');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import { connect } from 'react-redux';
import { compose, branch, renderComponent } from 'recompose';
import { initializeWorkpad } from '../../../state/actions/workpad';
import { selectElement } from '../../../state/actions/transient';
import { getEditing, getAppReady } from '../../../state/selectors/app';
import { getWorkpad } from '../../../state/selectors/workpad';
import { canUserWrite, getAppReady } from '../../../state/selectors/app';
import { getWorkpad, isWriteable } from '../../../state/selectors/workpad';
import { LoadWorkpad } from './load_workpad';
import { WorkpadApp as Component } from './workpad_app';

const mapStateToProps = state => {
const appReady = getAppReady(state);

return {
editing: getEditing(state),
isWriteable: isWriteable(state) && canUserWrite(state),
appReady: typeof appReady === 'object' ? appReady : { ready: appReady },
workpad: getWorkpad(state),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { WorkpadHeader } from '../../../components/workpad_header';

export class WorkpadApp extends React.PureComponent {
static propTypes = {
editing: PropTypes.bool,
isWriteable: PropTypes.bool.isRequired,
deselectElement: PropTypes.func,
initializeWorkpad: PropTypes.func.isRequired,
};
Expand All @@ -23,7 +23,7 @@ export class WorkpadApp extends React.PureComponent {
}

render() {
const { editing, deselectElement } = this.props;
const { isWriteable, deselectElement } = this.props;

return (
<div className="canvasLayout">
Expand All @@ -42,18 +42,16 @@ export class WorkpadApp extends React.PureComponent {
</div>
</div>

{editing && (
{isWriteable && (
<div className="canvasLayout__sidebar hide-for-sharing">
<Sidebar />
</div>
)}
</div>

{editing ? (
<div className="canvasLayout__footer hide-for-sharing">
<Toolbar />
</div>
) : null}
<div className="canvasLayout__footer hide-for-sharing">
<Toolbar />
</div>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@

import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { getEditing } from '../../state/selectors/app';
import { getResolvedArgs, getSelectedPage } from '../../state/selectors/workpad';
import { getResolvedArgs, getSelectedPage, isWriteable } from '../../state/selectors/workpad';
import { getState, getValue, getError } from '../../lib/resolved_arg';
import { ElementWrapper as Component } from './element_wrapper';
import { createHandlers as createHandlersWithDispatch } from './lib/handlers';

const mapStateToProps = (state, { element }) => ({
isEditing: getEditing(state),
isWriteable: isWriteable(state),
resolvedArg: getResolvedArgs(state, element.id, 'expressionRenderable'),
selectedPage: getSelectedPage(state),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
import { connect } from 'react-redux';
import { compose, withState } from 'recompose';
import * as pageActions from '../../state/actions/pages';
import { getSelectedPage, getWorkpad, getPages } from '../../state/selectors/workpad';
import { canUserWrite } from '../../state/selectors/app';
import { getSelectedPage, getWorkpad, getPages, isWriteable } from '../../state/selectors/workpad';
import { PageManager as Component } from './page_manager';

const mapStateToProps = state => ({
isWriteable: isWriteable(state) && canUserWrite(state),
pages: getPages(state),
selectedPage: getSelectedPage(state),
workpadId: getWorkpad(state).id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { PagePreview } from '../page_preview';

export class PageManager extends React.PureComponent {
static propTypes = {
isWriteable: PropTypes.bool.isRequired,
pages: PropTypes.array.isRequired,
workpadId: PropTypes.string.isRequired,
addPage: PropTypes.func.isRequired,
Expand Down Expand Up @@ -102,11 +103,11 @@ export class PageManager extends React.PureComponent {
};

renderPage = (page, i) => {
const { selectedPage, workpadId, movePage, duplicatePage } = this.props;
const { isWriteable, selectedPage, workpadId, movePage, duplicatePage } = this.props;
const pageNumber = i + 1;

return (
<Draggable key={page.id} draggableId={page.id} index={i}>
<Draggable key={page.id} draggableId={page.id} index={i} isDragDisabled={!isWriteable}>
{provided => (
<div
key={page.id}
Expand All @@ -133,6 +134,7 @@ export class PageManager extends React.PureComponent {
aria-label={`Load page number ${pageNumber}`}
>
<PagePreview
isWriteable={isWriteable}
page={page}
height={100}
pageNumber={pageNumber}
Expand All @@ -151,7 +153,7 @@ export class PageManager extends React.PureComponent {
};

render() {
const { pages, addPage, deleteId } = this.props;
const { pages, addPage, deleteId, isWriteable } = this.props;
const { showTrayPop } = this.state;

return (
Expand All @@ -178,17 +180,19 @@ export class PageManager extends React.PureComponent {
</Droppable>
</DragDropContext>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiToolTip
anchorClassName="canvasPageManager__addPageTip"
content="Add a new page to this workpad"
position="left"
>
<button onClick={addPage} className="canvasPageManager__addPage">
<EuiIcon color="ghost" type="plusInCircle" size="l" />
</button>
</EuiToolTip>
</EuiFlexItem>
{isWriteable && (
<EuiFlexItem grow={false}>
<EuiToolTip
anchorClassName="canvasPageManager__addPageTip"
content="Add a new page to this workpad"
position="left"
>
<button onClick={addPage} className="canvasPageManager__addPage">
<EuiIcon color="ghost" type="plusInCircle" size="l" />
</button>
</EuiToolTip>
</EuiFlexItem>
)}
</EuiFlexGroup>
<ConfirmModal
isOpen={deleteId != null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,9 @@
position: relative;
}

.canvasPageManager__pageList {
@include euiScrollBar;
display: flex;
overflow-x: auto;
overflow-y: hidden;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
.canvasPageManager__pages,
.canvasPageManager__addPage {
height: 144px;
}

.canvasPageManager--trayPop > div {
Expand All @@ -26,14 +19,25 @@
}
}

.canvasPageManager__pageList {
@include euiScrollBar;
display: flex;
overflow-x: auto;
overflow-y: hidden;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}

.canvasPageManager__addPage {
width: $euiSizeXXL + $euiSize;
background: $euiColorSecondary;
color: $euiColorGhost;
opacity: 0;
animation: buttonPop $euiAnimSpeedNormal $euiAnimSlightResistance;
animation-fill-mode: forwards;
height: 144px;
}

.canvasPageManager__addPageTip {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,32 @@ import PropTypes from 'prop-types';
import { DomPreview } from '../dom_preview';
import { PageControls } from './page_controls';

export const PagePreview = ({ page, pageNumber, height, duplicatePage, confirmDelete }) => (
export const PagePreview = ({
isWriteable,
page,
pageNumber,
height,
duplicatePage,
confirmDelete,
}) => (
<div
className="canvasPageManager__pagePreview"
style={{ backgroundColor: page.style.background }}
>
<DomPreview elementId={page.id} pageNumber={pageNumber} height={height} />
<PageControls
pageId={page.id}
pageNumber={pageNumber}
onDuplicate={duplicatePage}
onDelete={confirmDelete}
/>
{isWriteable && (
<PageControls
pageId={page.id}
pageNumber={pageNumber}
onDuplicate={duplicatePage}
onDelete={confirmDelete}
/>
)}
</div>
);

PagePreview.propTypes = {
isWriteable: PropTypes.bool.isRequired,
page: PropTypes.shape({
id: PropTypes.string.isRequired,
style: PropTypes.shape({
Expand Down
2 changes: 0 additions & 2 deletions x-pack/plugins/canvas/public/components/toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { compose, withState, getContext, withHandlers } from 'recompose';
import { getEditing } from '../../state/selectors/app';

import {
getWorkpad,
Expand All @@ -19,7 +18,6 @@ import {
import { Toolbar as Component } from './toolbar';

const mapStateToProps = state => ({
editing: getEditing(state),
workpadName: getWorkpadName(state),
workpadId: getWorkpad(state).id,
totalPages: getWorkpad(state).pages.length,
Expand Down
4 changes: 1 addition & 3 deletions x-pack/plugins/canvas/public/components/toolbar/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { Tray } from './tray';

export const Toolbar = props => {
const {
editing,
selectedElement,
tray,
setTray,
Expand Down Expand Up @@ -63,7 +62,7 @@ export const Toolbar = props => {
expression: !elementIsSelected ? null : <Expression done={done} />,
};

return !editing ? null : (
return (
<div className="canvasToolbar hide-for-sharing">
{trays[tray] && <Tray done={done}>{trays[tray]}</Tray>}
<Navbar>
Expand Down Expand Up @@ -122,7 +121,6 @@ export const Toolbar = props => {

Toolbar.propTypes = {
workpadName: PropTypes.string,
editing: PropTypes.bool,
tray: PropTypes.node,
setTray: PropTypes.func.isRequired,
nextPage: PropTypes.func.isRequired,
Expand Down
3 changes: 1 addition & 2 deletions x-pack/plugins/canvas/public/components/workpad/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { compose, withState, withProps, getContext, withHandlers } from 'recompo
import { transitionsRegistry } from '../../lib/transitions_registry';
import { undoHistory, redoHistory } from '../../state/actions/history';
import { fetchAllRenderables } from '../../state/actions/elements';
import { getFullscreen, getEditing } from '../../state/selectors/app';
import { getFullscreen } from '../../state/selectors/app';
import {
getSelectedPageIndex,
getAllElements,
Expand All @@ -25,7 +25,6 @@ const mapStateToProps = state => ({
totalElementCount: getAllElements(state).length,
workpad: getWorkpad(state),
isFullscreen: getFullscreen(state),
isEditing: getEditing(state),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This prop wasn't being used in the workpad component, so I removed it.

});

const mapDispatchToProps = {
Expand Down
13 changes: 7 additions & 6 deletions x-pack/plugins/canvas/public/components/workpad_header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,23 @@

import { compose, withState } from 'recompose';
import { connect } from 'react-redux';
import { getEditing } from '../../state/selectors/app';
import { getWorkpadName, getSelectedPage } from '../../state/selectors/workpad';
import { setEditing } from '../../state/actions/transient';
import { canUserWrite } from '../../state/selectors/app';
import { getWorkpadName, getSelectedPage, isWriteable } from '../../state/selectors/workpad';
import { setWriteable } from '../../state/actions/workpad';
import { getAssets } from '../../state/selectors/assets';
import { addElement } from '../../state/actions/elements';
import { WorkpadHeader as Component } from './workpad_header';

const mapStateToProps = state => ({
editing: getEditing(state),
isWriteable: isWriteable(state) && canUserWrite(state),
canUserWrite: canUserWrite(state),
workpadName: getWorkpadName(state),
selectedPage: getSelectedPage(state),
hasAssets: Object.keys(getAssets(state)).length ? true : false,
});

const mapDispatchToProps = dispatch => ({
setEditing: editing => dispatch(setEditing(editing)),
setWriteable: isWriteable => dispatch(setWriteable(isWriteable)),
addElement: pageId => partialElement => dispatch(addElement(pageId, partialElement)),
});

Expand All @@ -30,7 +31,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => ({
...dispatchProps,
...ownProps,
addElement: dispatchProps.addElement(stateProps.selectedPage),
toggleEditing: () => dispatchProps.setEditing(!stateProps.editing),
toggleWriteable: () => dispatchProps.setWriteable(!stateProps.isWriteable),
});

export const WorkpadHeader = compose(
Expand Down
Loading