EditPageContent.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // EDIT CUSTOM DETAILS ON YOUR PAGE
  2. import React, { useState, useEffect, useContext } from 'react';
  3. import { Typography, Button } from 'antd';
  4. import CodeMirror from '@uiw/react-codemirror';
  5. import { bbedit } from '@uiw/codemirror-theme-bbedit';
  6. import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
  7. import { languages } from '@codemirror/language-data';
  8. import { ServerStatusContext } from '../../../../utils/server-status-context';
  9. import {
  10. postConfigUpdateToAPI,
  11. RESET_TIMEOUT,
  12. API_CUSTOM_CONTENT,
  13. } from '../../../../utils/config-constants';
  14. import {
  15. createInputStatus,
  16. StatusState,
  17. STATUS_ERROR,
  18. STATUS_PROCESSING,
  19. STATUS_SUCCESS,
  20. } from '../../../../utils/input-statuses';
  21. import { FormStatusIndicator } from '../../FormStatusIndicator';
  22. const { Title } = Typography;
  23. // eslint-disable-next-line react/function-component-definition
  24. export default function EditPageContent() {
  25. const [content, setContent] = useState('');
  26. const [submitStatus, setSubmitStatus] = useState<StatusState>(null);
  27. const [hasChanged, setHasChanged] = useState(false);
  28. const serverStatusData = useContext(ServerStatusContext);
  29. const { serverConfig, setFieldInConfigState } = serverStatusData || {};
  30. const { instanceDetails } = serverConfig;
  31. const { extraPageContent: initialContent } = instanceDetails;
  32. let resetTimer = null;
  33. function handleEditorChange(text) {
  34. setContent(text);
  35. if (text !== initialContent && !hasChanged) {
  36. setHasChanged(true);
  37. } else if (text === initialContent && hasChanged) {
  38. setHasChanged(false);
  39. }
  40. }
  41. // Clear out any validation states and messaging
  42. const resetStates = () => {
  43. setSubmitStatus(null);
  44. setHasChanged(false);
  45. clearTimeout(resetTimer);
  46. resetTimer = null;
  47. };
  48. // posts all the tags at once as an array obj
  49. async function handleSave() {
  50. setSubmitStatus(createInputStatus(STATUS_PROCESSING));
  51. await postConfigUpdateToAPI({
  52. apiPath: API_CUSTOM_CONTENT,
  53. data: { value: content },
  54. onSuccess: (message: string) => {
  55. setFieldInConfigState({
  56. fieldName: 'extraPageContent',
  57. value: content,
  58. path: 'instanceDetails',
  59. });
  60. setSubmitStatus(createInputStatus(STATUS_SUCCESS, message));
  61. },
  62. onError: (message: string) => {
  63. setSubmitStatus(createInputStatus(STATUS_ERROR, message));
  64. },
  65. });
  66. resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
  67. }
  68. useEffect(() => {
  69. setContent(initialContent);
  70. }, [instanceDetails]);
  71. return (
  72. <div className="edit-page-content">
  73. <Title level={3} className="section-title">
  74. Custom Page Content
  75. </Title>
  76. <p className="description">
  77. Edit the content of your page by using simple{' '}
  78. <a
  79. href="https://www.markdownguide.org/basic-syntax/"
  80. target="_blank"
  81. rel="noopener noreferrer"
  82. >
  83. Markdown syntax
  84. </a>
  85. .
  86. </p>
  87. <CodeMirror
  88. value={content}
  89. placeholder="Enter your custom page content here..."
  90. theme={bbedit}
  91. height="200px"
  92. onChange={handleEditorChange}
  93. extensions={[markdown({ base: markdownLanguage, codeLanguages: languages })]}
  94. />
  95. <br />
  96. <div className="page-content-actions">
  97. {hasChanged && (
  98. <Button type="primary" onClick={handleSave}>
  99. Save
  100. </Button>
  101. )}
  102. <FormStatusIndicator status={submitStatus} />
  103. </div>
  104. </div>
  105. );
  106. }