datocms-plugin-netlify-forms 0.0.3 → 0.0.4

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.
@@ -0,0 +1,2 @@
1
+ (this["webpackJsonpdatocms-plugin-netlify-forms"]=this["webpackJsonpdatocms-plugin-netlify-forms"]||[]).push([[0],{64:function(e,t,n){"use strict";n.r(t);var r=n(74),s=n(0),a=n(8),i=n.n(a),c=n(2);function o(e){i.a.render(Object(c.jsx)(s.StrictMode,{children:e}),document.getElementById("root"))}var u=n(31),l=n(7),d=n.n(l),p=n(9),b=n(3),f=n(75),j=n(66),h=n(67),m=n(76),x=n(73),v=n(71),O=n(24);function g(e){var t=e.ctx,n=t.plugin.attributes.parameters.accessToken,r=Object(s.useState)([]),a=Object(b.a)(r,2),i=a[0],o=a[1];return Object(s.useEffect)((function(){if(n){o([]);var e=function(){var e=Object(p.a)(d.a.mark((function e(){var r,s,a;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||(s="An error has occured: ".concat(r.status),t.alert(s)),e.next=6,r.json();case 6:a=e.sent,o(a);case 8:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}();e()}}),[t,n]),Object(c.jsx)(f.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(p.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,s=e.dirty;return Object(c.jsxs)(j.a,{onSubmit:t,children:[Object(c.jsxs)(h.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))}}),i.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:i.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||!s,children:n?"Save settings":"Connect"})]})}})})}n(58);var y=n(72);function w(e){var t=e.ctx,n=t.plugin.attributes.parameters,r=n.site,a=n.accessToken,i=Object(s.useState)([]),o=Object(b.a)(i,2),u=o[0],l=o[1],j=Object(s.useState)(!1),h=Object(b.a)(j,2),m=h[0],x=h[1];Object(s.useEffect)((function(){if(a&&r){var e=function(){var e=Object(p.a)(d.a.mark((function e(){var n,s,i;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(a)}});case 3:return n=e.sent,x(!1),n.ok||(s="An error has occured: ".concat(n.status),t.alert(s)),e.next=8,n.json();case 8:i=e.sent,l(i);case 10:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}();e()}}),[r,a,t]);var O=function(){var e=Object(p.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(p.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(a)}});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)(f.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",{style:{display:"flex",justifyContent:"space-between",borderBottom:1,borderBottomColor:"var(--darker-border-color)",borderBottomStyle:"solid",paddingTop:"var(--spacing-m)",paddingBottom:"var(--spacing-m)",fontWeight:500},children:[Object(c.jsx)("span",{style:{width:"25%"},children:"Name"}),Object(c.jsx)("span",{style:{width:"25%"},children:"Form"}),Object(c.jsx)("span",{style:{width:"25%"},children:"Date"}),Object(c.jsx)("span",{style:{width:"25%",flexGrow:0}}),Object(c.jsx)("span",{})]}),m?Object(c.jsx)("div",{style:{height:"200px",position:"relative"},children:Object(c.jsx)(y.a,{size:48,placement:"centered"})}):u.map((function(e){return Object(c.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",borderBottom:1,borderBottomColor:"var(--darker-border-color)",borderBottomStyle:"solid",paddingTop:"var(--spacing-m)",paddingBottom:"var(--spacing-m)",alignItems:"center"},children:[Object(c.jsx)("span",{style:{width:"25%",flexGrow:0},children:e.name}),Object(c.jsx)("span",{style:{width:"25%",flexGrow:0},children:e.form_name}),Object(c.jsx)("span",{style:{width:"25%",flexGrow:0},children:new Intl.DateTimeFormat("en-US").format(new Date(e.created_at))}),Object(c.jsxs)("span",{style:{width:"25%",flexGrow:0,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)}))]})]})})}function k(e){var t=e.ctx,n=t.parameters.ordered_human_fields;return Object(c.jsx)(f.a,{ctx:t,children:n?n.map((function(e){return Object(c.jsxs)("div",{style:{marginBottom:"var(--spacing-m)"},children:[Object(c.jsx)("div",{style:{color:"var(--light-body-color)",fontSize:"var(--font-size-s)"},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)(w,{ctx:t}))},renderModal:function(e,t){if("showSubmission"===e)return o(Object(c.jsx)(k,{ctx:t}))}})}},[[64,1,2]]]);
2
+ //# sourceMappingURL=main.59c36fec.chunk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["utils/render.tsx","entrypoints/ConfigScreen.tsx","pages/SubmissionsPage.tsx","modals/ShowSubmissionModal.tsx","index.tsx"],"names":["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","display","justifyContent","borderBottom","borderBottomColor","borderBottomStyle","paddingBottom","flexGrow","height","position","Spinner","size","placement","alignItems","form_name","Intl","DateTimeFormat","format","Date","created_at","textAlign","onClick","marginRight","ShowSubmissionModal","fields","ordered_human_fields","marginBottom","color","fontSize","connect","renderConfigScreen","mainNavigationTabs","icon","pointsTo","pageId","renderPage","renderModal","modalId"],"mappings":"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","file":"static/js/main.59c36fec.chunk.js","sourcesContent":["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\";\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\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n borderBottom: 1,\n borderBottomColor: \"var(--darker-border-color)\",\n borderBottomStyle: \"solid\",\n paddingTop: \"var(--spacing-m)\",\n paddingBottom: \"var(--spacing-m)\",\n fontWeight: 500,\n }}\n >\n <span style={{ width: \"25%\" }}>Name</span>\n <span style={{ width: \"25%\" }}>Form</span>\n <span style={{ width: \"25%\" }}>Date</span>\n <span style={{ width: \"25%\", flexGrow: 0 }}></span>\n <span></span>\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\n key={item.id}\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n borderBottom: 1,\n borderBottomColor: \"var(--darker-border-color)\",\n borderBottomStyle: \"solid\",\n paddingTop: \"var(--spacing-m)\",\n paddingBottom: \"var(--spacing-m)\",\n alignItems: \"center\",\n }}\n >\n <span style={{ width: \"25%\", flexGrow: 0 }}>{item.name}</span>\n <span style={{ width: \"25%\", flexGrow: 0 }}>\n {item.form_name}\n </span>\n <span style={{ width: \"25%\", flexGrow: 0 }}>\n {new Intl.DateTimeFormat(\"en-US\").format(\n new Date(item.created_at)\n )}\n </span>\n <span style={{ width: \"25%\", flexGrow: 0, 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 </span>\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\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 ? (\n fields.map((item: any) => (\n <div\n key={item.title}\n style={{\n marginBottom: \"var(--spacing-m)\",\n }}\n >\n <div\n style={{\n color: \"var(--light-body-color)\",\n fontSize: \"var(--font-size-s)\",\n }}\n >\n {item.title}\n </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",
3
+ "version": "0.0.4",
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,8 +10,12 @@
10
10
  "datocms-plugin",
11
11
  "netlify"
12
12
  ],
13
+ "files": [
14
+ "docs",
15
+ "build"
16
+ ],
13
17
  "datoCmsPlugin": {
14
- "title": "Netlify forms",
18
+ "title": "Netlify Forms",
15
19
  "coverImage": "docs/cover.png",
16
20
  "previewImage": "docs/preview.mp4",
17
21
  "entryPoint": "build/index.html",
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,137 +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 parameters = ctx.plugin.attributes.parameters;
26
- const accessToken = parameters.accessToken;
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
- if (values.accessToken !== accessToken) {
69
- setSites([]);
70
- }
71
-
72
- await ctx.updatePluginParameters(values);
73
- ctx.notice("Settings updated successfully!");
74
- }}
75
- >
76
- {({ handleSubmit, submitting, dirty }) => (
77
- <Form onSubmit={handleSubmit}>
78
- <FieldGroup>
79
- <Field name="accessToken">
80
- {({ input, meta: { error } }) => (
81
- <TextField
82
- id="accessToken"
83
- label="Access token"
84
- hint={
85
- <>
86
- You can generate a{" "}
87
- <a
88
- target="_blank"
89
- rel="noreferrer"
90
- href="https://app.netlify.com/user/applications#personal-access-tokens"
91
- >
92
- personal access token
93
- </a>{" "}
94
- in your Netlify user settings.
95
- </>
96
- }
97
- required
98
- error={error}
99
- {...input}
100
- />
101
- )}
102
- </Field>
103
-
104
- {sites.length > 0 ? (
105
- <Field name="site">
106
- {({ input, meta: { error } }) => (
107
- <SelectField
108
- id="site"
109
- label="Site"
110
- error={error}
111
- selectInputProps={{
112
- options: sites.map((site: any) => ({
113
- label: site.name,
114
- value: site.site_id,
115
- })),
116
- }}
117
- {...input}
118
- />
119
- )}
120
- </Field>
121
- ) : null}
122
- </FieldGroup>
123
- <Button
124
- type="submit"
125
- fullWidth
126
- buttonSize="l"
127
- buttonType="primary"
128
- disabled={submitting || !dirty}
129
- >
130
- {!accessToken ? "Connect" : "Save settings"}
131
- </Button>
132
- </Form>
133
- )}
134
- </FormHandler>
135
- </Canvas>
136
- );
137
- }
@@ -1,3 +0,0 @@
1
- .inspector {
2
- margin-top: var(--spacing-l);
3
- }
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,183 +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
- setLoading(false);
33
-
34
- if (!response.ok) {
35
- const message = `An error has occured: ${response.status}`;
36
- ctx.alert(message);
37
- }
38
-
39
- const forms = await response.json();
40
- setSubmissions(forms);
41
- };
42
-
43
- getSubmissions();
44
- }
45
- }, [site, accessToken, ctx]);
46
-
47
- const handleShowSubmissionModal = async (submission: any) => {
48
- const result: any = await ctx.openModal({
49
- id: "showSubmission",
50
- title: `Submission (${submission.id})`,
51
- width: "l",
52
- parameters: submission,
53
- });
54
-
55
- ctx.notice(result);
56
- };
57
-
58
- const handleOpenDeleteSubmissonModal = async (submission: any) => {
59
- const result: any = await ctx.openConfirm({
60
- title: "Delete record?",
61
- content:
62
- "Are you sure you want to delete this record? This operation is not reversible!",
63
- choices: [
64
- {
65
- label: "Yes, delete this record",
66
- value: "negative",
67
- intent: "negative",
68
- },
69
- ],
70
- cancel: {
71
- label: "Cancel",
72
- value: false,
73
- },
74
- });
75
-
76
- if (result) {
77
- const response = await window.fetch(
78
- `https://api.netlify.com/api/v1/submissions/${submission.id}`,
79
- {
80
- method: "DELETE",
81
- headers: {
82
- Authorization: `Bearer ${accessToken}`,
83
- },
84
- }
85
- );
86
-
87
- if (!response.ok) {
88
- ctx.alert(`An error has occured: ${response.status}`);
89
- } else {
90
- setSubmissions(
91
- submissions.filter((item: any) => item.id !== submission.id)
92
- );
93
- ctx.notice("Record successfully removed");
94
- }
95
- }
96
- };
97
-
98
- return (
99
- <Canvas ctx={ctx}>
100
- <div
101
- style={{
102
- paddingTop: "var(--spacing-l)",
103
- paddingLeft: "var(--spacing-xxl)",
104
- paddingRight: "var(--spacing-xxl)",
105
- }}
106
- >
107
- <h1 style={{ fontWeight: 500 }}>Form submissions</h1>
108
- <div>
109
- <div
110
- style={{
111
- display: "flex",
112
- justifyContent: "space-between",
113
- borderBottom: 1,
114
- borderBottomColor: "var(--darker-border-color)",
115
- borderBottomStyle: "solid",
116
- paddingTop: "var(--spacing-m)",
117
- paddingBottom: "var(--spacing-m)",
118
- fontWeight: 500,
119
- }}
120
- >
121
- <span style={{ width: "25%" }}>Name</span>
122
- <span style={{ width: "25%" }}>Form</span>
123
- <span style={{ width: "25%" }}>Date</span>
124
- <span style={{ width: "25%", flexGrow: 0 }}></span>
125
- <span></span>
126
- </div>
127
-
128
- {loading ? (
129
- <div style={{ height: "200px", position: "relative" }}>
130
- <Spinner size={48} placement="centered" />
131
- </div>
132
- ) : (
133
- submissions.map((item: any) => (
134
- <div
135
- key={item.id}
136
- style={{
137
- display: "flex",
138
- justifyContent: "space-between",
139
- borderBottom: 1,
140
- borderBottomColor: "var(--darker-border-color)",
141
- borderBottomStyle: "solid",
142
- paddingTop: "var(--spacing-m)",
143
- paddingBottom: "var(--spacing-m)",
144
- alignItems: "center",
145
- }}
146
- >
147
- <span style={{ width: "25%", flexGrow: 0 }}>{item.name}</span>
148
- <span style={{ width: "25%", flexGrow: 0 }}>
149
- {item.form_name}
150
- </span>
151
- <span style={{ width: "25%", flexGrow: 0 }}>
152
- {new Intl.DateTimeFormat("en-US").format(
153
- new Date(item.created_at)
154
- )}
155
- </span>
156
- <span style={{ width: "25%", flexGrow: 0, textAlign: "right" }}>
157
- <Button
158
- buttonSize="xs"
159
- type="button"
160
- onClick={() => handleShowSubmissionModal(item)}
161
- style={{ marginRight: "var(--spacing-m)" }}
162
- >
163
- Show
164
- </Button>
165
- <Button
166
- buttonSize="xs"
167
- type="reset"
168
- buttonType="negative"
169
- onClick={() => handleOpenDeleteSubmissonModal(item)}
170
- >
171
- Delete
172
- </Button>
173
- </span>
174
- </div>
175
- ))
176
- )}
177
-
178
- {}
179
- </div>
180
- </div>
181
- </Canvas>
182
- );
183
- }
@@ -1 +0,0 @@
1
- /// <reference types="react-scripts" />
@@ -1,6 +0,0 @@
1
- import React, { StrictMode } from 'react';
2
- import ReactDOM from 'react-dom';
3
-
4
- export function render(component: React.ReactNode): void {
5
- ReactDOM.render(<StrictMode>{component}</StrictMode>, document.getElementById('root'));
6
- }
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
- }