Skip to content

Commit

Permalink
MNT Add to storybook
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli committed Feb 7, 2024
1 parent 03ffff8 commit b13bf3f
Show file tree
Hide file tree
Showing 2 changed files with 288 additions and 0 deletions.
159 changes: 159 additions & 0 deletions client/src/components/LinkField/LinkField-story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/* global window */
import React from 'react';
import { Component as LinkField } from 'components/LinkField/LinkField';

// mock global ss config
if (!window.ss) {
window.ss = {};
}
if (!window.ss.config) {
window.ss.config = {
sections: [
{
name: 'SilverStripe\\LinkField\\Controllers\\LinkFieldController',
form: {
linkForm: {
dataUrl: 'linkfield-endpoint',
}
}
},
]
};
}

// mock toast actions
const mockedActions = {
toasts: {
error: (text) => console.error(text),
success: (text) => console.warn(text),
}
};

// predetermine link types
const linkTypes = {
sitetree: {
key: 'sitetree',
title: 'Page on this site',
handlerName: 'FormBuilderModal',
priority: 0,
icon: 'font-icon-page',
allowed: true
},
file: {
key: 'file',
title: 'Link to a file',
handlerName: 'FormBuilderModal',
priority: 10,
icon: 'font-icon-image',
allowed: true
},
external: {
key: 'external',
title: 'Link to external URL',
handlerName: 'FormBuilderModal',
priority: 20,
icon: 'font-icon-external-link',
allowed: true
},
email: {
key: 'email',
title: 'Link to email address',
handlerName: 'FormBuilderModal',
priority: 30,
icon: 'font-icon-p-mail',
allowed: true
},
phone: {
key: 'phone',
title: 'Phone number',
handlerName: 'FormBuilderModal',
priority: 40,
icon: 'font-icon-mobile',
allowed: true
}
};

export default {
title: 'Linkfield/LinkField',
component: LinkField,
tags: ['autodocs'],
parameters: {
docs: {
description: {
component: 'The LinkField component. Note that the form modal for creating, editing, and viewing link data is disabled for the storybook.'
},
canvas: {
sourceState: 'shown',
},
controls: {
exclude: [
'onChange',
'value',
'ownerID',
'ownerClass',
'ownerRelation',
'actions',
],
},
},
},
argTypes: {
types: {
description: 'Types of links that are allowed in this field. The actual prop is a JSON object with some metadata about each type.',
control: 'inline-check',
options: Object.keys(linkTypes),
},
isMulti: {
description: 'Whether the field supports multiple links or not.',
},
canCreate: {
description: 'Whether the current user has create permission or not.',
},
readonly: {
description: 'Whether the field is readonly or not.',
},
disabled: {
description: 'Whether the field is disabled or not.',
},
ownerSaved: {
description: 'Whether the record which owns the link field has been saved or not. The actual props for this are OwnerID, OwnerClass, and OwnerRelation.',
},
},
};

export const _LinkField = {
name: 'LinkField',
args: {
value: [0],
onChange: () => {},
types: Object.keys(linkTypes),
actions: mockedActions,
isMulti: false,
canCreate: true,
readonly: false,
disabled: false,
ownerSaved: true,
ownerClass: '',
ownerRelation: '',
},
render: (args) => {
const { types, ownerSaved } = args;
delete args.ownerSaved;
delete args.hasLinks;

// `types` must be an array in args so controls can be used to toggle them.
// Because of that, we need to turn that back into the JSON object before
// passing that prop.
args.types = {};
types.sort((a, b) => linkTypes[a].priority - linkTypes[b].priority);
// eslint-disable-next-line no-restricted-syntax
for (const type of types) {
args.types[type] = linkTypes[type];
}

// Determine whether the link is rendered as though the parent record is saved or not
args.ownerID = ownerSaved ? 1 : 0;

return <LinkField {...args} />;
},
};
129 changes: 129 additions & 0 deletions client/src/components/LinkPicker/LinkPickerTitle-story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import React from 'react';
import LinkPickerTitle from 'components/LinkPicker/LinkPickerTitle';
import { LinkFieldContext } from '../LinkField/LinkField';

// // mock global ss config
// if (!window.ss) {
// window.ss = {};
// }
// if (!window.ss.config) {
// window.ss.config = {
// sections: [
// {
// name: 'SilverStripe\\LinkField\\Controllers\\LinkFieldController',
// form: {
// linkForm: {
// dataUrl: 'linkfield-endpoint',
// }
// }
// },
// ]
// };
// }

// mock toast actions
const mockedActions = {
toasts: {
error: (text) => console.error(text),
success: (text) => console.warn(text),
}
};

export default {
title: 'LinkField/LinkPicker/LinkPickerTitle',
component: LinkPickerTitle,
tags: ['autodocs'],
parameters: {
docs: {
description: {
component: 'The LinkPickerTitle component. Used to display a link inside the link field'
},
canvas: {
sourceState: 'shown',
},
controls: {
exclude: [
'id',
'onDelete',
'onClick',
'onUnpublishedVersionedState',
'isFirst',
'isLast',
'isSorting',
'canCreate',
],
},
},
},
argTypes: {
versionState: {
description: 'The current versioned state of the link. "unsaved" and "unversioned" are effectively identical.',
control: 'select',
options: ['unversioned', 'unsaved', 'published', 'draft', 'modified'],
},
title: {
description: 'The title (aka link text) for the link.',
},
typeTitle: {
description: 'Text that informs the user what type of link this is.',
},
description: {
description: 'The URL, or information about what the link is linking to.',
},
typeIcon: {
description: 'CSS class of an icon for this type of link (usually prefixed with "font-icon-"). See the Admin/Icons story for the full set of options.',
},
isMulti: {
description: 'Whether this link is inside a link field that supports multiple links or not.',
},
canDelete: {
description: 'Whether the current user has the permissions necessary to delete (or archive) this link.',
},
readonly: {
description: 'Whether the link field is readonly.',
},
disabled: {
description: 'Whether the link field is disabled.',
},
loading: {
description: 'Whether the link field is loading. This is passed as part of the context, not as a prop, but is here for demonstration purposes.',
},
},
};

export const _LinkPickerTitle = {
name: 'LinkPickerTitle',
args: {
id: 1,
title: 'Example link',
typeTitle: 'External URL',
description: 'https://www.example.com',
typeIcon: 'font-icon-external-link',
versionState: 'unversioned',
onDelete: () => {},
onClick: () => {},
onUnpublishedVersionedState: () => {},
isFirst: true,
isLast: true,
isMulti: false,
canCreate: true,
canDelete: true,
isSorting: false,
readonly: false,
disabled: false,
loading: false,
},
render: (args) => {
const providerArgs = {
ownerID: 1,
ownerClass: '',
ownerRelation: '',
actions: mockedActions,
loading: args.loading,
};
delete args.loading;
return <LinkFieldContext.Provider value={providerArgs}>
<LinkPickerTitle {...args} />
</LinkFieldContext.Provider>;
}
};

0 comments on commit b13bf3f

Please sign in to comment.