datocms-plugin-netlify-forms 0.0.2 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/build/asset-manifest.json +23 -0
- package/build/index.html +1 -0
- package/{public → build}/robots.txt +0 -0
- package/build/static/css/2.6844907f.chunk.css +2 -0
- package/build/static/css/2.6844907f.chunk.css.map +1 -0
- package/build/static/css/main.f2605287.chunk.css +2 -0
- package/build/static/css/main.f2605287.chunk.css.map +1 -0
- package/build/static/js/2.38b96e8c.chunk.js +3 -0
- package/build/static/js/2.38b96e8c.chunk.js.LICENSE.txt +56 -0
- package/build/static/js/2.38b96e8c.chunk.js.map +1 -0
- package/build/static/js/main.368140bd.chunk.js +2 -0
- package/build/static/js/main.368140bd.chunk.js.map +1 -0
- package/build/static/js/runtime-main.bfdb9e12.js +2 -0
- package/build/static/js/runtime-main.bfdb9e12.js.map +1 -0
- package/package.json +7 -3
- package/public/index.html +0 -11
- package/src/entrypoints/ConfigScreen.tsx +0 -133
- package/src/entrypoints/styles.module.css +0 -3
- package/src/index.tsx +0 -41
- package/src/modals/ShowSubmissionModal.tsx +0 -37
- package/src/pages/SubmissionsPage.tsx +0 -182
- package/src/react-app-env.d.ts +0 -1
- package/src/utils/render.tsx +0 -6
- package/tsconfig.json +0 -26
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(this["webpackJsonpdatocms-plugin-netlify-forms"]=this["webpackJsonpdatocms-plugin-netlify-forms"]||[]).push([[0],{34:function(e,t,n){e.exports={row:"SubmissionsPage_row__17uQG",rowHeader:"SubmissionsPage_rowHeader__3GgEA"}},35:function(e,t,n){e.exports={item:"ShowSubmissionModal_item__3iBzF",itemTitle:"ShowSubmissionModal_itemTitle__3n6id"}},66:function(e,t,n){"use strict";n.r(t);var r=n(76),i=n(0),s=n(8),a=n.n(s),c=n(2);function o(e){a.a.render(Object(c.jsx)(i.StrictMode,{children:e}),document.getElementById("root"))}var u=n(31),l=n(7),d=n.n(l),h=n(9),b=n(3),j=n(77),f=n(68),p=n(69),m=n(78),x=n(75),v=n(73),O=n(24);function g(e){var t=e.ctx,n=t.plugin.attributes.parameters.accessToken,r=Object(i.useState)([]),s=Object(b.a)(r,2),a=s[0],o=s[1];return Object(i.useEffect)((function(){if(n){o([]);var e=function(){var e=Object(h.a)(d.a.mark((function e(){var r,i,s;return d.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,window.fetch("https://api.netlify.com/api/v1/sites/",{method:"GET",headers:{Authorization:"Bearer ".concat(n)}});case 2:return(r=e.sent).ok||(i="An error has occured: ".concat(r.status),t.alert(i)),e.next=6,r.json();case 6:s=e.sent,o(s);case 8:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}();e()}}),[t,n]),Object(c.jsx)(j.a,{ctx:t,children:Object(c.jsx)(O.b,{initialValues:t.plugin.attributes.parameters,validate:function(e){var t={};return e.accessToken||(t.accessToken="This field is required!"),t},onSubmit:function(){var e=Object(h.a)(d.a.mark((function e(r){return d.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r.accessToken!==n&&o([]),e.next=3,t.updatePluginParameters(r);case 3:t.notice("Settings updated successfully!");case 4:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),children:function(e){var t=e.handleSubmit,r=e.submitting,i=e.dirty;return Object(c.jsxs)(f.a,{onSubmit:t,children:[Object(c.jsxs)(p.a,{children:[Object(c.jsx)(O.a,{name:"accessToken",children:function(e){var t=e.input,n=e.meta.error;return Object(c.jsx)(m.a,Object(u.a)({id:"accessToken",label:"Access token",hint:Object(c.jsxs)(c.Fragment,{children:["You can generate a"," ",Object(c.jsx)("a",{target:"_blank",rel:"noreferrer",href:"https://app.netlify.com/user/applications#personal-access-tokens",children:"personal access token"})," ","in your Netlify user settings."]}),required:!0,error:n},t))}}),a.length>0?Object(c.jsx)(O.a,{name:"site",children:function(e){var t=e.input,n=e.meta.error;return Object(c.jsx)(x.a,Object(u.a)({id:"site",label:"Site",error:n,selectInputProps:{options:a.map((function(e){return{label:e.name,value:e.site_id}}))}},t))}}):null]}),Object(c.jsx)(v.a,{type:"submit",fullWidth:!0,buttonSize:"l",buttonType:"primary",disabled:r||!i,children:n?"Save settings":"Connect"})]})}})})}n(60);var w=n(74),y=n(34),S=n.n(y);function k(e){var t=e.ctx,n=t.plugin.attributes.parameters,r=n.site,s=n.accessToken,a=Object(i.useState)([]),o=Object(b.a)(a,2),u=o[0],l=o[1],f=Object(i.useState)(!1),p=Object(b.a)(f,2),m=p[0],x=p[1];Object(i.useEffect)((function(){if(s&&r){var e=function(){var e=Object(h.a)(d.a.mark((function e(){var n,i,a;return d.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return x(!0),e.next=3,window.fetch("https://api.netlify.com/api/v1/sites/".concat(r.value,"/submissions"),{method:"GET",headers:{Authorization:"Bearer ".concat(s)}});case 3:return n=e.sent,x(!1),n.ok||(i="An error has occured: ".concat(n.status),t.alert(i)),e.next=8,n.json();case 8:a=e.sent,l(a);case 10:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}();e()}}),[r,s,t]);var O=function(){var e=Object(h.a)(d.a.mark((function e(n){var r;return d.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t.openModal({id:"showSubmission",title:"Submission (".concat(n.id,")"),width:"l",parameters:n});case 2:r=e.sent,t.notice(r);case 4:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),g=function(){var e=Object(h.a)(d.a.mark((function e(n){var r;return d.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t.openConfirm({title:"Delete record?",content:"Are you sure you want to delete this record? This operation is not reversible!",choices:[{label:"Yes, delete this record",value:"negative",intent:"negative"}],cancel:{label:"Cancel",value:!1}});case 2:if(!e.sent){e.next=8;break}return e.next=6,window.fetch("https://api.netlify.com/api/v1/submissions/".concat(n.id),{method:"DELETE",headers:{Authorization:"Bearer ".concat(s)}});case 6:(r=e.sent).ok?(l(u.filter((function(e){return e.id!==n.id}))),t.notice("Record successfully removed")):t.alert("An error has occured: ".concat(r.status));case 8:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}();return Object(c.jsx)(j.a,{ctx:t,children:Object(c.jsxs)("div",{style:{paddingTop:"var(--spacing-l)",paddingLeft:"var(--spacing-xxl)",paddingRight:"var(--spacing-xxl)"},children:[Object(c.jsx)("h1",{style:{fontWeight:500},children:"Form submissions"}),Object(c.jsxs)("div",{children:[Object(c.jsxs)("div",{className:S.a.rowHeader,children:[Object(c.jsx)("div",{style:{width:"25%"},children:"Name"}),Object(c.jsx)("div",{style:{width:"25%"},children:"Form"}),Object(c.jsx)("div",{style:{width:"25%"},children:"Date"}),Object(c.jsx)("div",{style:{width:"25%"}})]}),m?Object(c.jsx)("div",{style:{height:"200px",position:"relative"},children:Object(c.jsx)(w.a,{size:48,placement:"centered"})}):u.map((function(e){return Object(c.jsxs)("div",{className:S.a.row,children:[Object(c.jsx)("div",{style:{width:"25%"},children:e.name}),Object(c.jsx)("div",{style:{width:"25%"},children:e.form_name}),Object(c.jsx)("div",{style:{width:"25%",flexGrow:0},children:new Intl.DateTimeFormat("en-US").format(new Date(e.created_at))}),Object(c.jsxs)("div",{style:{width:"25%",textAlign:"right"},children:[Object(c.jsx)(v.a,{buttonSize:"xs",type:"button",onClick:function(){return O(e)},style:{marginRight:"var(--spacing-m)"},children:"Show"}),Object(c.jsx)(v.a,{buttonSize:"xs",type:"reset",buttonType:"negative",onClick:function(){return g(e)},children:"Delete"})]})]},e.id)}))]})]})})}var T=n(35),_=n.n(T);function A(e){var t=e.ctx,n=t.parameters.ordered_human_fields;return Object(c.jsx)(j.a,{ctx:t,children:n.length>0?n.map((function(e){return Object(c.jsxs)("div",{className:_.a.item,children:[Object(c.jsx)("div",{className:_.a.itemTitle,children:e.title}),Object(c.jsx)("div",{children:e.value})]},e.title)})):Object(c.jsx)("span",{children:"No form fields found!"})})}Object(r.a)({renderConfigScreen:function(e){return o(Object(c.jsx)(g,{ctx:e}))},mainNavigationTabs:function(e){return[{label:"Netlify Forms",icon:"file-signature",pointsTo:{pageId:"form-submissions"},placement:["before","settings"]}]},renderPage:function(e,t){if("form-submissions"===e)return o(Object(c.jsx)(k,{ctx:t}))},renderModal:function(e,t){if("showSubmission"===e)return o(Object(c.jsx)(A,{ctx:t}))}})}},[[66,1,2]]]);
|
|
2
|
+
//# sourceMappingURL=main.368140bd.chunk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["pages/SubmissionsPage.module.css","modals/ShowSubmissionModal.module.css","utils/render.tsx","entrypoints/ConfigScreen.tsx","pages/SubmissionsPage.tsx","modals/ShowSubmissionModal.tsx","index.tsx"],"names":["module","exports","render","component","ReactDOM","document","getElementById","ConfigScreen","ctx","accessToken","plugin","attributes","parameters","useState","sites","setSites","useEffect","getSites","a","window","fetch","method","headers","Authorization","response","ok","message","status","alert","json","Canvas","initialValues","validate","values","errors","onSubmit","updatePluginParameters","notice","handleSubmit","submitting","dirty","Form","FieldGroup","name","input","error","meta","TextField","id","label","hint","target","rel","href","required","length","SelectField","selectInputProps","options","map","site","value","site_id","Button","type","fullWidth","buttonSize","buttonType","disabled","SubmissionsPage","submissions","setSubmissions","loading","setLoading","getSubmissions","forms","handleShowSubmissionModal","submission","openModal","title","width","result","handleOpenDeleteSubmissonModal","openConfirm","content","choices","intent","cancel","filter","item","style","paddingTop","paddingLeft","paddingRight","fontWeight","className","styles","rowHeader","height","position","Spinner","size","placement","row","form_name","flexGrow","Intl","DateTimeFormat","format","Date","created_at","textAlign","onClick","marginRight","ShowSubmissionModal","fields","ordered_human_fields","itemTitle","connect","renderConfigScreen","mainNavigationTabs","icon","pointsTo","pageId","renderPage","renderModal","modalId"],"mappings":"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","file":"static/js/main.368140bd.chunk.js","sourcesContent":["// extracted by mini-css-extract-plugin\nmodule.exports = {\"row\":\"SubmissionsPage_row__17uQG\",\"rowHeader\":\"SubmissionsPage_rowHeader__3GgEA\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"item\":\"ShowSubmissionModal_item__3iBzF\",\"itemTitle\":\"ShowSubmissionModal_itemTitle__3n6id\"};","import React, { StrictMode } from 'react';\nimport ReactDOM from 'react-dom';\n\nexport function render(component: React.ReactNode): void {\n ReactDOM.render(<StrictMode>{component}</StrictMode>, document.getElementById('root'));\n}\n","import { RenderConfigScreenCtx } from \"datocms-plugin-sdk\";\nimport {\n Button,\n Canvas,\n TextField,\n Form,\n FieldGroup,\n SelectField,\n} from \"datocms-react-ui\";\nimport { useEffect, useState } from \"react\";\nimport { Form as FormHandler, Field } from \"react-final-form\";\n\ntype PropTypes = {\n ctx: RenderConfigScreenCtx;\n};\n\nexport type ValidParameters = {\n accessToken: string;\n site: { label: string; value: string };\n};\n\ntype Parameters = ValidParameters;\n\nexport default function ConfigScreen({ ctx }: PropTypes) {\n const parameters = ctx.plugin.attributes.parameters;\n const accessToken = parameters.accessToken;\n const [sites, setSites] = useState([]);\n\n useEffect(() => {\n if (accessToken) {\n setSites([]);\n const getSites = async () => {\n const response = await window.fetch(\n \"https://api.netlify.com/api/v1/sites/\",\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n }\n );\n\n if (!response.ok) {\n const message = `An error has occured: ${response.status}`;\n ctx.alert(message);\n }\n\n const sites = await response.json();\n setSites(sites);\n };\n\n getSites();\n }\n }, [ctx, accessToken]);\n\n return (\n <Canvas ctx={ctx}>\n <FormHandler<Parameters>\n initialValues={ctx.plugin.attributes.parameters}\n validate={(values) => {\n const errors: Record<string, string> = {};\n if (!values.accessToken) {\n errors.accessToken = \"This field is required!\";\n }\n return errors;\n }}\n onSubmit={async (values) => {\n if (values.accessToken !== accessToken) {\n setSites([]);\n }\n\n await ctx.updatePluginParameters(values);\n ctx.notice(\"Settings updated successfully!\");\n }}\n >\n {({ handleSubmit, submitting, dirty }) => (\n <Form onSubmit={handleSubmit}>\n <FieldGroup>\n <Field name=\"accessToken\">\n {({ input, meta: { error } }) => (\n <TextField\n id=\"accessToken\"\n label=\"Access token\"\n hint={\n <>\n You can generate a{\" \"}\n <a\n target=\"_blank\"\n rel=\"noreferrer\"\n href=\"https://app.netlify.com/user/applications#personal-access-tokens\"\n >\n personal access token\n </a>{\" \"}\n in your Netlify user settings.\n </>\n }\n required\n error={error}\n {...input}\n />\n )}\n </Field>\n\n {sites.length > 0 ? (\n <Field name=\"site\">\n {({ input, meta: { error } }) => (\n <SelectField\n id=\"site\"\n label=\"Site\"\n error={error}\n selectInputProps={{\n options: sites.map((site: any) => ({\n label: site.name,\n value: site.site_id,\n })),\n }}\n {...input}\n />\n )}\n </Field>\n ) : null}\n </FieldGroup>\n <Button\n type=\"submit\"\n fullWidth\n buttonSize=\"l\"\n buttonType=\"primary\"\n disabled={submitting || !dirty}\n >\n {!accessToken ? \"Connect\" : \"Save settings\"}\n </Button>\n </Form>\n )}\n </FormHandler>\n </Canvas>\n );\n}\n","import { RenderPageCtx } from \"datocms-plugin-sdk\";\nimport { Button, Canvas, Spinner } from \"datocms-react-ui\";\nimport { useEffect, useState } from \"react\";\nimport { ValidParameters } from \"../entrypoints/ConfigScreen\";\nimport styles from \"./SubmissionsPage.module.css\";\n\ntype PropTypes = {\n ctx: RenderPageCtx;\n};\n\nexport default function SubmissionsPage({ ctx }: PropTypes) {\n const parameters = ctx.plugin.attributes.parameters as ValidParameters;\n const site = parameters.site;\n const accessToken = parameters.accessToken;\n\n const [submissions, setSubmissions] = useState([]);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n if (accessToken && site) {\n const getSubmissions = async () => {\n setLoading(true);\n const response = await window.fetch(\n `https://api.netlify.com/api/v1/sites/${site.value}/submissions`,\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n }\n );\n\n setLoading(false);\n\n if (!response.ok) {\n const message = `An error has occured: ${response.status}`;\n ctx.alert(message);\n }\n\n const forms = await response.json();\n setSubmissions(forms);\n };\n\n getSubmissions();\n }\n }, [site, accessToken, ctx]);\n\n const handleShowSubmissionModal = async (submission: any) => {\n const result: any = await ctx.openModal({\n id: \"showSubmission\",\n title: `Submission (${submission.id})`,\n width: \"l\",\n parameters: submission,\n });\n\n ctx.notice(result);\n };\n\n const handleOpenDeleteSubmissonModal = async (submission: any) => {\n const result: any = await ctx.openConfirm({\n title: \"Delete record?\",\n content:\n \"Are you sure you want to delete this record? This operation is not reversible!\",\n choices: [\n {\n label: \"Yes, delete this record\",\n value: \"negative\",\n intent: \"negative\",\n },\n ],\n cancel: {\n label: \"Cancel\",\n value: false,\n },\n });\n\n if (result) {\n const response = await window.fetch(\n `https://api.netlify.com/api/v1/submissions/${submission.id}`,\n {\n method: \"DELETE\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n }\n );\n\n if (!response.ok) {\n ctx.alert(`An error has occured: ${response.status}`);\n } else {\n setSubmissions(\n submissions.filter((item: any) => item.id !== submission.id)\n );\n ctx.notice(\"Record successfully removed\");\n }\n }\n };\n\n return (\n <Canvas ctx={ctx}>\n <div\n style={{\n paddingTop: \"var(--spacing-l)\",\n paddingLeft: \"var(--spacing-xxl)\",\n paddingRight: \"var(--spacing-xxl)\",\n }}\n >\n <h1 style={{ fontWeight: 500 }}>Form submissions</h1>\n <div>\n <div className={styles.rowHeader}>\n <div style={{ width: \"25%\" }}>Name</div>\n <div style={{ width: \"25%\" }}>Form</div>\n <div style={{ width: \"25%\" }}>Date</div>\n <div style={{ width: \"25%\" }}></div>\n </div>\n\n {loading ? (\n <div style={{ height: \"200px\", position: \"relative\" }}>\n <Spinner size={48} placement=\"centered\" />\n </div>\n ) : (\n submissions.map((item: any) => (\n <div key={item.id} className={styles.row}>\n <div style={{ width: \"25%\" }}>{item.name}</div>\n <div style={{ width: \"25%\" }}>{item.form_name}</div>\n <div style={{ width: \"25%\", flexGrow: 0 }}>\n {new Intl.DateTimeFormat(\"en-US\").format(\n new Date(item.created_at)\n )}\n </div>\n <div style={{ width: \"25%\", textAlign: \"right\" }}>\n <Button\n buttonSize=\"xs\"\n type=\"button\"\n onClick={() => handleShowSubmissionModal(item)}\n style={{ marginRight: \"var(--spacing-m)\" }}\n >\n Show\n </Button>\n <Button\n buttonSize=\"xs\"\n type=\"reset\"\n buttonType=\"negative\"\n onClick={() => handleOpenDeleteSubmissonModal(item)}\n >\n Delete\n </Button>\n </div>\n </div>\n ))\n )}\n\n {}\n </div>\n </div>\n </Canvas>\n );\n}\n","import { RenderModalCtx } from \"datocms-plugin-sdk\";\nimport { Canvas } from \"datocms-react-ui\";\n\nimport styles from \"./ShowSubmissionModal.module.css\";\n\ntype PropTypes = {\n ctx: RenderModalCtx;\n};\n\nexport default function ShowSubmissionModal({ ctx }: PropTypes) {\n const fields = ctx.parameters.ordered_human_fields as any;\n\n return (\n <Canvas ctx={ctx}>\n {fields.length > 0 ? (\n fields.map((item: any) => (\n <div key={item.title} className={styles.item}>\n <div className={styles.itemTitle}>{item.title}</div>\n <div>{item.value}</div>\n </div>\n ))\n ) : (\n <span>No form fields found!</span>\n )}\n </Canvas>\n );\n}\n","import {\n connect,\n IntentCtx,\n RenderModalCtx,\n RenderPageCtx,\n} from \"datocms-plugin-sdk\";\nimport { render } from \"./utils/render\";\nimport ConfigScreen from \"./entrypoints/ConfigScreen\";\nimport \"datocms-react-ui/styles.css\";\nimport SubmissionsPage from \"./pages/SubmissionsPage\";\nimport ShowSubmissionModal from \"./modals/ShowSubmissionModal\";\n\nconnect({\n renderConfigScreen(ctx) {\n return render(<ConfigScreen ctx={ctx} />);\n },\n mainNavigationTabs(ctx: IntentCtx) {\n return [\n {\n label: \"Netlify Forms\",\n icon: \"file-signature\",\n pointsTo: {\n pageId: \"form-submissions\",\n },\n placement: [\"before\", \"settings\"],\n },\n ];\n },\n renderPage(pageId, ctx: RenderPageCtx) {\n switch (pageId) {\n case \"form-submissions\":\n return render(<SubmissionsPage ctx={ctx} />);\n }\n },\n renderModal(modalId: string, ctx: RenderModalCtx) {\n switch (modalId) {\n case \"showSubmission\":\n return render(<ShowSubmissionModal ctx={ctx} />);\n }\n },\n});\n"],"sourceRoot":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(e){function t(t){for(var n,l,f=t[0],i=t[1],a=t[2],c=0,s=[];c<f.length;c++)l=f[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n]);for(p&&p(t);s.length;)s.shift()();return u.push.apply(u,a||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,f=1;f<r.length;f++){var i=r[f];0!==o[i]&&(n=!1)}n&&(u.splice(t--,1),e=l(l.s=r[0]))}return e}var n={},o={1:0},u=[];function l(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,l),r.l=!0,r.exports}l.m=e,l.c=n,l.d=function(e,t,r){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},l.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,t){if(1&t&&(e=l(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(l.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)l.d(r,n,function(t){return e[t]}.bind(null,n));return r},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="./";var f=this["webpackJsonpdatocms-plugin-netlify-forms"]=this["webpackJsonpdatocms-plugin-netlify-forms"]||[],i=f.push.bind(f);f.push=t,f=f.slice();for(var a=0;a<f.length;a++)t(f[a]);var p=i;r()}([]);
|
|
2
|
+
//# sourceMappingURL=runtime-main.bfdb9e12.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../webpack/bootstrap"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","this","oldJsonpFunction","slice"],"mappings":"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","file":"static/js/runtime-main.bfdb9e12.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t1: 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"./\";\n\n \tvar jsonpArray = this[\"webpackJsonpdatocms-plugin-netlify-forms\"] = this[\"webpackJsonpdatocms-plugin-netlify-forms\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// run deferred modules from other chunks\n \tcheckDeferredModules();\n"],"sourceRoot":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datocms-plugin-netlify-forms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Plugin that allows DatoCMS show and manage Netlify form submissions",
|
|
5
5
|
"homepage": "https://github.com/gempi/datocms-plugin-netlify-forms#readme",
|
|
6
6
|
"author": "Matthias Gemperli <hello@matthiasgemperli.ch>",
|
|
@@ -10,10 +10,14 @@
|
|
|
10
10
|
"datocms-plugin",
|
|
11
11
|
"netlify"
|
|
12
12
|
],
|
|
13
|
+
"files": [
|
|
14
|
+
"docs",
|
|
15
|
+
"build"
|
|
16
|
+
],
|
|
13
17
|
"datoCmsPlugin": {
|
|
14
|
-
"title": "Netlify
|
|
18
|
+
"title": "Netlify Forms",
|
|
15
19
|
"coverImage": "docs/cover.png",
|
|
16
|
-
"previewImage": "docs/
|
|
20
|
+
"previewImage": "docs/demo.gif",
|
|
17
21
|
"entryPoint": "build/index.html",
|
|
18
22
|
"permissions": []
|
|
19
23
|
},
|
package/public/index.html
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
-
</head>
|
|
7
|
-
<body>
|
|
8
|
-
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
9
|
-
<div id="root"></div>
|
|
10
|
-
</body>
|
|
11
|
-
</html>
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { RenderConfigScreenCtx } from "datocms-plugin-sdk";
|
|
2
|
-
import {
|
|
3
|
-
Button,
|
|
4
|
-
Canvas,
|
|
5
|
-
TextField,
|
|
6
|
-
Form,
|
|
7
|
-
FieldGroup,
|
|
8
|
-
SelectField,
|
|
9
|
-
} from "datocms-react-ui";
|
|
10
|
-
import { useEffect, useState } from "react";
|
|
11
|
-
import { Form as FormHandler, Field } from "react-final-form";
|
|
12
|
-
|
|
13
|
-
type PropTypes = {
|
|
14
|
-
ctx: RenderConfigScreenCtx;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type ValidParameters = {
|
|
18
|
-
accessToken: string;
|
|
19
|
-
site: { label: string; value: string };
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
type Parameters = ValidParameters;
|
|
23
|
-
|
|
24
|
-
export default function ConfigScreen({ ctx }: PropTypes) {
|
|
25
|
-
const accessToken = ctx.plugin.attributes.parameters.accessToken;
|
|
26
|
-
const site = ctx.plugin.attributes.parameters.site;
|
|
27
|
-
const [sites, setSites] = useState([]);
|
|
28
|
-
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
if (accessToken) {
|
|
31
|
-
setSites([]);
|
|
32
|
-
const getSites = async () => {
|
|
33
|
-
const response = await window.fetch(
|
|
34
|
-
"https://api.netlify.com/api/v1/sites/",
|
|
35
|
-
{
|
|
36
|
-
method: "GET",
|
|
37
|
-
headers: {
|
|
38
|
-
Authorization: `Bearer ${accessToken}`,
|
|
39
|
-
},
|
|
40
|
-
}
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
const message = `An error has occured: ${response.status}`;
|
|
45
|
-
ctx.alert(message);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const sites = await response.json();
|
|
49
|
-
setSites(sites);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
getSites();
|
|
53
|
-
}
|
|
54
|
-
}, [ctx, accessToken]);
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<Canvas ctx={ctx}>
|
|
58
|
-
<FormHandler<Parameters>
|
|
59
|
-
initialValues={ctx.plugin.attributes.parameters}
|
|
60
|
-
validate={(values) => {
|
|
61
|
-
const errors: Record<string, string> = {};
|
|
62
|
-
if (!values.accessToken) {
|
|
63
|
-
errors.accessToken = "This field is required!";
|
|
64
|
-
}
|
|
65
|
-
return errors;
|
|
66
|
-
}}
|
|
67
|
-
onSubmit={async (values) => {
|
|
68
|
-
await ctx.updatePluginParameters(values);
|
|
69
|
-
ctx.notice("Settings updated successfully!");
|
|
70
|
-
}}
|
|
71
|
-
>
|
|
72
|
-
{({ handleSubmit, submitting, dirty }) => (
|
|
73
|
-
<Form onSubmit={handleSubmit}>
|
|
74
|
-
<FieldGroup>
|
|
75
|
-
<Field name="accessToken">
|
|
76
|
-
{({ input, meta: { error } }) => (
|
|
77
|
-
<TextField
|
|
78
|
-
id="accessToken"
|
|
79
|
-
label="Access token"
|
|
80
|
-
hint={
|
|
81
|
-
<>
|
|
82
|
-
You can generate a{" "}
|
|
83
|
-
<a
|
|
84
|
-
target="_blank"
|
|
85
|
-
rel="noreferrer"
|
|
86
|
-
href="https://app.netlify.com/user/applications#personal-access-tokens"
|
|
87
|
-
>
|
|
88
|
-
personal access token
|
|
89
|
-
</a>{" "}
|
|
90
|
-
in your Netlify user settings.
|
|
91
|
-
</>
|
|
92
|
-
}
|
|
93
|
-
required
|
|
94
|
-
error={error}
|
|
95
|
-
{...input}
|
|
96
|
-
/>
|
|
97
|
-
)}
|
|
98
|
-
</Field>
|
|
99
|
-
|
|
100
|
-
{site || sites.length > 0 ? (
|
|
101
|
-
<Field name="site">
|
|
102
|
-
{({ input, meta: { error } }) => (
|
|
103
|
-
<SelectField
|
|
104
|
-
id="site"
|
|
105
|
-
label="Site"
|
|
106
|
-
error={error}
|
|
107
|
-
selectInputProps={{
|
|
108
|
-
options: sites.map((site: any) => ({
|
|
109
|
-
label: site.name,
|
|
110
|
-
value: site.site_id,
|
|
111
|
-
})),
|
|
112
|
-
}}
|
|
113
|
-
{...input}
|
|
114
|
-
/>
|
|
115
|
-
)}
|
|
116
|
-
</Field>
|
|
117
|
-
) : null}
|
|
118
|
-
</FieldGroup>
|
|
119
|
-
<Button
|
|
120
|
-
type="submit"
|
|
121
|
-
fullWidth
|
|
122
|
-
buttonSize="l"
|
|
123
|
-
buttonType="primary"
|
|
124
|
-
disabled={submitting || !dirty}
|
|
125
|
-
>
|
|
126
|
-
{!accessToken ? "Connect" : "Save settings"}
|
|
127
|
-
</Button>
|
|
128
|
-
</Form>
|
|
129
|
-
)}
|
|
130
|
-
</FormHandler>
|
|
131
|
-
</Canvas>
|
|
132
|
-
);
|
|
133
|
-
}
|
package/src/index.tsx
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
connect,
|
|
3
|
-
IntentCtx,
|
|
4
|
-
RenderModalCtx,
|
|
5
|
-
RenderPageCtx,
|
|
6
|
-
} from "datocms-plugin-sdk";
|
|
7
|
-
import { render } from "./utils/render";
|
|
8
|
-
import ConfigScreen from "./entrypoints/ConfigScreen";
|
|
9
|
-
import "datocms-react-ui/styles.css";
|
|
10
|
-
import SubmissionsPage from "./pages/SubmissionsPage";
|
|
11
|
-
import ShowSubmissionModal from "./modals/ShowSubmissionModal";
|
|
12
|
-
|
|
13
|
-
connect({
|
|
14
|
-
renderConfigScreen(ctx) {
|
|
15
|
-
return render(<ConfigScreen ctx={ctx} />);
|
|
16
|
-
},
|
|
17
|
-
mainNavigationTabs(ctx: IntentCtx) {
|
|
18
|
-
return [
|
|
19
|
-
{
|
|
20
|
-
label: "Netlify forms",
|
|
21
|
-
icon: "file-signature",
|
|
22
|
-
pointsTo: {
|
|
23
|
-
pageId: "form-submissions",
|
|
24
|
-
},
|
|
25
|
-
placement: ["before", "settings"],
|
|
26
|
-
},
|
|
27
|
-
];
|
|
28
|
-
},
|
|
29
|
-
renderPage(pageId, ctx: RenderPageCtx) {
|
|
30
|
-
switch (pageId) {
|
|
31
|
-
case "form-submissions":
|
|
32
|
-
return render(<SubmissionsPage ctx={ctx} />);
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
renderModal(modalId: string, ctx: RenderModalCtx) {
|
|
36
|
-
switch (modalId) {
|
|
37
|
-
case "showSubmission":
|
|
38
|
-
return render(<ShowSubmissionModal ctx={ctx} />);
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { RenderModalCtx } from "datocms-plugin-sdk";
|
|
2
|
-
import { Canvas } from "datocms-react-ui";
|
|
3
|
-
|
|
4
|
-
type PropTypes = {
|
|
5
|
-
ctx: RenderModalCtx;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export default function ShowSubmissionModal({ ctx }: PropTypes) {
|
|
9
|
-
const fields = ctx.parameters.ordered_human_fields as any;
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Canvas ctx={ctx}>
|
|
13
|
-
{fields ? (
|
|
14
|
-
fields.map((item: any) => (
|
|
15
|
-
<div
|
|
16
|
-
key={item.title}
|
|
17
|
-
style={{
|
|
18
|
-
marginBottom: "var(--spacing-m)",
|
|
19
|
-
}}
|
|
20
|
-
>
|
|
21
|
-
<div
|
|
22
|
-
style={{
|
|
23
|
-
color: "var(--light-body-color)",
|
|
24
|
-
fontSize: "var(--font-size-s)",
|
|
25
|
-
}}
|
|
26
|
-
>
|
|
27
|
-
{item.title}
|
|
28
|
-
</div>
|
|
29
|
-
<div>{item.value}</div>
|
|
30
|
-
</div>
|
|
31
|
-
))
|
|
32
|
-
) : (
|
|
33
|
-
<span>No form fields found!</span>
|
|
34
|
-
)}
|
|
35
|
-
</Canvas>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import { RenderPageCtx } from "datocms-plugin-sdk";
|
|
2
|
-
import { Button, Canvas, Spinner } from "datocms-react-ui";
|
|
3
|
-
import { useEffect, useState } from "react";
|
|
4
|
-
import { ValidParameters } from "../entrypoints/ConfigScreen";
|
|
5
|
-
|
|
6
|
-
type PropTypes = {
|
|
7
|
-
ctx: RenderPageCtx;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export default function SubmissionsPage({ ctx }: PropTypes) {
|
|
11
|
-
const parameters = ctx.plugin.attributes.parameters as ValidParameters;
|
|
12
|
-
const site = parameters.site;
|
|
13
|
-
const accessToken = parameters.accessToken;
|
|
14
|
-
|
|
15
|
-
const [submissions, setSubmissions] = useState([]);
|
|
16
|
-
const [loading, setLoading] = useState(false);
|
|
17
|
-
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
if (accessToken && site) {
|
|
20
|
-
const getSubmissions = async () => {
|
|
21
|
-
setLoading(true);
|
|
22
|
-
const response = await window.fetch(
|
|
23
|
-
`https://api.netlify.com/api/v1/sites/${site.value}/submissions`,
|
|
24
|
-
{
|
|
25
|
-
method: "GET",
|
|
26
|
-
headers: {
|
|
27
|
-
Authorization: `Bearer ${accessToken}`,
|
|
28
|
-
},
|
|
29
|
-
}
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
if (!response.ok) {
|
|
33
|
-
const message = `An error has occured: ${response.status}`;
|
|
34
|
-
ctx.alert(message);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const forms = await response.json();
|
|
38
|
-
setSubmissions(forms);
|
|
39
|
-
setLoading(false);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
getSubmissions();
|
|
43
|
-
}
|
|
44
|
-
}, [site, accessToken, ctx]);
|
|
45
|
-
|
|
46
|
-
const handleShowSubmissionModal = async (submission: any) => {
|
|
47
|
-
const result: any = await ctx.openModal({
|
|
48
|
-
id: "showSubmission",
|
|
49
|
-
title: `Submission (${submission.id})`,
|
|
50
|
-
width: "l",
|
|
51
|
-
parameters: submission,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
ctx.notice(result);
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const handleOpenDeleteSubmissonModal = async (submission: any) => {
|
|
58
|
-
const result: any = await ctx.openConfirm({
|
|
59
|
-
title: "Delete record?",
|
|
60
|
-
content:
|
|
61
|
-
"Are you sure you want to delete this record? This operation is not reversible!",
|
|
62
|
-
choices: [
|
|
63
|
-
{
|
|
64
|
-
label: "Yes, delete this record",
|
|
65
|
-
value: "negative",
|
|
66
|
-
intent: "negative",
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
cancel: {
|
|
70
|
-
label: "Cancel",
|
|
71
|
-
value: false,
|
|
72
|
-
},
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
if (result) {
|
|
76
|
-
const response = await window.fetch(
|
|
77
|
-
`https://api.netlify.com/api/v1/submissions/${submission.id}`,
|
|
78
|
-
{
|
|
79
|
-
method: "DELETE",
|
|
80
|
-
headers: {
|
|
81
|
-
Authorization: `Bearer ${accessToken}`,
|
|
82
|
-
},
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
if (!response.ok) {
|
|
87
|
-
ctx.alert(`An error has occured: ${response.status}`);
|
|
88
|
-
} else {
|
|
89
|
-
setSubmissions(
|
|
90
|
-
submissions.filter((item: any) => item.id !== submission.id)
|
|
91
|
-
);
|
|
92
|
-
ctx.notice("Record successfully removed");
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
return (
|
|
98
|
-
<Canvas ctx={ctx}>
|
|
99
|
-
<div
|
|
100
|
-
style={{
|
|
101
|
-
paddingTop: "var(--spacing-l)",
|
|
102
|
-
paddingLeft: "var(--spacing-xxl)",
|
|
103
|
-
paddingRight: "var(--spacing-xxl)",
|
|
104
|
-
}}
|
|
105
|
-
>
|
|
106
|
-
<h1 style={{ fontWeight: 500 }}>Form submissions</h1>
|
|
107
|
-
<div>
|
|
108
|
-
<div
|
|
109
|
-
style={{
|
|
110
|
-
display: "flex",
|
|
111
|
-
justifyContent: "space-between",
|
|
112
|
-
borderBottom: 1,
|
|
113
|
-
borderBottomColor: "var(--darker-border-color)",
|
|
114
|
-
borderBottomStyle: "solid",
|
|
115
|
-
paddingTop: "var(--spacing-m)",
|
|
116
|
-
paddingBottom: "var(--spacing-m)",
|
|
117
|
-
fontWeight: 500,
|
|
118
|
-
}}
|
|
119
|
-
>
|
|
120
|
-
<span style={{ width: "25%" }}>Name</span>
|
|
121
|
-
<span style={{ width: "25%" }}>Form</span>
|
|
122
|
-
<span style={{ width: "25%" }}>Date</span>
|
|
123
|
-
<span style={{ width: "25%", flexGrow: 0 }}></span>
|
|
124
|
-
<span></span>
|
|
125
|
-
</div>
|
|
126
|
-
|
|
127
|
-
{loading ? (
|
|
128
|
-
<div style={{ height: "200px", position: "relative" }}>
|
|
129
|
-
<Spinner size={48} placement="centered" />
|
|
130
|
-
</div>
|
|
131
|
-
) : (
|
|
132
|
-
submissions.map((item: any) => (
|
|
133
|
-
<div
|
|
134
|
-
key={item.id}
|
|
135
|
-
style={{
|
|
136
|
-
display: "flex",
|
|
137
|
-
justifyContent: "space-between",
|
|
138
|
-
borderBottom: 1,
|
|
139
|
-
borderBottomColor: "var(--darker-border-color)",
|
|
140
|
-
borderBottomStyle: "solid",
|
|
141
|
-
paddingTop: "var(--spacing-m)",
|
|
142
|
-
paddingBottom: "var(--spacing-m)",
|
|
143
|
-
alignItems: "center",
|
|
144
|
-
}}
|
|
145
|
-
>
|
|
146
|
-
<span style={{ width: "25%", flexGrow: 0 }}>{item.name}</span>
|
|
147
|
-
<span style={{ width: "25%", flexGrow: 0 }}>
|
|
148
|
-
{item.form_name}
|
|
149
|
-
</span>
|
|
150
|
-
<span style={{ width: "25%", flexGrow: 0 }}>
|
|
151
|
-
{new Intl.DateTimeFormat("en-US").format(
|
|
152
|
-
new Date(item.created_at)
|
|
153
|
-
)}
|
|
154
|
-
</span>
|
|
155
|
-
<span style={{ width: "25%", flexGrow: 0, textAlign: "right" }}>
|
|
156
|
-
<Button
|
|
157
|
-
buttonSize="xs"
|
|
158
|
-
type="button"
|
|
159
|
-
onClick={() => handleShowSubmissionModal(item)}
|
|
160
|
-
style={{ marginRight: "var(--spacing-m)" }}
|
|
161
|
-
>
|
|
162
|
-
Show
|
|
163
|
-
</Button>
|
|
164
|
-
<Button
|
|
165
|
-
buttonSize="xs"
|
|
166
|
-
type="reset"
|
|
167
|
-
buttonType="negative"
|
|
168
|
-
onClick={() => handleOpenDeleteSubmissonModal(item)}
|
|
169
|
-
>
|
|
170
|
-
Delete
|
|
171
|
-
</Button>
|
|
172
|
-
</span>
|
|
173
|
-
</div>
|
|
174
|
-
))
|
|
175
|
-
)}
|
|
176
|
-
|
|
177
|
-
{}
|
|
178
|
-
</div>
|
|
179
|
-
</div>
|
|
180
|
-
</Canvas>
|
|
181
|
-
);
|
|
182
|
-
}
|
package/src/react-app-env.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="react-scripts" />
|
package/src/utils/render.tsx
DELETED
package/tsconfig.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es5",
|
|
4
|
-
"lib": [
|
|
5
|
-
"dom",
|
|
6
|
-
"dom.iterable",
|
|
7
|
-
"esnext"
|
|
8
|
-
],
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"allowSyntheticDefaultImports": true,
|
|
13
|
-
"strict": true,
|
|
14
|
-
"forceConsistentCasingInFileNames": true,
|
|
15
|
-
"noFallthroughCasesInSwitch": true,
|
|
16
|
-
"module": "esnext",
|
|
17
|
-
"moduleResolution": "node",
|
|
18
|
-
"resolveJsonModule": true,
|
|
19
|
-
"isolatedModules": true,
|
|
20
|
-
"noEmit": true,
|
|
21
|
-
"jsx": "react-jsx"
|
|
22
|
-
},
|
|
23
|
-
"include": [
|
|
24
|
-
"src"
|
|
25
|
-
]
|
|
26
|
-
}
|