PluginProbe
Code Snippets / 3.9.6
Code Snippets v3.9.6
4.0.0-beta.2 3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 All 65 releases
code-snippets / js / components / SnippetForm / SnippetForm.tsx

SnippetForm.tsx in Code Snippets 3.9.6, at js/components/SnippetForm/SnippetForm.tsx

193 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import React, { useState } from 'react'
2 import classnames from 'classnames'
3 import { __ } from '@wordpress/i18n'
4 import { addQueryArgs } from '@wordpress/url'
5 import { WithRestAPIContext } from '../../hooks/useRestAPI'
6 import { WithSnippetsListContext, useSnippetsList } from '../../hooks/useSnippetsList'
7 import { SubmitSnippetAction, useSubmitSnippet } from '../../hooks/useSubmitSnippet'
8 import { handleUnknownError } from '../../utils/errors'
9 import { createSnippetObject, getSnippetType, isCondition, validateSnippet } from '../../utils/snippets/snippets'
10 import { WithSnippetFormContext, useSnippetForm } from '../../hooks/useSnippetForm'
11 import { ConfirmDialog } from '../common/ConfirmDialog'
12 import { UpsellDialog } from '../common/UpsellDialog'
13 import { EditorSidebar } from '../EditorSidebar'
14 import { UpsellBanner } from '../common/UpsellBanner'
15 import { SnippetTypeInput } from './fields/SnippetTypeInput'
16 import { TagsEditor } from './fields/TagsEditor'
17 import { CodeEditor } from './fields/CodeEditor'
18 import { DescriptionEditor } from './fields/DescriptionEditor'
19 import { NameInput } from './fields/NameInput'
20 import { PageHeading } from './page/PageHeading'
21 import type { PropsWithChildren } from 'react'
22 import type { Snippet } from '../../types/Snippet'
23
24 const editFormClassName = ({ snippet, isReadOnly, isExpanded }: {
25 snippet: Snippet,
26 isReadOnly: boolean,
27 isExpanded: boolean
28 }) =>
29 classnames(
30 'snippet-form',
31 isExpanded ? 'snippet-form-expanded' : 'snippet-form-collapsed',
32 `${snippet.scope}-snippet`,
33 `${getSnippetType(snippet)}-snippet`,
34 `${snippet.id ? 'saved' : 'new'}-snippet`,
35 `${snippet.active ? 'active' : 'inactive'}-snippet`,
36 {
37 'erroneous-snippet': !!snippet.code_error,
38 'read-only-snippet': isReadOnly
39 }
40 )
41
42 interface ConfirmSubmitDialogProps {
43 doSubmit: (action: SubmitSnippetAction | undefined) => void
44 submitAction: SubmitSnippetAction | undefined
45 setSubmitAction: (action: SubmitSnippetAction | undefined) => void
46 validationWarning: string | undefined
47 setValidationWarning: (warning: string | undefined) => void
48 }
49
50 const ConfirmSubmitDialog: React.FC<ConfirmSubmitDialogProps> = ({
51 doSubmit,
52 submitAction,
53 setSubmitAction,
54 validationWarning,
55 setValidationWarning
56 }) =>
57 <ConfirmDialog
58 open={validationWarning !== undefined}
59 title={__('Snippet incomplete', 'code-snippets')}
60 confirmLabel={__('Continue', 'code-snippets')}
61 onCancel={() => {
62 setSubmitAction(undefined)
63 setValidationWarning(undefined)
64 }}
65 onConfirm={() => {
66 doSubmit(submitAction)
67 setSubmitAction(undefined)
68 setValidationWarning(undefined)
69 }}
70 >
71 <p>{`${validationWarning} ${__('Continue?', 'code-snippets')}`}</p>
72 </ConfirmDialog>
73
74 interface EditFormProps extends PropsWithChildren {
75 className?: string
76 }
77
78 const EditForm: React.FC<EditFormProps> = ({ children, className }) => {
79 const { submitSnippet } = useSubmitSnippet()
80 const { snippet } = useSnippetForm()
81 const { refreshSnippetsList } = useSnippetsList()
82
83 const [validationWarning, setValidationWarning] = useState<string | undefined>()
84 const [submitAction, setSubmitAction] = useState<SubmitSnippetAction | undefined>()
85
86 const doSubmit = (action?: SubmitSnippetAction) => {
87 submitSnippet(action)
88 .then(response => {
89 if (response && 0 !== response.id && window.CODE_SNIPPETS) {
90 if (window.location.href.toString().includes(window.CODE_SNIPPETS.urls.addNew)) {
91 document.title = document.title
92 .replace(__('Add New Snippet', 'code-snippets'), __('Edit Snippet', 'code-snippets'))
93 .replace(__('Add New Condition', 'code-snippets'), __('Edit Condition', 'code-snippets'))
94
95 const newUrl = addQueryArgs(window.CODE_SNIPPETS.urls.edit, { id: response.id })
96 window.history.pushState({}, document.title, newUrl)
97 }
98 }
99 })
100 .then(refreshSnippetsList)
101 .catch(handleUnknownError)
102 }
103
104 const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
105 event.preventDefault()
106
107 const action = Object.values(SubmitSnippetAction).find(actionName =>
108 actionName === document.activeElement?.getAttribute('name'))
109
110 const validationWarning = validateSnippet(snippet)
111
112 if (validationWarning) {
113 setValidationWarning(validationWarning)
114 setSubmitAction(action)
115 } else {
116 doSubmit(action)
117 }
118 }
119
120 return (
121 <>
122 <form id="snippet-form" method="post" onSubmit={handleSubmit} className={className}>
123 {children}
124 </form>
125
126 <ConfirmSubmitDialog {...{ doSubmit, submitAction, setSubmitAction, validationWarning, setValidationWarning }} />
127 </>
128 )
129 }
130
131 const ConditionsEditor: React.FC = () => {
132 const { snippet } = useSnippetForm()
133
134 return isCondition(snippet)
135 ? <div id="snippet_conditions" className="snippet-condition-editor-container">
136 <p>{__('This snippet type is not supported in this version of Code Snippets.')}</p>
137 </div>
138 : null
139 }
140
141 const EditFormWrap: React.FC = () => {
142 const { snippet, isReadOnly } = useSnippetForm()
143 const [isExpanded, setIsExpanded] = useState(false)
144 const [isUpgradeDialogOpen, setIsUpgradeDialogOpen] = useState(false)
145
146 return (
147 <div className="wrap">
148 <p><small className="cs-back">
149 {isCondition(snippet)
150 ? <a href={addQueryArgs(window.CODE_SNIPPETS?.urls.manage, { type: 'cond' })}>
151 {__('Back to all conditions', 'code-snippets')}
152 </a>
153 : <a href={window.CODE_SNIPPETS?.urls.manage}>
154 {__('Back to all snippets', 'code-snippets')}
155 </a>}
156 </small></p>
157
158 <PageHeading />
159
160 <EditForm className={editFormClassName({ snippet, isReadOnly, isExpanded })}>
161 <main className="snippet-form-upper">
162 <div className="snippet-name-wrapper">
163 <NameInput />
164 <SnippetTypeInput setIsUpgradeDialogOpen={setIsUpgradeDialogOpen} />
165 </div>
166
167 <CodeEditor {...{ isExpanded, setIsExpanded }} />
168 <ConditionsEditor />
169 </main>
170
171 <div className="snippet-form-lower">
172 <UpsellBanner />
173 <DescriptionEditor />
174 <TagsEditor />
175 </div>
176
177 <EditorSidebar setIsUpgradeDialogOpen={setIsUpgradeDialogOpen} />
178 </EditForm>
179
180 <UpsellDialog isOpen={isUpgradeDialogOpen} setIsOpen={setIsUpgradeDialogOpen} />
181 </div>
182 )
183 }
184
185 export const SnippetForm: React.FC = () =>
186 <WithRestAPIContext>
187 <WithSnippetsListContext>
188 <WithSnippetFormContext initialSnippet={() => createSnippetObject(window.CODE_SNIPPETS_EDIT?.snippet)}>
189 <EditFormWrap />
190 </WithSnippetFormContext>
191 </WithSnippetsListContext>
192 </WithRestAPIContext>
193