From 1ec63fc784bf70e52779f5a49861b2b8f7aba7c9 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Mon, 25 Sep 2023 18:17:34 +1300 Subject: [PATCH] ENH Simplify APIs --- _config.php | 1 - _config/graphql.yml | 8 -- _graphql/queries.yml | 6 -- _graphql/types.yml | 11 --- client/dist/js/bundle.js | 2 +- client/src/boot/index.js | 5 -- client/src/boot/registerQueries.js | 10 --- client/src/components/LinkField/LinkField.js | 44 ++++++++--- .../linkDescription/readLinkDescription.js | 43 ----------- client/src/state/linkTypes/readLinkTypes.js | 48 ------------ src/Controllers/LinkFieldController.php | 73 +++++++++++++++++++ src/Extensions/LeftAndMain.php | 13 ++++ src/GraphQL/LinkDescriptionResolver.php | 34 --------- src/GraphQL/LinkTypeResolver.php | 30 -------- 14 files changed, 121 insertions(+), 207 deletions(-) delete mode 100644 _config/graphql.yml delete mode 100644 _graphql/queries.yml delete mode 100644 _graphql/types.yml delete mode 100644 client/src/boot/registerQueries.js delete mode 100644 client/src/state/linkDescription/readLinkDescription.js delete mode 100644 client/src/state/linkTypes/readLinkTypes.js create mode 100644 src/Controllers/LinkFieldController.php delete mode 100644 src/GraphQL/LinkDescriptionResolver.php delete mode 100644 src/GraphQL/LinkTypeResolver.php diff --git a/_config.php b/_config.php index 9e519d4a..71c7914c 100644 --- a/_config.php +++ b/_config.php @@ -5,5 +5,4 @@ // Avoid creating global variables call_user_func(function () { - }); diff --git a/_config/graphql.yml b/_config/graphql.yml deleted file mode 100644 index a353b4d1..00000000 --- a/_config/graphql.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -Name: linkgraphql ---- -SilverStripe\GraphQL\Schema\Schema: - schemas: - admin: - src: - link: silverstripe/linkfield:_graphql diff --git a/_graphql/queries.yml b/_graphql/queries.yml deleted file mode 100644 index 9775dadb..00000000 --- a/_graphql/queries.yml +++ /dev/null @@ -1,6 +0,0 @@ -'readLinkDescription(dataStr: String!)': - type: LinkDescription - resolver: ['SilverStripe\LinkField\GraphQL\LinkDescriptionResolver', 'resolve'] -'readLinkTypes(keys: [ID])': - type: '[LinkType]' - resolver: ['SilverStripe\LinkField\GraphQL\LinkTypeResolver', 'resolve'] diff --git a/_graphql/types.yml b/_graphql/types.yml deleted file mode 100644 index 70525b16..00000000 --- a/_graphql/types.yml +++ /dev/null @@ -1,11 +0,0 @@ -LinkDescription: - description: Given some Link data, computes the matching description - fields: - description: String - -LinkType: - description: Describe a Type of Link that can be managed by a LinkField - fields: - key: ID - handlerName: String! - title: String! diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index 8726ffc2..866dd70b 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -1 +1 @@ -!function(){"use strict";var e={274:function(e,t,n){i(n(510));var r=i(n(180)),a=i(n(521)),o=i(n(154));function i(e){return e&&e.__esModule?e:{default:e}}document.addEventListener("DOMContentLoaded",(()=>{(0,a.default)(),(0,o.default)(),(0,r.default)()}))},521:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=u(n(648)),a=u(n(809)),o=u(n(852)),i=u(n(117)),l=u(n(606));function u(e){return e&&e.__esModule?e:{default:e}}var d=()=>{r.default.component.registerMany({LinkPicker:a.default,LinkField:o.default,"LinkModal.FormBuilderModal":i.default,"LinkModal.InsertMediaModal":l.default})};t.default=d},154:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=i(n(648)),a=i(n(689)),o=i(n(287));function i(e){return e&&e.__esModule?e:{default:e}}var l=()=>{r.default.query.register("readLinkTypes",a.default),r.default.query.register("readLinkDescription",o.default)};t.default=l},180:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r;(r=n(648))&&r.__esModule,n(827);var a=()=>{};t.default=a},852:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r,a=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=u(t);if(n&&n.has(e))return n.get(e);var r={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if("default"!==o&&Object.prototype.hasOwnProperty.call(e,o)){var i=a?Object.getOwnPropertyDescriptor(e,o):null;i&&(i.get||i.set)?Object.defineProperty(r,o,i):r[o]=e[o]}r.default=e,n&&n.set(e,r);return r}(n(363)),o=n(827),i=n(648),l=(r=n(42))&&r.__esModule?r:{default:r};function u(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(u=function(e){return e?n:t})(e)}function d(){return d=Object.assign?Object.assign.bind():function(e){for(var t=1;tt=>{let{data:n,value:r,...o}=t,i=r||n;return"string"==typeof i&&(i=JSON.parse(i)),a.default.createElement(e,d({dataStr:JSON.stringify(i)},o,{data:i}))}),(0,i.injectGraphql)("readLinkDescription"),l.default)((e=>{let{id:t,loading:n,Loading:r,data:o,LinkPicker:l,onChange:u,types:d,linkDescription:s,...f}=e;if(n)return a.default.createElement(r,null);const[c,p]=(0,a.useState)(!1),[y,v]=(0,a.useState)(""),{typeKey:g}=o,m=d[g],k=y?d[y]:m;let _=o?o.Title:"";_||(_=o?o.TitleRelField:"");const O={title:_,link:m?{type:m,title:_,description:s}:void 0,onEdit:()=>{p(!0)},onClear:e=>{"function"==typeof u&&u(e,{id:t,value:{}})},onSelect:e=>{v(e),p(!0)},types:Object.values(d)},h={type:k,editing:c,onSubmit:(e,n,r)=>{const{SecurityID:a,action_insert:o,...i}=e;return"function"==typeof u&&u(event,{id:t,value:i}),p(!1),v(""),Promise.resolve()},onClosed:()=>{p(!1)},data:o},b=k?k.handlerName:"FormBuilderModal",j=(0,i.loadComponent)(`LinkModal.${b}`);return a.default.createElement(a.Fragment,null,a.default.createElement(l,O),a.default.createElement(j,h))}));t.default=s},606:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;i(n(754));var r=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=o(t);if(n&&n.has(e))return n.get(e);var r={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var l=a?Object.getOwnPropertyDescriptor(e,i):null;l&&(l.get||l.set)?Object.defineProperty(r,i,l):r[i]=e[i]}r.default=e,n&&n.set(e,r);return r}(n(363)),a=i(n(475));function o(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(o=function(e){return e?n:t})(e)}function i(e){return e&&e.__esModule?e:{default:e}}function l(){return l=Object.assign?Object.assign.bind():function(e){for(var t=1;te({type:"INIT_FORM_SCHEMA_STACK",payload:{formSchema:{type:"insert-link",nextType:"admin"}}}),reset:()=>e({type:"RESET"})}}}))((e=>{let{type:t,editing:n,data:o,actions:i,onSubmit:u,...d}=e;if(!t)return!1;(0,r.useEffect)((()=>{n?i.initModal():i.reset()}),[n]);const s=o?{ID:o.FileID,Description:o.Title,TargetBlank:!!o.OpenInNew}:{};return r.default.createElement(a.default,l({isOpen:n,type:"insert-link",title:!1,bodyClassName:"modal__dialog",className:"insert-link__dialog-wrapper--internal",fileAttributes:s,onInsert:e=>{let{ID:n,Description:r,TargetBlank:a}=e;return u({FileID:n,Title:r,OpenInNew:a,typeKey:t.key},"",(()=>{}))}},d))}));t.default=u},117:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;u(n(754));var r=u(n(363)),a=(u(n(86)),u(n(912))),o=u(n(872)),i=u(n(902)),l=u(n(510));function u(e){return e&&e.__esModule?e:{default:e}}function d(){return d=Object.assign?Object.assign.bind():function(e){for(var t=1;t{const{schemaUrl:n}=l.default.getSection("SilverStripe\\Admin\\LeftAndMain").form.DynamicLink,r=o.default.parse(n),a=i.default.parse(r.query);return a.key=e,t&&(a.data=JSON.stringify(t)),o.default.format({...r,search:i.default.stringify(a)})};var f=e=>{let{type:t,editing:n,data:o,...i}=e;return!!t&&r.default.createElement(a.default,d({title:t.title,isOpen:n,schemaUrl:s(t.key,o),identifier:"Link.EditingLinkInfo"},i))};t.default=f},809:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;u(n(754));var r=u(n(363)),a=(n(648),u(n(86))),o=(n(127),u(n(820))),i=u(n(97)),l=u(n(734));u(n(686));function u(e){return e&&e.__esModule?e:{default:e}}function d(){return d=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{types:t,onSelect:n,link:a,onEdit:u,onClear:s}=e;return r.default.createElement("div",{className:(0,o.default)("link-picker","form-control",{"link-picker--selected":a})},void 0===a&&r.default.createElement(i.default,{types:t,onSelect:n}),a&&r.default.createElement(l.default,d({},a,{onClear:s,onClick:()=>a&&u&&u(a)})))};t.Component=s,s.propTypes={...i.default.propTypes,link:a.default.shape(l.default.propTypes),onEdit:a.default.func,onClear:a.default.func};var f=s;t.default=f},97:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=d(n(754)),a=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=u(t);if(n&&n.has(e))return n.get(e);var r={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if("default"!==o&&Object.prototype.hasOwnProperty.call(e,o)){var i=a?Object.getOwnPropertyDescriptor(e,o):null;i&&(i.get||i.set)?Object.defineProperty(r,o,i):r[o]=e[o]}r.default=e,n&&n.set(e,r);return r}(n(363)),o=(n(648),d(n(86))),i=n(127),l=(d(n(820)),d(n(686)));function u(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(u=function(e){return e?n:t})(e)}function d(e){return e&&e.__esModule?e:{default:e}}const s=e=>{let{types:t,onSelect:n}=e;const[o,l]=(0,a.useState)(!1);return a.default.createElement(i.Dropdown,{isOpen:o,toggle:()=>l((e=>!e)),className:"link-picker__menu"},a.default.createElement(i.DropdownToggle,{className:"link-picker__menu-toggle font-icon-link",caret:!0},r.default._t("Link.ADD_LINK","Add Link")),a.default.createElement(i.DropdownMenu,null,t.map((e=>{let{key:t,title:r}=e;return a.default.createElement(i.DropdownItem,{key:t,onClick:()=>n(t)},r)}))))};s.propTypes={types:o.default.arrayOf(l.default).isRequired,onSelect:o.default.func.isRequired};var f=s;t.default=f},734:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=u(n(754)),a=u(n(363)),o=u(n(86)),i=u(n(686)),l=n(127);function u(e){return e&&e.__esModule?e:{default:e}}const d=e=>t=>{t.nativeEvent.stopImmediatePropagation(),t.preventDefault(),t.nativeEvent.preventDefault(),t.stopPropagation(),e&&e()},s=e=>{let{title:t,type:n,description:o,onClear:i,onClick:u}=e;return a.default.createElement("div",{className:"link-picker__link"},a.default.createElement(l.Button,{className:"link-picker__button font-icon-link",color:"secondary",onClick:d(u)},a.default.createElement("div",{className:"link-picker__link-detail"},a.default.createElement("div",{className:"link-picker__title"},t),a.default.createElement("small",{className:"link-picker__type"},n.title,": ",a.default.createElement("span",{className:"link-picker__url"},o)))),a.default.createElement(l.Button,{className:"link-picker__clear",color:"link",onClick:d(i)},r.default._t("Link.CLEAR","Clear")))};s.propTypes={title:o.default.string.isRequired,type:i.default,description:o.default.string,onClear:o.default.func,onClick:o.default.func};var f=s;t.default=f},115:function(e,t,n){var r=l(n(311)),a=l(n(363)),o=l(n(691)),i=n(648);function l(e){return e&&e.__esModule?e:{default:e}}function u(){return u=Object.assign?Object.assign.bind():function(e){for(var t=1;t{e(".js-injector-boot .entwine-jsonfield").entwine({Component:null,Root:null,onmatch(){const e=this.closest(".cms-content").attr("id"),t=e?{context:e}:{},n=this.data("schema-component"),r=(0,i.loadComponent)(n,t);this.setComponent(r),this.setRoot(o.default.createRoot(this[0])),this._super(),this.refresh()},refresh(){const e=this.getProps(),t=this.getComponent();this.getRoot().render(a.default.createElement(t,u({},e,{noHolder:!0})))},handleChange(t,n){let{id:r,value:a}=n;const o=e(this).data("field-id");e("#"+o).val(JSON.stringify(a)).trigger("change"),this.refresh()},getProps(){const t=e(this).data("field-id"),n=e("#"+t).val();return{id:t,value:n?JSON.parse(n):void 0,onChange:this.handleChange.bind(this)}},onunmatch(){this.getRoot().unmount()}})}))},287:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=n(648);const a={props(e){const{data:{error:t,readLinkDescription:n,loading:r}}=e,a=t&&t.graphQLErrors&&t.graphQLErrors.map((e=>e.message));return{loading:r,linkDescription:n?n.description:"",graphQLErrors:a}}},{READ:o}=r.graphqlTemplates;var i={apolloConfig:a,templateName:o,pluralName:"LinkDescription",pagination:!1,params:{dataStr:"String!"},args:{root:{dataStr:"dataStr"}},fields:["description"]};t.default=i},689:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=n(648);const a={props(e){const{data:{error:t,readLinkTypes:n,loading:r}}=e,a=t&&t.graphQLErrors&&t.graphQLErrors.map((e=>e.message));return{loading:r,types:n?n.reduce(((e,t)=>({...e,[t.key]:t})),{}):{},graphQLErrors:a}}},{READ:o}=r.graphqlTemplates;var i={apolloConfig:a,templateName:o,pluralName:"LinkTypes",pagination:!1,params:{keys:"[ID]"},args:{root:{keys:"keys"}},fields:["key","title","handlerName"]};t.default=i},686:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r,a=(r=n(86))&&r.__esModule?r:{default:r};var o=a.default.shape({key:a.default.string.isRequired,title:a.default.string.isRequired});t.default=o},510:function(e){e.exports=Config},42:function(e){e.exports=FieldHolder},912:function(e){e.exports=FormBuilderModal},648:function(e){e.exports=Injector},475:function(e){e.exports=InsertMediaModal},872:function(e){e.exports=NodeUrl},86:function(e){e.exports=PropTypes},363:function(e){e.exports=React},691:function(e){e.exports=ReactDomClient},624:function(e){e.exports=ReactRedux},127:function(e){e.exports=Reactstrap},827:function(e){e.exports=Redux},820:function(e){e.exports=classnames},754:function(e){e.exports=i18n},311:function(e){e.exports=jQuery},902:function(e){e.exports=qs}},t={};function n(r){var a=t[r];if(void 0!==a)return a.exports;var o=t[r]={exports:{}};return e[r](o,o.exports,n),o.exports}n(274),n(115)}(); \ No newline at end of file +!function(){"use strict";var e={274:function(e,t,n){var r=o(n(180)),a=o(n(521));function o(e){return e&&e.__esModule?e:{default:e}}document.addEventListener("DOMContentLoaded",(()=>{(0,a.default)(),(0,r.default)()}))},521:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=u(n(648)),a=u(n(809)),o=u(n(852)),i=u(n(117)),l=u(n(606));function u(e){return e&&e.__esModule?e:{default:e}}var f=()=>{r.default.component.registerMany({LinkPicker:a.default,LinkField:o.default,"LinkModal.FormBuilderModal":i.default,"LinkModal.InsertMediaModal":l.default})};t.default=f},180:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r;(r=n(648))&&r.__esModule,n(827);var a=()=>{};t.default=a},852:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r,a=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=u(t);if(n&&n.has(e))return n.get(e);var r={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if("default"!==o&&Object.prototype.hasOwnProperty.call(e,o)){var i=a?Object.getOwnPropertyDescriptor(e,o):null;i&&(i.get||i.set)?Object.defineProperty(r,o,i):r[o]=e[o]}r.default=e,n&&n.set(e,r);return r}(n(363)),o=n(827),i=n(648),l=(r=n(42))&&r.__esModule?r:{default:r};function u(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(u=function(e){return e?n:t})(e)}function f(){return f=Object.assign?Object.assign.bind():function(e){for(var t=1;tt=>{let{data:n,value:r,...o}=t,i=r||n;return"string"==typeof i&&(i=JSON.parse(i)),a.default.createElement(e,f({dataStr:JSON.stringify(i)},o,{data:i}))}),l.default)((e=>{let{id:t,onChange:n,dataStr:r,Loading:o,LinkPicker:l}=e;const[u,f]=(0,a.useState)([]),[d,c]=(0,a.useState)(null),[s,p]=(0,a.useState)(!1),[y,v]=(0,a.useState)(""),m=(e,t)=>{(async()=>fetch(e))().then((e=>e.json())).then(t)};if((0,a.useEffect)((()=>{m("/admin/linkfield/types",(e=>f(e)))}),[]),(0,a.useEffect)((()=>{if(!s){const e=`/admin/linkfield/description?data=${encodeURI(r)}`;m(e,(e=>c(e.description)))}}),[s]),0===u.length||null===d)return a.default.createElement(o,null);const _=JSON.parse(r),{typeKey:k}=_,g=u[k],O=y?u[y]:g;let h=_?_.Title:"";h||(h=_?_.TitleRelField:"");const b={title:h,link:g?{type:g,title:h,description:d}:void 0,onEdit:()=>{p(!0)},onClear:e=>{"function"==typeof n&&n(e,{id:t,value:{}})},onSelect:e=>{v(e),p(!0)},types:Object.values(u)},j={type:O,editing:s,onSubmit:(e,r,a)=>{const{SecurityID:o,action_insert:i,...l}=e;return"function"==typeof n&&n(event,{id:t,value:l}),p(!1),v(""),Promise.resolve()},onClosed:()=>{p(!1)},data:_},M=O?O.handlerName:"FormBuilderModal",P=(0,i.loadComponent)(`LinkModal.${M}`);return a.default.createElement(a.Fragment,null,a.default.createElement(l,b),a.default.createElement(P,j))}));t.default=d},606:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;i(n(754));var r=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=o(t);if(n&&n.has(e))return n.get(e);var r={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var l=a?Object.getOwnPropertyDescriptor(e,i):null;l&&(l.get||l.set)?Object.defineProperty(r,i,l):r[i]=e[i]}r.default=e,n&&n.set(e,r);return r}(n(363)),a=i(n(475));function o(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(o=function(e){return e?n:t})(e)}function i(e){return e&&e.__esModule?e:{default:e}}function l(){return l=Object.assign?Object.assign.bind():function(e){for(var t=1;te({type:"INIT_FORM_SCHEMA_STACK",payload:{formSchema:{type:"insert-link",nextType:"admin"}}}),reset:()=>e({type:"RESET"})}}}))((e=>{let{type:t,editing:n,data:o,actions:i,onSubmit:u,...f}=e;if(!t)return!1;(0,r.useEffect)((()=>{n?i.initModal():i.reset()}),[n]);const d=o?{ID:o.FileID,Description:o.Title,TargetBlank:!!o.OpenInNew}:{};return r.default.createElement(a.default,l({isOpen:n,type:"insert-link",title:!1,bodyClassName:"modal__dialog",className:"insert-link__dialog-wrapper--internal",fileAttributes:d,onInsert:e=>{let{ID:n,Description:r,TargetBlank:a}=e;return u({FileID:n,Title:r,OpenInNew:a,typeKey:t.key},"",(()=>{}))}},f))}));t.default=u},117:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;u(n(754));var r=u(n(363)),a=(u(n(86)),u(n(912))),o=u(n(872)),i=u(n(902)),l=u(n(510));function u(e){return e&&e.__esModule?e:{default:e}}function f(){return f=Object.assign?Object.assign.bind():function(e){for(var t=1;t{const{schemaUrl:n}=l.default.getSection("SilverStripe\\Admin\\LeftAndMain").form.DynamicLink,r=o.default.parse(n),a=i.default.parse(r.query);return a.key=e,t&&(a.data=JSON.stringify(t)),o.default.format({...r,search:i.default.stringify(a)})};var c=e=>{let{type:t,editing:n,data:o,...i}=e;return!!t&&r.default.createElement(a.default,f({title:t.title,isOpen:n,schemaUrl:d(t.key,o),identifier:"Link.EditingLinkInfo"},i))};t.default=c},809:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;u(n(754));var r=u(n(363)),a=(n(648),u(n(86))),o=(n(127),u(n(820))),i=u(n(97)),l=u(n(734));u(n(686));function u(e){return e&&e.__esModule?e:{default:e}}function f(){return f=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{types:t,onSelect:n,link:a,onEdit:u,onClear:d}=e;return r.default.createElement("div",{className:(0,o.default)("link-picker","form-control",{"link-picker--selected":a})},void 0===a&&r.default.createElement(i.default,{types:t,onSelect:n}),a&&r.default.createElement(l.default,f({},a,{onClear:d,onClick:()=>a&&u&&u(a)})))};t.Component=d,d.propTypes={...i.default.propTypes,link:a.default.shape(l.default.propTypes),onEdit:a.default.func,onClear:a.default.func};var c=d;t.default=c},97:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=f(n(754)),a=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=u(t);if(n&&n.has(e))return n.get(e);var r={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if("default"!==o&&Object.prototype.hasOwnProperty.call(e,o)){var i=a?Object.getOwnPropertyDescriptor(e,o):null;i&&(i.get||i.set)?Object.defineProperty(r,o,i):r[o]=e[o]}r.default=e,n&&n.set(e,r);return r}(n(363)),o=(n(648),f(n(86))),i=n(127),l=(f(n(820)),f(n(686)));function u(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(u=function(e){return e?n:t})(e)}function f(e){return e&&e.__esModule?e:{default:e}}const d=e=>{let{types:t,onSelect:n}=e;const[o,l]=(0,a.useState)(!1);return a.default.createElement(i.Dropdown,{isOpen:o,toggle:()=>l((e=>!e)),className:"link-picker__menu"},a.default.createElement(i.DropdownToggle,{className:"link-picker__menu-toggle font-icon-link",caret:!0},r.default._t("Link.ADD_LINK","Add Link")),a.default.createElement(i.DropdownMenu,null,t.map((e=>{let{key:t,title:r}=e;return a.default.createElement(i.DropdownItem,{key:t,onClick:()=>n(t)},r)}))))};d.propTypes={types:o.default.arrayOf(l.default).isRequired,onSelect:o.default.func.isRequired};var c=d;t.default=c},734:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=u(n(754)),a=u(n(363)),o=u(n(86)),i=u(n(686)),l=n(127);function u(e){return e&&e.__esModule?e:{default:e}}const f=e=>t=>{t.nativeEvent.stopImmediatePropagation(),t.preventDefault(),t.nativeEvent.preventDefault(),t.stopPropagation(),e&&e()},d=e=>{let{title:t,type:n,description:o,onClear:i,onClick:u}=e;return a.default.createElement("div",{className:"link-picker__link"},a.default.createElement(l.Button,{className:"link-picker__button font-icon-link",color:"secondary",onClick:f(u)},a.default.createElement("div",{className:"link-picker__link-detail"},a.default.createElement("div",{className:"link-picker__title"},t),a.default.createElement("small",{className:"link-picker__type"},n.title,": ",a.default.createElement("span",{className:"link-picker__url"},o)))),a.default.createElement(l.Button,{className:"link-picker__clear",color:"link",onClick:f(i)},r.default._t("Link.CLEAR","Clear")))};d.propTypes={title:o.default.string.isRequired,type:i.default,description:o.default.string,onClear:o.default.func,onClick:o.default.func};var c=d;t.default=c},115:function(e,t,n){var r=l(n(311)),a=l(n(363)),o=l(n(691)),i=n(648);function l(e){return e&&e.__esModule?e:{default:e}}function u(){return u=Object.assign?Object.assign.bind():function(e){for(var t=1;t{e(".js-injector-boot .entwine-jsonfield").entwine({Component:null,Root:null,onmatch(){const e=this.closest(".cms-content").attr("id"),t=e?{context:e}:{},n=this.data("schema-component"),r=(0,i.loadComponent)(n,t);this.setComponent(r),this.setRoot(o.default.createRoot(this[0])),this._super(),this.refresh()},refresh(){const e=this.getProps(),t=this.getComponent();this.getRoot().render(a.default.createElement(t,u({},e,{noHolder:!0})))},handleChange(t,n){let{id:r,value:a}=n;const o=e(this).data("field-id");e("#"+o).val(JSON.stringify(a)).trigger("change"),this.refresh()},getProps(){const t=e(this).data("field-id"),n=e("#"+t).val();return{id:t,value:n?JSON.parse(n):void 0,onChange:this.handleChange.bind(this)}},onunmatch(){this.getRoot().unmount()}})}))},686:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r,a=(r=n(86))&&r.__esModule?r:{default:r};var o=a.default.shape({key:a.default.string.isRequired,title:a.default.string.isRequired});t.default=o},510:function(e){e.exports=Config},42:function(e){e.exports=FieldHolder},912:function(e){e.exports=FormBuilderModal},648:function(e){e.exports=Injector},475:function(e){e.exports=InsertMediaModal},872:function(e){e.exports=NodeUrl},86:function(e){e.exports=PropTypes},363:function(e){e.exports=React},691:function(e){e.exports=ReactDomClient},624:function(e){e.exports=ReactRedux},127:function(e){e.exports=Reactstrap},827:function(e){e.exports=Redux},820:function(e){e.exports=classnames},754:function(e){e.exports=i18n},311:function(e){e.exports=jQuery},902:function(e){e.exports=qs}},t={};function n(r){var a=t[r];if(void 0!==a)return a.exports;var o=t[r]={exports:{}};return e[r](o,o.exports,n),o.exports}n(274),n(115)}(); \ No newline at end of file diff --git a/client/src/boot/index.js b/client/src/boot/index.js index 4d7bb2a5..aa344fe7 100644 --- a/client/src/boot/index.js +++ b/client/src/boot/index.js @@ -1,14 +1,9 @@ /* global document */ /* eslint-disable */ -import Config from 'lib/Config'; import registerReducers from './registerReducers'; import registerComponents from './registerComponents'; -import registerQueries from './registerQueries'; document.addEventListener('DOMContentLoaded', () => { registerComponents(); - - registerQueries(); - registerReducers(); }); diff --git a/client/src/boot/registerQueries.js b/client/src/boot/registerQueries.js deleted file mode 100644 index 1d68cfa3..00000000 --- a/client/src/boot/registerQueries.js +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-disable */ -import Injector from 'lib/Injector'; -import readLinkTypes from 'state/linkTypes/readLinkTypes'; -import readLinkDescription from 'state/linkDescription/readLinkDescription'; - -const registerQueries = () => { - Injector.query.register('readLinkTypes', readLinkTypes); - Injector.query.register('readLinkDescription', readLinkDescription); -}; -export default registerQueries; diff --git a/client/src/components/LinkField/LinkField.js b/client/src/components/LinkField/LinkField.js index 5571450f..2ab45c00 100644 --- a/client/src/components/LinkField/LinkField.js +++ b/client/src/components/LinkField/LinkField.js @@ -1,13 +1,13 @@ -import React, { Fragment, useState } from 'react'; +import React, { Fragment, useState, useEffect } from 'react'; import { compose } from 'redux'; -import { inject, injectGraphql, loadComponent } from 'lib/Injector'; +import { inject, loadComponent } from 'lib/Injector'; import fieldHolder from 'components/FieldHolder/FieldHolder'; -const LinkField = ({ id, loading, Loading, data, LinkPicker, onChange, types, linkDescription, ...props }) => { - if (loading) { - return ; - } - +const LinkField = ({ id, onChange, dataStr, Loading, LinkPicker }) => { + // params id, onChange, dataStr come from entwine/JsonField.js + // params LinkPicker, Loading come from inject(['LinkPicker', 'Loading']) + const [types, setTypes] = useState([]); + const [description, setDescription] = useState(null); const [editing, setEditing] = useState(false); const [newTypeKey, setNewTypeKey] = useState(''); @@ -19,6 +19,32 @@ const LinkField = ({ id, loading, Loading, data, LinkPicker, onChange, types, li onChange(event, { id, value: {} }); }; + // Utility function to make a GET request to the server + const fetchData = (path, onFetched) => { + (async () => fetch(path))() + .then(response => response.json()) + .then(onFetched); + }; + + // Request types data from server on initial load of component + useEffect(() => { + fetchData('/admin/linkfield/types', (responseJson) => setTypes(responseJson)); + }, []); + + // Request description of the link from the server when `editing` variable changes to false + // and on initial load of component + useEffect(() => { + if (!editing) { + const path = `/admin/linkfield/description?data=${encodeURI(dataStr)}`; + fetchData(path, (responseJson) => setDescription(responseJson.description)); + } + }, [editing]); + + if (types.length === 0 || description === null) { + return ; + } + + const data = JSON.parse(dataStr); const { typeKey } = data; const type = types[typeKey]; const modalType = newTypeKey ? types[newTypeKey] : type; @@ -31,7 +57,7 @@ const LinkField = ({ id, loading, Loading, data, LinkPicker, onChange, types, li const linkProps = { title, - link: type ? { type, title, description: linkDescription } : undefined, + link: type ? { type, title, description } : undefined, onEdit: () => { setEditing(true); }, onClear, onSelect: (key) => { @@ -83,8 +109,6 @@ const stringifyData = (Component) => (({ data, value, ...props }) => { export default compose( inject(['LinkPicker', 'Loading']), - injectGraphql('readLinkTypes'), stringifyData, - injectGraphql('readLinkDescription'), fieldHolder )(LinkField); diff --git a/client/src/state/linkDescription/readLinkDescription.js b/client/src/state/linkDescription/readLinkDescription.js deleted file mode 100644 index 2301bd26..00000000 --- a/client/src/state/linkDescription/readLinkDescription.js +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-disable */ -import { graphqlTemplates } from 'lib/Injector'; - -const apolloConfig = { - props( - props - ) { - const { - data: { - error, - readLinkDescription, - loading: networkLoading, - }, - } = props; - const errors = error && error.graphQLErrors && - error.graphQLErrors.map((graphQLError) => graphQLError.message); - const linkDescription = readLinkDescription ? readLinkDescription.description : ''; - - return { - loading: networkLoading, - linkDescription, - graphQLErrors: errors, - }; - }, -}; - -const { READ } = graphqlTemplates; -const query = { - apolloConfig, - templateName: READ, - pluralName: 'LinkDescription', - pagination: false, - params: { - dataStr: 'String!' - }, - args: { - root: { - dataStr: 'dataStr' - } - }, - fields: ['description'], -}; -export default query; diff --git a/client/src/state/linkTypes/readLinkTypes.js b/client/src/state/linkTypes/readLinkTypes.js deleted file mode 100644 index 1bb0bb7e..00000000 --- a/client/src/state/linkTypes/readLinkTypes.js +++ /dev/null @@ -1,48 +0,0 @@ -/* eslint-disable */ -import { graphqlTemplates } from 'lib/Injector'; - -const apolloConfig = { - props( - props - ) { - const { - data: { - error, - readLinkTypes, - loading: networkLoading, - }, - } = props; - const errors = error && error.graphQLErrors && - error.graphQLErrors.map((graphQLError) => graphQLError.message); - - const types = readLinkTypes ? - readLinkTypes.reduce((accumulator, type) => ( - { ...accumulator, [type.key]: type } - ), {}) : - {}; - - return { - loading: networkLoading, - types, - graphQLErrors: errors, - }; - }, -}; - -const { READ } = graphqlTemplates; -const query = { - apolloConfig, - templateName: READ, - pluralName: 'LinkTypes', - pagination: false, - params: { - keys: '[ID]' - }, - args: { - root: { - keys: 'keys' - } - }, - fields: ['key', 'title', 'handlerName'], -}; -export default query; diff --git a/src/Controllers/LinkFieldController.php b/src/Controllers/LinkFieldController.php new file mode 100644 index 00000000..3fc06aba --- /dev/null +++ b/src/Controllers/LinkFieldController.php @@ -0,0 +1,73 @@ +getOwner()->getRequest(); + $jsonStr = $request->getVar('data'); + // data will be an empty array if there is no existing link + $data = json_decode($jsonStr, true); + $description = ''; + if (json_last_error() !== JSON_ERROR_NONE) { + throw new HTTPResponse_Exception('data is not a valid JSON string'); + } + if (array_key_exists('typeKey', $data)) { + $typeKey = $data['typeKey']; + /** @var Type $type */ + $type = Registry::singleton()->byKey($typeKey); + if (!$type) { + throw new HTTPResponse_Exception('typeKey is not allowed'); + } + $description = $type->generateLinkDescription($data); + } + return $this->jsonResponse([ + 'description' => $description + ]); + } + + /** + * Used for requests to /admin/linkfield/types + */ + public function types(): HTTPResponse + { + $data = []; + /** @var Type $type */ + foreach (Registry::singleton()->list() as $key => $type) { + $data[$key] = [ + 'key' => $key, + 'handlerName' => $type->LinkTypeHandlerName(), + 'title' => $type->LinkTypeTile() + ]; + } + return $this->jsonResponse($data); + } + + /** + * Create a JSON response to send back to the browser + */ + private function jsonResponse(array $data) + { + $response = $this->getOwner()->getResponse(); + $jsonStr = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + $response->setBody($jsonStr); + $response->addHeader('Content-type', 'application/json'); + return $response; + } +} diff --git a/src/Extensions/LeftAndMain.php b/src/Extensions/LeftAndMain.php index d1173a3d..bc4729c1 100644 --- a/src/Extensions/LeftAndMain.php +++ b/src/Extensions/LeftAndMain.php @@ -4,12 +4,17 @@ use SilverStripe\Core\Extension; use SilverStripe\LinkField\Type\Registry; +use SilverStripe\LinkField\Controllers\LinkFieldController; /** * Register a new Form Schema in LeftAndMain. */ class LeftAndMain extends Extension { + private static $allowed_actions = [ + 'linkfield', + ]; + public function init() { // Get the Link Registry to load all the JS requirements for managing Links. @@ -22,4 +27,12 @@ public function updateClientConfig(&$clientConfig) 'schemaUrl' => $this->getOwner()->Link('methodSchema/Modals/DynamicLink'), ]; } + + /** + * Endpoint for /admin/linkfield/ + */ + public function linkfield(): LinkFieldController + { + return LinkFieldController::create($this, 'linkfield'); + } } diff --git a/src/GraphQL/LinkDescriptionResolver.php b/src/GraphQL/LinkDescriptionResolver.php deleted file mode 100644 index 2259f25d..00000000 --- a/src/GraphQL/LinkDescriptionResolver.php +++ /dev/null @@ -1,34 +0,0 @@ - '']; - } - - $type = Registry::singleton()->byKey($typeKey); - - if (!$type) { - return ['description' => '']; - } - - return ['description' => $type->generateLinkDescription($data)]; - } -} diff --git a/src/GraphQL/LinkTypeResolver.php b/src/GraphQL/LinkTypeResolver.php deleted file mode 100644 index a61f28f1..00000000 --- a/src/GraphQL/LinkTypeResolver.php +++ /dev/null @@ -1,30 +0,0 @@ -list(); - $flattenType = array_map(function (Type $type, string $key) { - return [ - 'key' => $key, - 'handlerName' => $type->LinkTypeHandlerName(), - 'title' => $type->LinkTypeTile() - ]; - }, $types, array_keys($types)); - - return $flattenType; - } -}