EditMusicAlbum.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import React from 'react';
  2. import { Button, Tab } from 'semantic-ui-react';
  3. import { Form, withFormik } from 'formik';
  4. import { History } from 'history';
  5. import { TxButton } from '@polkadot/joy-utils/react/components';
  6. import { onImageError } from '../common/images';
  7. import { ReorderableTracks } from './ReorderableTracks';
  8. import { MusicAlbumValidationSchema, MusicAlbumType, MusicAlbumClass as Fields, MusicAlbumFormValues, MusicAlbumToFormValues } from '../schemas/music/MusicAlbum';
  9. import { withMediaForm, MediaFormProps, datePlaceholder } from '../common/MediaForms';
  10. import EntityId from '@joystream/types/versioned-store/EntityId';
  11. import { MediaDropdownOptions } from '../common/MediaDropdownOptions';
  12. import { MusicTrackReaderPreviewProps } from './MusicTrackReaderPreview';
  13. import { FormTabs } from '../common/FormTabs';
  14. export type OuterProps = {
  15. history?: History;
  16. id?: EntityId;
  17. entity?: MusicAlbumType;
  18. tracks?: MusicTrackReaderPreviewProps[];
  19. opts?: MediaDropdownOptions;
  20. };
  21. type FormValues = MusicAlbumFormValues;
  22. const InnerForm = (props: MediaFormProps<OuterProps, FormValues>) => {
  23. const {
  24. // React components for form fields:
  25. MediaText,
  26. MediaDropdown,
  27. LabelledField,
  28. // Callbacks:
  29. onSubmit,
  30. onTxSuccess,
  31. onTxFailed,
  32. // history,
  33. entity,
  34. tracks = [],
  35. opts = MediaDropdownOptions.Empty,
  36. values,
  37. dirty,
  38. errors,
  39. isValid,
  40. isSubmitting,
  41. resetForm
  42. } = props;
  43. const { thumbnail } = values;
  44. const isNew = !entity;
  45. const buildTxParams = () => {
  46. if (!isValid) return [];
  47. return [];
  48. };
  49. const basicInfoTab = () => <Tab.Pane as='div'>
  50. <MediaText field={Fields.title} {...props} />
  51. <MediaText field={Fields.artist} {...props} />
  52. <MediaText field={Fields.thumbnail} {...props} />
  53. <MediaText field={Fields.description} textarea {...props} />
  54. <MediaText field={Fields.firstReleased} placeholder={datePlaceholder} {...props} />
  55. <MediaText field={Fields.explicit} {...props} />
  56. <MediaDropdown field={Fields.license} options={opts.contentLicenseOptions} {...props} />
  57. <MediaDropdown field={Fields.publicationStatus} options={opts.publicationStatusOptions} {...props} />
  58. </Tab.Pane>;
  59. const additionalTab = () => <Tab.Pane as='div'>
  60. <MediaText field={Fields.composerOrSongwriter} {...props} />
  61. <MediaDropdown field={Fields.genre} options={opts.musicGenreOptions} {...props} />
  62. <MediaDropdown field={Fields.mood} options={opts.musicMoodOptions} {...props} />
  63. <MediaDropdown field={Fields.theme} options={opts.musicThemeOptions} {...props} />
  64. <MediaDropdown field={Fields.language} options={opts.languageOptions} {...props} />
  65. <MediaText field={Fields.lyrics} {...props} />
  66. <MediaText field={Fields.attribution} {...props} />
  67. </Tab.Pane>;
  68. const tracksTab = () => <Tab.Pane as='div'>
  69. <ReorderableTracks
  70. tracks={tracks}
  71. noTracksView={<em style={{ padding: '1rem 0', display: 'block' }}>This album has no tracks yet.</em>}
  72. />
  73. </Tab.Pane>;
  74. const tabs = <FormTabs errors={errors} panes={[
  75. {
  76. id: 'Basic info',
  77. render: basicInfoTab,
  78. fields: [
  79. Fields.title,
  80. Fields.artist,
  81. Fields.thumbnail,
  82. Fields.description,
  83. Fields.firstReleased,
  84. Fields.explicit,
  85. Fields.license,
  86. Fields.publicationStatus
  87. ]
  88. },
  89. {
  90. id: 'Additional',
  91. render: additionalTab,
  92. fields: [
  93. Fields.composerOrSongwriter,
  94. Fields.genre,
  95. Fields.mood,
  96. Fields.theme,
  97. Fields.language,
  98. Fields.lyrics,
  99. Fields.attribution
  100. ]
  101. },
  102. {
  103. id: `Tracks (${tracks.length})`,
  104. render: tracksTab
  105. }
  106. ]} />;
  107. const renderMainButton = () =>
  108. <TxButton
  109. type='submit'
  110. isDisabled={!dirty || isSubmitting}
  111. label={isNew
  112. ? 'Publish'
  113. : 'Update'
  114. }
  115. params={buildTxParams()}
  116. tx={isNew
  117. ? 'dataDirectory.addMetadata'
  118. : 'dataDirectory.updateMetadata'
  119. }
  120. onClick={onSubmit}
  121. txFailedCb={onTxFailed}
  122. txSuccessCb={onTxSuccess}
  123. />;
  124. return <div className='EditMetaBox'>
  125. <div className='EditMetaThumb'>
  126. {thumbnail && <img src={thumbnail} onError={onImageError} />}
  127. </div>
  128. <Form className='ui form JoyForm EditMetaForm'>
  129. {tabs}
  130. <LabelledField style={{ marginTop: '1rem' }} {...props} flex>
  131. {renderMainButton()}
  132. <Button
  133. type='button'
  134. size='large'
  135. disabled={!dirty || isSubmitting}
  136. onClick={() => resetForm()}
  137. content='Reset form'
  138. />
  139. </LabelledField>
  140. </Form>
  141. </div>;
  142. };
  143. export const EditForm = withFormik<OuterProps, FormValues>({
  144. // Transform outer props into form values
  145. mapPropsToValues: (props): FormValues => {
  146. const { entity } = props;
  147. return MusicAlbumToFormValues(entity);
  148. },
  149. validationSchema: MusicAlbumValidationSchema,
  150. handleSubmit: () => {
  151. // do submitting things
  152. }
  153. })(withMediaForm(InnerForm) as any);
  154. export default EditForm;