Skip to content

Commit

Permalink
Create NoteCreatePage component (#510)
Browse files Browse the repository at this point in the history
  • Loading branch information
MaksymDryha authored May 16, 2019
1 parent 966439e commit 46a8062
Show file tree
Hide file tree
Showing 13 changed files with 292 additions and 38 deletions.
1 change: 0 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,4 @@ export { default as UserName } from './lib/UserName';
export { default as ViewMetaData } from './lib/ViewMetaData';

export { default as DueDatePicker } from './lib/ChangeDueDateDialog/DueDatePicker';

export * from './lib/Notes';
22 changes: 11 additions & 11 deletions lib/Notes/AssignmentsList/AssignmentsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ import styles from './AssignmentsList.css';

import {
referredEntityDataShape,
linkedEntitiesTypesShape,
linkedEntityTypesShape,
} from '../NoteForm/noteShapes';

export default class AssignmentsList extends Component {
static propTypes = {
entityTypePluralizedTranslationKeyMap: PropTypes.objectOf(PropTypes.string),
entityTypeTranslationKeyMap: PropTypes.objectOf(PropTypes.string),
linkedEntitiesTypes: linkedEntitiesTypesShape,
entityTypesPluralizedTranslationKeys: PropTypes.objectOf(PropTypes.string),
entityTypesTranslationKeys: PropTypes.objectOf(PropTypes.string),
linkedEntityTypes: linkedEntityTypesShape,
referredEntityData: referredEntityDataShape.isRequired,
};

static defaultProps = {
linkedEntitiesTypes: [],
linkedEntityTypes: [],
};

renderReferredRecord = () => {
Expand All @@ -32,12 +32,12 @@ export default class AssignmentsList extends Component {
name,
type,
},
entityTypeTranslationKeyMap,
entityTypesTranslationKeys,
} = this.props;

const entityType = (
<span className={styles['referred-record__entity-type']}>
<FormattedMessage id={entityTypeTranslationKeyMap[type]} />
<FormattedMessage id={entityTypesTranslationKeys[type]} />
</span>
);

Expand All @@ -59,14 +59,14 @@ export default class AssignmentsList extends Component {

getListItems() {
const {
linkedEntitiesTypes,
entityTypePluralizedTranslationKeyMap,
linkedEntityTypes,
entityTypesPluralizedTranslationKeys,
} = this.props;

return linkedEntitiesTypes.map(({ count, type }) => (
return linkedEntityTypes.map(({ count, type }) => (
<span className={styles['assignments-list__item']}>
<FormattedMessage
id={entityTypePluralizedTranslationKeyMap[type]}
id={entityTypesPluralizedTranslationKeys[type]}
values={{ count }}
/>
</span>
Expand Down
152 changes: 152 additions & 0 deletions lib/Notes/NoteCreatePage/NoteCreatePage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { get } from 'lodash';

import {
stripesConnect,
TitleManager,
} from '@folio/stripes-core';

import { Icon } from '@folio/stripes-components';

import NoteForm from '../NoteForm';
import noteTypesCollectionShape from '../response-shapes';

@stripesConnect
class NoteCreatePage extends Component {
static propTypes = {
domain: PropTypes.string.isRequired,
entityTypesTranslationKeys: PropTypes.objectOf(PropTypes.string),
mutator: PropTypes.shape({
notes: PropTypes.shape({
POST: PropTypes.func.isRequired,
}).isRequired,
}).isRequired,
navigateBack: PropTypes.func.isRequired,
paneHeaderAppIcon: PropTypes.string.isRequired,
referredEntityData: PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
}).isRequired,
resources: PropTypes.shape({
noteTypesData: noteTypesCollectionShape
}),
}

static manifest = Object.freeze({
noteTypesData: {
type: 'okapi',
path: 'note-types',
},
notes: {
type: 'okapi',
path: 'notes',
fetch: false,
},
});

state = {
submitIsPending: false,
submitSucceeded: false,
};

onSubmit = async (noteData) => {
try {
await this.sendNoteData(noteData);
this.handleSuccessResponse();
} catch (err) {
this.handleFailedResponse();
}
}

sendNoteData(noteData) {
this.setState({ submitIsPending: true });

return this.props.mutator.notes.POST(this.serializeNoteData(noteData));
}

serializeNoteData = (formData) => {
const {
domain,
referredEntityData: {
id,
type,
},
} = this.props;

return {
domain,
typeId: formData.type,
content: formData.content,
title: formData.title,
links: [{ type, id }]
};
}

handleSuccessResponse() {
this.setState({
submitSucceeded: true,
submitIsPending: false,
}, this.props.navigateBack);
}

handleFailedResponse() {
this.setState({ submitIsPending: false });
}

renderSpinner() {
return (
<Icon icon="spinner-ellipsis" />
);
}

getNoteTypesSelectOptions = () => {
const { noteTypes } = this.props.resources.noteTypesData.records[0];

return noteTypes.map(noteType => ({
label: noteType.name,
value: noteType.id
}));
}

render() {
const {
referredEntityData,
entityTypesTranslationKeys,
paneHeaderAppIcon,
navigateBack,
} = this.props;

const {
submitIsPending,
submitSucceeded,
} = this.state;

const noteTypesLoaded = get(this.props, ['resources', 'noteTypesData', 'hasLoaded']);

return noteTypesLoaded
? (
<FormattedMessage id="stripes-smart-components.notes.newNote">
{pageTitle => (
<TitleManager record={pageTitle}>
<NoteForm
noteTypes={this.getNoteTypesSelectOptions()}
referredEntityData={referredEntityData}
entityTypesTranslationKeys={entityTypesTranslationKeys}
submitIsPending={submitIsPending}
submitSucceeded={submitSucceeded}
paneHeaderAppIcon={paneHeaderAppIcon}
onSubmit={this.onSubmit}
navigateBack={navigateBack}
/>
</TitleManager>
)}
</FormattedMessage>
)
: this.renderSpinner();
}
}

export default NoteCreatePage;
1 change: 1 addition & 0 deletions lib/Notes/NoteCreatePage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './NoteCreatePage';
66 changes: 66 additions & 0 deletions lib/Notes/NoteCreatePage/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
## NoteCreatePage
A connected component for creating a note

## Description
This is a connected component used for creating a note. It's responsible for fetching note types, validating the note data entered by user, sending it to the back-end (mod-notes), handling navigation/redirection after a note is created or chancel button is clicked.

## Props
| Name | Type | Description |
| ---------------------- | --------------------------- | ----------------------------------------------------- |
| referredEntityData | object with `name`, `type` and `id` strings | Is used for displaying the data of an entity from whose page a user navigated to the create note page. The newly created note will be attached to this entity |
| domain | string | Every note is associated with a domain (i.e application). This prop tells which domain the newly created note should be associated with |
| paneHeaderAppIcon | string | A name of an icon to be displayed in the pane header |
| navigateBack | func | A callback which is executed after the note is successfully saved or when cancellation button is clicked |
| entityTypesTranslationKeys | object whose keys are entity types and values are the translation keys for those entity types | is used to translate `referredEntityData`'s entity type |

## Usage (eholdings example)
```js
const entityTypeTranslationKeys = {
provider: 'ui-eholdings.notes.entityType.provider',
package: 'ui-eholdings.notes.entityType.package',
resource: 'ui-eholdings.notes.entityType.resource',
};

export default class NoteCreateRoute extends Component {
static propTypes = {
history: PropTypes.shape({
goBack: PropTypes.func.isRequired,
}).isRequired,
location: ReactRouterPropTypes.location.isRequired,
};

referredEntityData = this.getReferredEntityData();

getReferredEntityData() {
const {
referredName: name,
referredType: type,
referredId: id,
} = this.parseQueryParams();

return {
name,
type,
id,
};
}

parseQueryParams() {
return queryString.parse(this.props.location.search, {
ignoreQueryPrefix: true
});
}

render() {
return (
<NoteCreatePage
referredEntityData={this.referredEntityData}
entityTypesTranslationKeys={entityTypesTranslationKeys}
paneHeaderAppIcon="eholdings"
domain="eholdings"
navigateBack={this.props.history.goBack}
/>
);
}
}
```
Loading

0 comments on commit 46a8062

Please sign in to comment.