Refactored to use a common <OrganizationPicker /> component (#4470)
* Refactored to use a common <OrganizationPicker /> component. * Small refactor to organization <option />s. * Renamed files from OrgSettings* to OrganizationPicker* * Brought orgsettings inline to article form. * Brought orgsettings inline to listings form. * Rename onBlur to onToggle for org picker instances. Ooops. * Updated <OrganizationPicker /> test.
This commit is contained in:
parent
d6d251e9ce
commit
68e94f524b
9 changed files with 195 additions and 126 deletions
|
|
@ -16,10 +16,10 @@ import Title from './elements/title';
|
|||
import MainImage from './elements/mainImage';
|
||||
import ImageManagement from './elements/imageManagement';
|
||||
import MoreConfig from './elements/moreConfig';
|
||||
import OrgSettings from './elements/orgSettings';
|
||||
import Errors from './elements/errors';
|
||||
import KeyboardShortcutsHandler from './elements/keyboardShortcutsHandler';
|
||||
import Tags from '../shared/components/tags';
|
||||
import { OrganizationPicker } from '../organization/OrganizationPicker';
|
||||
|
||||
const SetupImageButton = ({
|
||||
className,
|
||||
|
|
@ -88,7 +88,7 @@ export default class ArticleForm extends Component {
|
|||
tagList: this.article.cached_tag_list || '',
|
||||
description: '',
|
||||
canonicalUrl: this.article.canonical_url || '',
|
||||
series:this.state.series || '',
|
||||
series: this.state.series || '',
|
||||
allSeries: this.article.all_series || [],
|
||||
bodyMarkdown: this.article.body_markdown || '',
|
||||
published: this.article.published || false,
|
||||
|
|
@ -292,7 +292,7 @@ export default class ArticleForm extends Component {
|
|||
tagList: this.article.cached_tag_list || '',
|
||||
description: '',
|
||||
canonicalUrl: this.article.canonical_url || '',
|
||||
series:this.state.series || '',
|
||||
series: this.state.series || '',
|
||||
allSeries: this.article.all_series || [],
|
||||
bodyMarkdown: this.article.body_markdown || '',
|
||||
published: this.article.published || false,
|
||||
|
|
@ -381,14 +381,17 @@ export default class ArticleForm extends Component {
|
|||
);
|
||||
const orgArea =
|
||||
organizations && organizations.length > 0 ? (
|
||||
<OrgSettings
|
||||
organizations={organizations}
|
||||
organizationId={organizationId}
|
||||
onToggle={this.handleOrgIdChange}
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
);
|
||||
<div className="articleform__orgsettings">
|
||||
Publish under an organization:
|
||||
<OrganizationPicker
|
||||
name="article[organization_id]"
|
||||
id="article_publish_under_org"
|
||||
organizations={organizations}
|
||||
organizationId={organizationId}
|
||||
onToggle={this.handleOrgIdChange}
|
||||
/>
|
||||
</div>
|
||||
) : null;
|
||||
const errorsArea = errors ? <Errors errorsList={errors} /> : '';
|
||||
let editorView = '';
|
||||
if (previewShowing) {
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
import { h } from 'preact';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const orgOptions = (organizations, organizationId) => {
|
||||
const orgs = organizations.map(organization => {
|
||||
if (organizationId === organization.id) {
|
||||
return (
|
||||
<option value={organization.id} selected>
|
||||
{organization.name}
|
||||
</option>
|
||||
);
|
||||
}
|
||||
return <option value={organization.id}>{organization.name}</option>;
|
||||
});
|
||||
const nullOrgOption =
|
||||
organizationId === null ? (
|
||||
<option value="" selected>
|
||||
None
|
||||
</option>
|
||||
) : (
|
||||
<option value="">None</option>
|
||||
);
|
||||
orgs.unshift(nullOrgOption); // make first option as "None"
|
||||
return orgs;
|
||||
};
|
||||
|
||||
const OrgSettings = ({ organizations, organizationId, onToggle }) => (
|
||||
<div className="articleform__orgsettings">
|
||||
Publish under an organization:
|
||||
<select
|
||||
name="article[organization_id]"
|
||||
id="article_publish_under_org"
|
||||
onBlur={onToggle}
|
||||
>
|
||||
{orgOptions(organizations, organizationId)}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
|
||||
OrgSettings.propTypes = {
|
||||
onToggle: PropTypes.func.isRequired,
|
||||
organizationId: PropTypes.string.isRequired,
|
||||
organizations: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
}),
|
||||
).isRequired,
|
||||
};
|
||||
|
||||
export default OrgSettings;
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
// listings
|
||||
import { h } from 'preact';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const orgOptions = (organizations, organizationId) => {
|
||||
const orgs = organizations.map(organization => {
|
||||
if (organizationId === organization.id) {
|
||||
return (
|
||||
<option value={organization.id} selected>
|
||||
{organization.name}
|
||||
</option>
|
||||
);
|
||||
}
|
||||
return <option value={organization.id}>{organization.name}</option>;
|
||||
});
|
||||
const nullOrgOption =
|
||||
organizationId === null ? (
|
||||
<option value="" selected>
|
||||
None
|
||||
</option>
|
||||
) : (
|
||||
<option value="">None</option>
|
||||
);
|
||||
orgs.unshift(nullOrgOption); // make first option as "None"
|
||||
return orgs;
|
||||
};
|
||||
|
||||
const OrgSettings = ({ organizations, organizationId, onToggle }) => (
|
||||
<div className="field">
|
||||
<label htmlFor="organizationId">Post under an organization:</label>
|
||||
<select
|
||||
name="classified_listing[organization_id]"
|
||||
id="listing_organization_id"
|
||||
onBlur={onToggle}
|
||||
>
|
||||
{orgOptions(organizations, organizationId)}
|
||||
</select>
|
||||
<p>
|
||||
<em>Posting on behalf of org spends org credits.</em>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
OrgSettings.propTypes = {
|
||||
onToggle: PropTypes.func.isRequired,
|
||||
organizationId: PropTypes.number.isRequired,
|
||||
organizations: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
}),
|
||||
).isRequired,
|
||||
};
|
||||
|
||||
export default OrgSettings;
|
||||
|
|
@ -4,10 +4,10 @@ import linkState from 'linkstate';
|
|||
import Title from './elements/title';
|
||||
import BodyMarkdown from './elements/bodyMarkdown';
|
||||
import Categories from './elements/categories';
|
||||
import OrgSettings from './elements/orgSettings';
|
||||
import ContactViaConnect from './elements/contactViaConnect';
|
||||
import ExpireDate from './elements/expireDate';
|
||||
import Tags from '../shared/components/tags';
|
||||
import { OrganizationPicker } from '../organization/OrganizationPicker';
|
||||
|
||||
export default class ListingForm extends Component {
|
||||
constructor(props) {
|
||||
|
|
@ -63,14 +63,20 @@ export default class ListingForm extends Component {
|
|||
|
||||
const selectOrg =
|
||||
organizations && organizations.length > 0 ? (
|
||||
<OrgSettings
|
||||
organizations={organizations}
|
||||
organizationId={organizationId}
|
||||
onToggle={this.handleOrgIdChange}
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
);
|
||||
<div className="field">
|
||||
<label htmlFor="organizationId">Post under an organization:</label>
|
||||
<OrganizationPicker
|
||||
name="classified_listing[organization_id]"
|
||||
id="listing_organization_id"
|
||||
organizations={organizations}
|
||||
organizationId={organizationId}
|
||||
onToggle={this.handleOrgIdChange}
|
||||
/>
|
||||
<p>
|
||||
<em>Posting on behalf of org spends org credits.</em>
|
||||
</p>
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
if (id === null) {
|
||||
return (
|
||||
|
|
|
|||
46
app/javascript/organization/OrganizationPicker.jsx
Normal file
46
app/javascript/organization/OrganizationPicker.jsx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import { h } from 'preact';
|
||||
import PropTypes from 'prop-types';
|
||||
import { organizationPropType } from '../src/components/common-prop-types';
|
||||
|
||||
const orgOptions = (organizations, organizationId) => {
|
||||
const orgs = organizations.map(organization => {
|
||||
if (organizationId === organization.id) {
|
||||
return (
|
||||
<option value={organization.id} selected>
|
||||
{organization.name}
|
||||
</option>
|
||||
);
|
||||
}
|
||||
return <option value={organization.id}>{organization.name}</option>;
|
||||
});
|
||||
const nullOrgOption =
|
||||
organizationId === null ? (
|
||||
<option value="" selected>
|
||||
None
|
||||
</option>
|
||||
) : (
|
||||
<option value="">None</option>
|
||||
);
|
||||
|
||||
return [nullOrgOption, ...orgs];
|
||||
};
|
||||
|
||||
export const OrganizationPicker = ({
|
||||
name,
|
||||
id,
|
||||
organizations,
|
||||
organizationId,
|
||||
onToggle,
|
||||
}) => (
|
||||
<select name={name} id={id} onBlur={onToggle}>
|
||||
{orgOptions(organizations, organizationId)}
|
||||
</select>
|
||||
);
|
||||
|
||||
OrganizationPicker.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
onToggle: PropTypes.func.isRequired,
|
||||
organizationId: PropTypes.number.isRequired,
|
||||
organizations: PropTypes.arrayOf(organizationPropType).isRequired,
|
||||
};
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import { h } from 'preact';
|
||||
import render from 'preact-render-to-json';
|
||||
import { OrganizationPicker } from '../OrganizationPicker';
|
||||
|
||||
const commonProps = {
|
||||
id: 'someFormElementId',
|
||||
name: 'someFormElementName',
|
||||
onToggle: jest.fn(),
|
||||
};
|
||||
|
||||
const organizations = [
|
||||
{ id: 1, name: 'Acme Org 1' },
|
||||
{ id: 2, name: 'Acme Org 2' },
|
||||
];
|
||||
|
||||
describe('<OrganizationPicker />', () => {
|
||||
it('renders with the given organization selected from the list of available organizations', () => {
|
||||
const tree = render(
|
||||
<OrganizationPicker
|
||||
{...commonProps}
|
||||
organizationId={1}
|
||||
organizations={organizations}
|
||||
/>,
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders with no organization selected when the organization ID is not set', () => {
|
||||
const tree = render(
|
||||
<OrganizationPicker
|
||||
{...commonProps}
|
||||
organizationId={undefined}
|
||||
organizations={organizations}
|
||||
/>,
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders an organization list with only "None" as an option when no organizations are passed in.', () => {
|
||||
const tree = render(
|
||||
<OrganizationPicker
|
||||
{...commonProps}
|
||||
organizationId={undefined}
|
||||
organizations={[]}
|
||||
/>,
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<OrganizationPicker /> renders an organization list with only "None" as an option when no organizations are passed in. 1`] = `
|
||||
<select
|
||||
id="someFormElementId"
|
||||
name="someFormElementName"
|
||||
onBlur={[MockFunction]}
|
||||
>
|
||||
<option
|
||||
value=""
|
||||
>
|
||||
None
|
||||
</option>
|
||||
</select>
|
||||
`;
|
||||
|
||||
exports[`<OrganizationPicker /> renders with no organization selected when the organization ID is not set 1`] = `
|
||||
<select
|
||||
id="someFormElementId"
|
||||
name="someFormElementName"
|
||||
onBlur={[MockFunction]}
|
||||
>
|
||||
<option
|
||||
value=""
|
||||
>
|
||||
None
|
||||
</option>
|
||||
<option
|
||||
value={1}
|
||||
>
|
||||
Acme Org 1
|
||||
</option>
|
||||
<option
|
||||
value={2}
|
||||
>
|
||||
Acme Org 2
|
||||
</option>
|
||||
</select>
|
||||
`;
|
||||
|
||||
exports[`<OrganizationPicker /> renders with the given organization selected from the list of available organizations 1`] = `
|
||||
<select
|
||||
id="someFormElementId"
|
||||
name="someFormElementName"
|
||||
onBlur={[MockFunction]}
|
||||
>
|
||||
<option
|
||||
value=""
|
||||
>
|
||||
None
|
||||
</option>
|
||||
<option
|
||||
selected={true}
|
||||
value={1}
|
||||
>
|
||||
Acme Org 1
|
||||
</option>
|
||||
<option
|
||||
value={2}
|
||||
>
|
||||
Acme Org 2
|
||||
</option>
|
||||
</select>
|
||||
`;
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import userPropTypes from './user-prop-types';
|
||||
import defaultChildrenPropTypes from './default-children-prop-types';
|
||||
|
||||
export * from './organization-prop-type';
|
||||
export { userPropTypes, defaultChildrenPropTypes };
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
export const organizationPropType = PropTypes.shape({
|
||||
id: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue