Skip to content

Commit

Permalink
Batch properties in folder contents
Browse files Browse the repository at this point in the history
  • Loading branch information
robgietema committed Apr 26, 2017
1 parent 545f687 commit 0dee3b1
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased]
### Added
- Batch properties in folder contents @robgietema
- Batch tags in folder contents @robgietema
- Batch rename in folder contents @robgietema
- Diff view @robgietema
- Add revert to version @robgietema
Expand Down
1 change: 1 addition & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export Contents from './manage/Contents/Contents';
export ContentsIndexHeader from './manage/Contents/ContentsIndexHeader';
export ContentsItem from './manage/Contents/ContentsItem';
export ContentsUploadModal from './manage/Contents/ContentsUploadModal';
export ContentsPropertiesModal from './manage/Contents/ContentsPropertiesModal';
export ContentsRenameModal from './manage/Contents/ContentsRenameModal';
export ContentsTagsModal from './manage/Contents/ContentsTagsModal';
export Delete from './manage/Delete/Delete';
Expand Down
48 changes: 47 additions & 1 deletion src/components/manage/Contents/Contents.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
ContentsRenameModal,
ContentsUploadModal,
ContentsTagsModal,
ContentsPropertiesModal,
Pagination,
} from '../../../components';

Expand Down Expand Up @@ -159,6 +160,8 @@ export default class ContentsComponent extends Component {
this.onRenameCancel = this.onRenameCancel.bind(this);
this.onTagsOk = this.onTagsOk.bind(this);
this.onTagsCancel = this.onTagsCancel.bind(this);
this.onPropertiesOk = this.onPropertiesOk.bind(this);
this.onPropertiesCancel = this.onPropertiesCancel.bind(this);
this.onChangeFilter = this.onChangeFilter.bind(this);
this.onChangePage = this.onChangePage.bind(this);
this.onChangePageSize = this.onChangePageSize.bind(this);
Expand All @@ -173,6 +176,7 @@ export default class ContentsComponent extends Component {
this.upload = this.upload.bind(this);
this.rename = this.rename.bind(this);
this.tags = this.tags.bind(this);
this.properties = this.properties.bind(this);
this.paste = this.paste.bind(this);
this.fetchContents = this.fetchContents.bind(this);
this.state = {
Expand All @@ -181,6 +185,7 @@ export default class ContentsComponent extends Component {
showUpload: false,
showRename: false,
showTags: false,
showProperties: false,
itemsToDelete: [],
items: this.props.items,
filter: '',
Expand Down Expand Up @@ -525,6 +530,30 @@ export default class ContentsComponent extends Component {
});
}

/**
* On properties ok
* @method onPropertiesOk
* @returns {undefined}
*/
onPropertiesOk() {
this.fetchContents();
this.setState({
showProperties: false,
selected: [],
});
}

/**
* On properties cancel
* @method onPropertiesCancel
* @returns {undefined}
*/
onPropertiesCancel() {
this.setState({
showProperties: false,
});
}

/**
* Get field by id
* @method getFieldById
Expand Down Expand Up @@ -625,6 +654,17 @@ export default class ContentsComponent extends Component {
});
}

/**
* Properties handler
* @method properties
* @returns {undefined}
*/
properties() {
this.setState({
showProperties: true,
});
}

/**
* Paste handler
* @method paste
Expand Down Expand Up @@ -697,6 +737,12 @@ export default class ContentsComponent extends Component {
subjects: this.getFieldById(item, 'Subject'),
}))}
/>
<ContentsPropertiesModal
open={this.state.showProperties}
onCancel={this.onPropertiesCancel}
onOk={this.onPropertiesOk}
items={this.state.selected}
/>
<h1>Contents</h1>
<section id="content-core">
<Menu stackable>
Expand Down Expand Up @@ -733,7 +779,7 @@ export default class ContentsComponent extends Component {
<Dropdown.Item>
<Icon name="random" /> State
</Dropdown.Item>
<Dropdown.Item>
<Dropdown.Item onClick={this.properties}>
<Icon name="edit" /> Properties
</Dropdown.Item>
</Dropdown.Menu>
Expand Down
147 changes: 147 additions & 0 deletions src/components/manage/Contents/ContentsPropertiesModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/**
* Contents properties modal.
* @module components/manage/Contents/ContentsPropertiesModal
*/

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { isEmpty, map } from 'lodash';

import { editContent } from '../../../actions';
import { ModalForm } from '../../../components';

/**
* ContentsPropertiesModal class.
* @class ContentsPropertiesModal
* @extends Component
*/
@connect(
state => ({
request: state.content.edit,
}),
dispatch => bindActionCreators({ editContent }, dispatch),
)
export default class ContentsPropertiesModal extends Component {
/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
static propTypes = {
editContent: PropTypes.func.isRequired,
items: PropTypes.arrayOf(PropTypes.string).isRequired,
request: PropTypes.shape({
loading: PropTypes.bool,
loaded: PropTypes.bool,
}).isRequired,
open: PropTypes.bool.isRequired,
onOk: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
};

/**
* Constructor
* @method constructor
* @param {Object} props Component properties
* @constructs ContentsUploadModal
*/
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
}

/**
* Component will receive props
* @method componentWillReceiveProps
* @param {Object} nextProps Next properties
* @returns {undefined}
*/
componentWillReceiveProps(nextProps) {
if (this.props.request.loading && nextProps.request.loaded) {
this.props.onOk();
}
}

/**
* Submit handler
* @method onSubmit
* @param {Object} data Form data
* @returns {undefined}
*/
onSubmit(data) {
if (isEmpty(data)) {
this.props.onOk();
} else {
this.props.editContent(
this.props.items,
map(this.props.items, () => data),
);
}
}

/**
* Render method.
* @method render
* @returns {string} Markup for the component.
*/
render() {
return (
this.props.open &&
<ModalForm
open={this.props.open}
onSubmit={this.onSubmit}
onCancel={this.props.onCancel}
title="Properties"
schema={{
fieldsets: [
{
id: 'default',
title: 'Default',
fields: [
'effective',
'expires',
'rights',
'creators',
'exclude_from_nav',
],
},
],
properties: {
effective: {
description: 'If this date is in the future, the content will not show up in listings and searches until this date.',
title: 'Publishing Date',
type: 'string',
widget: 'datetime',
},
expires: {
description: 'When this date is reached, the content will nolonger be visible in listings and searches.',
title: 'Expiration Date',
type: 'string',
widget: 'datetime',
},
rights: {
description: 'Copyright statement or other rights information on this item.',
title: 'Rights',
type: 'string',
widget: 'textarea',
},
creators: {
description: 'Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first.',
title: 'Creators',
type: 'array',
},
exclude_from_nav: {
default: false,
description: 'If selected, this item will not appear in the navigation tree',
title: 'Exclude from navigation',
type: 'boolean',
},
},
required: [],
}}
/>
);
}
}
35 changes: 35 additions & 0 deletions src/components/manage/Contents/ContentsPropertiesModal.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import renderer from 'react-test-renderer';
import configureStore from 'redux-mock-store';
import { Provider } from 'react-redux';

import ContentsPropertiesModal from './ContentsPropertiesModal';

const mockStore = configureStore();

jest.mock('../Form/ModalForm', () => jest.fn(() => <div id="modalform" />));

describe('ContentsPropertiesModal', () => {
it('renders a contents properties modal component', () => {
const store = mockStore({
content: {
edit: {
loading: false,
loaded: true,
},
},
});
const component = renderer.create(
<Provider store={store}>
<ContentsPropertiesModal
open
onOk={() => {}}
onCancel={() => {}}
items={['/blog']}
/>
</Provider>,
);
const json = component.toJSON();
expect(json).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ContentsPropertiesModal renders a contents properties modal component 1`] = `
<div
id="modalform"
/>
`;

0 comments on commit 0dee3b1

Please sign in to comment.