diff --git a/client/dist/js/browserWarning.js b/client/dist/js/browserWarning.js deleted file mode 100644 index e10f535c4..000000000 --- a/client/dist/js/browserWarning.js +++ /dev/null @@ -1 +0,0 @@ -webpackJsonp([1],{"./client/src/lib/browserWarning.js":function(e,r,n){"use strict";var s=n("./node_modules/detect-browser/browser.js"),a=function(e){return e&&e.__esModule?e:{default:e}}(s);if("ie"===a.default.name&&parseInt(a.default.version,10)<=10){var t=document.getElementById("browser-warning-wrapper");t&&(t.className=t.className+" browser-warning-wrapper--incompatible")}}},["./client/src/lib/browserWarning.js"]); \ No newline at end of file diff --git a/client/dist/styles/browser-warning.css b/client/dist/styles/browser-warning.css deleted file mode 100644 index 41848f7f1..000000000 --- a/client/dist/styles/browser-warning.css +++ /dev/null @@ -1 +0,0 @@ -.browser-warning-wrapper{display:none}.browser-warning-wrapper--incompatible{display:block}.browser-warning{position:fixed;color:#fff;background:#005a93;height:100%;width:100%;z-index:100000;top:0;left:0;overflow:auto}.browser-warning__content{text-align:center;padding:30px}.browser-warning__content a{color:#fff;text-decoration:underline}.browser-warning__content .ss-logo{text-indent:-9999em;display:inline-block;width:80px;height:80px;background-image:url(data:image/png;base64,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);background-image:none,url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzVweCIgaGVpZ2h0PSI3NXB4IiB2aWV3Qm94PSIwIDAgNzUgNzUiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDQ2LjIgKDQ0NDk2KSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5CcmFuZCAvIExvZ288L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iTm90aWZpY2F0aW9ucy0vLVVuc3VwcG9ydGVkLWJyb3dzZXIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJOb3RpZmljYXRpb25zLUJhbm5lci1iYXIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01NDEuMDAwMDAwLCAtMzE0LjAwMDAwMCkiIGZpbGw9IiM1OENFRjAiPgogICAgICAgICAgICA8ZyBpZD0iR3JvdXAtNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzE3LjAwMDAwMCwgMzE0LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgPGcgaWQ9IkJyYW5kLS8tTG9nbyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjI0LjAwMDAwMCwgMC4wMDAwMDApIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNDQuNTYwNjU3MSwyNC41ODUyMjg2IEw0NC41NjA2NTcxLDI0LjU4NTIyODYgTDQ0LjU1MzIyODYsMjQuNTg1MjI4NiBDNDQuNTI3MjI4NiwyNC41ODUyMjg2IDQ0LjUwNDk0MjksMjQuNjgxOCA0NC40ODI2NTcxLDI0LjcwMDM3MTQgTDQ0LjU2MDY1NzEsMjQuNjc0MzcxNCBDMzguNjc3MjI4NiwyOC42NjM1MTQzIDM3LjM0MzgsMzYuNjEyMDg1NyA0MS4zNzc1MTQzLDQyLjQzMjM3MTQgTDUyLjIwODM3MTQsMzUuMjQxNTE0MyBMNTIuMjA4MzcxNCwzNS4yMzQwODU3IEM1NS45MjI2NTcxLDMzLjI0MzIyODYgNTkuMDAxOCwzMy45Nzg2NTcxIDYxLjAxMTIyODYsMzYuODk0MzcxNCBDNjMuMDI4MDg1NywzOS44MDI2NTcxIDYyLjE4ODY1NzEsNDMuNzczMjI4NiA1OS4yNDMyMjg2LDQ1Ljc2NDA4NTcgTDQ5LjQ2NzIyODYsNTIuMzUzMjI4NiBMNDMuMTkwMDg1Nyw1Ni41ODAwODU3IEMzNy4yOTkyMjg2LDYwLjU2MTggMzUuNzg3NTE0Myw2OC41MTAzNzE0IDM5LjgxNzUxNDMsNzQuMzIzMjI4NiBMNTAuNDcwMDg1Nyw2Ny4xMTM4IEw2Ni40NTYzNzE0LDU2LjI5NzggQzc1LjI4NTIyODYsNTAuMzI1MjI4NiA3Ny41NDM1MTQzLDM4LjM1MDM3MTQgNzEuNTAwMzcxNCwyOS42MjE4IEM2NS40NTcyMjg2LDIwLjkwNDM3MTQgNTMuMzkzMjI4NiwxNy4xNTY2NTcxIDQ0LjU2MDY1NzEsMjQuNTg1MjI4NiIgaWQ9IkZpbGwtMyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0yOS45MjExNzE0LDQ5LjY2MzcxNDMgQzM3LjM0OTc0MjksNDUuNjc4Mjg1NyAzNy42MjQ2LDM3Ljg5Njg1NzEgMzMuNTkwODg1NywzMi4wODAyODU3IEwyMy4wODY4ODU3LDM5LjQ0MiBMMjMuMTY0ODg1NywzOS40NDIgQzIwLjIyMzE3MTQsMzkuNDQyIDE2LjIzNDAyODYsNDAuMzg1NDI4NiAxNC4yMjA4ODU3LDM3LjQ3MzQyODYgQzEyLjIwNDAyODYsMzQuNTcyNTcxNCAxMi45OTUxNzE0LDMyLjAxMzQyODYgMTUuOTQwNiwyOC4yOTkxNDI5IEwxNS45NDgwMjg2LDI4LjI5OTE0MjkgTDI1LjY3MjAyODYsMjEuODY2IEwzMS45MzA2LDE3LjcwNiBDMzcuODI1MTcxNCwxMy43MjA1NzE0IDM5LjMyNTc0MjksNS44MTI4NTcxNCAzNS4yOTU3NDI5LDAgTDI0LjYzNTc0MjksNy4yMjggTDguNjYwNiwxOC4wMzY1NzE0IEw4LjY0MjAyODU3LDE4LjA1ODg1NzEgQy0wLjE4MzExNDI4NiwyNC4wMzUxNDI5IC0yLjc1MzQsMzUuOTUwNTcxNCAzLjI5MzQ1NzE0LDQ0LjY2OCBDOS4zNDAzMTQyOSw1My4zOTY1NzE0IDIyLjQ5MjYsNTUuNjI4ODU3MSAyOS45MjExNzE0LDQ5LjY1NjI4NTcgTDI5LjkyMTE3MTQsNDkuNjYzNzE0MyBaIiBpZD0iRmlsbC0xIj48L3BhdGg+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==);background-repeat:no-repeat;background-position:50% 50%}@media (min-width:768px){.browser-warning__content{margin:100px 0}}.browser-warning__list{padding:0;margin-top:70px;list-style:none}.browser-warning__list>li{display:inline-block;min-width:130px;margin:0 15px;padding-top:75px;-webkit-background-size:60px 60px;background-size:60px 60px;background-repeat:no-repeat;background-position:50% 0;margin-bottom:30px}.browser-warning__list>li[data-browser=ie]{background-image:url(data:image/png;base64,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);background-image:none,url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNTZweCIgaGVpZ2h0PSI1NXB4IiB2aWV3Qm94PSIwIDAgNTYgNTUiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDQ2LjIgKDQ0NDk2KSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5GaWxsIDE8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iTm90aWZpY2F0aW9ucy0vLVVuc3VwcG9ydGVkLWJyb3dzZXIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJOb3RpZmljYXRpb25zLUJhbm5lci1iYXIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC00MTAuMDAwMDAwLCAtNTcwLjAwMDAwMCkiIGZpbGw9IiNGRkZGRkYiPgogICAgICAgICAgICA8ZyBpZD0iR3JvdXAtNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzE3LjAwMDAwMCwgMzE0LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQzLjAwMDAwMCwgMjU2LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJHcm91cCI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik04OS45Mjk2ODk0LDUuMzE2MTE3OTYgQzkyLjI1ODUwODIsNC4xOTEzNjU4IDk4LjAyNTUwNDYsMS44MTI0NTM2OCAxMDEuMjk5MDUzLDQuMDIyMDM5ODYgQzEwMy40NjYxMTIsNS40ODQ2NjExOSAxMDUuMjA0MjQ2LDcuNzgxNjQ5ODIgMTAyLjIxOTI1NywxNS41MTcxNTgyIEM5OS4zNTYzNywxMC45MTMwMDU3IDk1LjA0OTEyNSw3LjMwMTMyNzY5IDg5LjkyOTY4OTQsNS4zMTYxMTc5NiBMODkuOTI5Njg5NCw1LjMxNjExNzk2IFogTTY5Ljc0NDE1ODMsMjUuMTQ1NTE2NyBDNjkuOTQ1MzE0MywxOS4zODYwODY1IDc0Ljk1Nzc3OTgsMTQuNzc0NjI4NyA4MS4xMTYzOTE0LDE0Ljc3NDYyODcgQzg3LjI3NDQ4MTIsMTQuNzc0NjI4NyA5Mi4yODc0Njg0LDE5LjM4NjA4NjUgOTIuNDg4NjI0NSwyNS4xNDU1MTY3IEw2OS43NDQxNTgzLDI1LjE0NTUxNjcgWiBNNTUuMjQ1NTI2NCw1MS4zMDgzMzIgQzUzLjQ4MDUxODYsNDkuNDk4MTg4MSA1My4xNjg0Nzg4LDQ1LjA4OTQ1MTggNTcuMDYzMjM2NSwzNy4wNTU3MzE1IEM1OS4wMjg4Nzg1LDQyLjcwNjg4NzEgNjIuOTUxMjkxOCw0Ny40NDI1MzQ2IDY4LjAyMTE1NTksNTAuNDQ3ODc0NCBDNjUuNDk5NzkwOCw1MS44MzU2MTY2IDU4LjgwNjA2NzUsNTQuOTYwMTg5MSA1NS4yNDU1MjY0LDUxLjMwODMzMiBMNTUuMjQ1NTI2NCw1MS4zMDgzMzIgWiBNMTA2LDI4Ljc4NTg5NDEgQzEwNiwyNC4zNTg4OTQ2IDEwNC44NTU0MTksMjAuMTk5ODQyNCAxMDIuODQ4Mjk0LDE2LjU4NTgxNjMgQzExMS40MDM1NTksLTIuNzc2NTY2NDIgOTMuNjgxMjExNCwwLjA1OTQ0NzQ4MDQgOTIuNjk0NDc2OCwwLjI1MjUxNTU4NCBDODguOTM5ODI0LDAuOTg3MjE3OTg5IDg1LjQ2NjE2MzYsMi4xNjY3NTk3NCA4Mi4yNjE3NTQ4LDMuNjYxOTkzOTMgQzgxLjc4OTUyMDcsMy42MzUzODE4NCA4MS4zMTQxNTU3LDMuNjIwNzcxMjggODAuODM1MTM4MSwzLjYyMDc3MTI4IEM2OC44NzcxNzgxLDMuNjIwNzcxMjggNTguODY3NjQwNSwxMS45NjEzMTM0IDU2LjMwNTgzNTUsMjMuMTQyMzA0NyBDNjIuNjA4NDY1NSwxNi4wNzE1NzY3IDY3LjAxOTI4OSwxMy4yMTg2MDQyIDY5LjY2MDY2OTMsMTIuMDc2ODkzMyBDNjkuMjM5MDUwNCwxMi40NTM2MzcgNjguODI2MzAyMSwxMi44MzQ1NTUyIDY4LjQyMDMzNzIsMTMuMjE4MzQzMyBDNjguMjg1MTg5NiwxMy4zNDU5MjQ4IDY4LjE1NDk5OSwxMy40NzUzMzI2IDY4LjAyMTY3NzcsMTMuNjAzNjk2OCBDNjcuNzUzOTkxNCwxMy44NjEyMDc5IDY3LjQ4NjgyNjksMTQuMTE4OTc5OSA2Ny4yMjU5MjQsMTQuMzc5MSBDNjcuMDcwNjg2OCwxNC41MzM4MTU0IDY2LjkxOTYyNDEsMTQuNjg5ODM1MyA2Ni43NjY3MzUsMTQuODQ1NTk0MyBDNjYuNTM1MzE0MiwxNS4wODExODk2IDY2LjMwNDQxNTIsMTUuMzE2NTIzOSA2Ni4wNzg0NzMzLDE1LjU1MzQyMzcgQzY1LjkxODAxODEsMTUuNzIxNzA2IDY1Ljc2MTQ3NjQsMTUuODkwNTEwMiA2NS42MDM4OTEsMTYuMDU5MDUzNCBDNjUuMzkyODIwNiwxNi4yODQ5OTUzIDY1LjE4MzA1NDgsMTYuNTExMTk4IDY0Ljk3NzIwMjQsMTYuNzM4MTgzNSBDNjQuODE3MjY5LDE2LjkxNDU1MzggNjQuNjU5OTQ0NiwxNy4wOTA5MjQyIDY0LjUwMjg4MSwxNy4yNjc4MTYzIEM2NC4zMDc3MjU3LDE3LjQ4NzQ5NjUgNjQuMTE0Mzk2NywxNy43MDcxNzY3IDYzLjkyMzY3NjcsMTcuOTI3Mzc4NyBDNjMuNzY1NTY5NiwxOC4xMTAwMTA3IDYzLjYwODc2NywxOC4yOTI2NDI3IDYzLjQ1MzUyOTgsMTguNDc1NTM1NSBDNjMuMjcyOTg1LDE4LjY4ODk1NDEgNjMuMDk0NTI3NSwxOC45MDIzNzI2IDYyLjkxNzg5NjMsMTkuMTE1NzkxMSBDNjIuNzYxNjE1NSwxOS4zMDQ2ODQ4IDYyLjYwNTU5NTYsMTkuNDkzMzE3NSA2Mi40NTI5Njc0LDE5LjY4MTk1MDMgQzYyLjI4NzU1NSwxOS44ODU5NzYzIDYyLjEyNTc5NTIsMjAuMDg5NzQxNCA2MS45NjQwMzU1LDIwLjI5MzI0NTYgQzYxLjgwNzc1NDcsMjAuNDkwNDg4MiA2MS42NTEyMTMsMjAuNjg3NDY5OCA2MS40OTgzMjM5LDIwLjg4NDQ1MTUgQzYxLjM1Mjc0MDEsMjEuMDcyMDQwNiA2MS4yMTEzMzA4LDIxLjI1ODg0NzEgNjEuMDY4ODc3OCwyMS40NDU5MTQ0IEM2MC45MDgxNjE3LDIxLjY1NzI0NTcgNjAuNzQ2MTQxLDIxLjg2ODU3NyA2MC41ODk1OTkzLDIyLjA3ODg2NDcgQzYwLjQ3NzY3MiwyMi4yMjk0MDU2IDYwLjM3MDE4LDIyLjM3ODM4MTIgNjAuMjYwMzM5OSwyMi41Mjg0MDAzIEM1OS4yNjYwMzkyLDIzLjg4NTA5NTEgNTguMzU3NTc1NSwyNS4yMTU2OTk2IDU3LjUzNzAzNiwyNi40OTM4NjI2IEM1Ny41MzQ5NDg4LDI2LjQ5Njk5MzQgNTcuNTMyODYxNiwyNi41MDAxMjQzIDU3LjUzMTAzNTMsMjYuNTAzMjU1MSBDNTcuMzE1MDA3NywyNi44Mzk4MTk4IDU3LjEwNjU0NjQsMjcuMTcxNDI3MyA1Ni45MDIyNTk0LDI3LjUwMDE2NDkgQzU2Ljg5MTMwMTUsMjcuNTE3OTA2MyA1Ni44Nzk4MjE4LDI3LjUzNTkwODYgNTYuODY4ODYzOSwyNy41NTM5MTA5IEM1Ni42NjQzMTYsMjcuODgzOTUzIDU2LjQ2NjgxMjYsMjguMjA4MjU1MiA1Ni4yNzQyNjYzLDI4LjUyOTE2NTcgQzU2LjI2NzQ4MjgsMjguNTQwMzg0NSA1Ni4yNjA0Mzg0LDI4LjU1MTg2NDIgNTYuMjUzNjU1LDI4LjU2MzA4MzEgQzU1LjczNTc2MjgsMjkuNDI2OTMyNCA1NS4yNTU5NjI1LDMwLjI1OTQ3MzMgNTQuODIzNjQ2NSwzMS4wNDMyMjU1IEM1Mi41NTcxODM1LDM1LjE1MDYxODkgNTEuNDUzODI1NCwzOC4wMjAyODkzIDUxLjQwNjA4MDEsMzguMTkwNjU4OSBDNDQuMjQ4OTkzNCw2My43Nzc5MjI1IDY2LjU4NjQ1MTEsNTIuOTcyNjMxMiA2OS43MDM0NTc0LDUxLjM1OTcyOTkgQzczLjA1OTcxMTYsNTMuMDE3NzY3NCA3Ni44MzgxMDY2LDUzLjk1MTAxNjkgODAuODM1MTM4MSw1My45NTEwMTY5IEM5MS43Nzc0MDMzLDUzLjk1MTAxNjkgMTAxLjA4NzE5OSw0Ni45NjYzODY5IDEwNC41NTI1MTEsMzcuMjEyNTM0MSBMOTEuMzI5OTU1LDM3LjIxMjUzNDEgQzg5LjM3MzQ0NDUsNDAuNTE3OTEyMiA4NS42MDY3OTAyLDQyLjc1NjcxOTUgODEuMjc5NDU1Niw0Mi43NTY3MTk1IEM3NC45MzkyNTU3LDQyLjc1NjcxOTUgNjkuNzk5NzMwNiwzNy45NTI5NzY0IDY5Ljc5OTczMDYsMzIuMDI3MDkwMSBMMTA1Ljc5Mjg0MywzMi4wMjcwOTAxIEMxMDUuOTI5MDM0LDMwLjk2NTczNzMgMTA2LDI5Ljg4NDAzNDIgMTA2LDI4Ljc4NTg5NDEgTDEwNiwyOC43ODU4OTQxIFoiIGlkPSJGaWxsLTEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==)}.browser-warning__list>li[data-browser=firefox]{background-image:url(data:image/png;base64,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);background-image:none,url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNTZweCIgaGVpZ2h0PSI1NnB4IiB2aWV3Qm94PSIwIDAgNTYgNTYiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDQ2LjIgKDQ0NDk2KSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5GaWxsIDM8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iTm90aWZpY2F0aW9ucy0vLVVuc3VwcG9ydGVkLWJyb3dzZXIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJOb3RpZmljYXRpb25zLUJhbm5lci1iYXIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01NTIuMDAwMDAwLCAtNTcwLjAwMDAwMCkiIGZpbGw9IiNGRkZGRkYiPgogICAgICAgICAgICA8ZyBpZD0iR3JvdXAtNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzE3LjAwMDAwMCwgMzE0LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQzLjAwMDAwMCwgMjU2LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJHcm91cC0yIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNDIuMDAwMDAwLCAwLjAwMDAwMCkiPgogICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNzguMDY2NTY4OSwxLjg3MTEwNDU5IEM4My4wMzMzMjcyLDEuODcxMTA0NTkgODcuNjc4MDAzNSwzLjIyOTU4ODcxIDkxLjYzNTQ2NTUsNS41ODc4MDIzNCBMODMuODAzNDUzNyw1LjM4NjEwMjUzIEM4OC4zMTEwMDYxLDYuMjI3OTgwMDEgOTEuMTI2ODMxMSw4Ljg2MDQ0MTYxIDkxLjEyNjgzMTEsOC44NjA0NDE2MSBMODYuOTUzMzE5Miw5Ljk1NTgzOTAyIEM5NC4xNjI2OTI0LDExLjcxMzczNjYgOTcuMjkzNDI0MywxOC4zMjQzODgyIDk3LjI5MzQyNDMsMTguMzI0Mzg4MiBMOTUuNDk5NjUxMiwxOC41NjQzNTUyIEM5Ni45NzkzMTQ3LDIyLjExNjgyMyA5NS40OTk2NTEyLDI3Ljg4ODc4NjEgOTUuNDk5NjUxMiwyNy44ODg3ODYxIEw5My4yMzQ3MTM4LDI2LjM3ODgyNzggQzkzLjIzNDcxMzgsMjYuMzc4ODI3OCA5My4yNjQyMTE0LDMwLjg1NTI4ODEgOTIuMTg0NzU4NiwzMy4yMTc0ODc5IEM4Ni44ODYzNTE3LDQyLjUxMTYyMzkgNzYuMjU5MjQyOSwzOS45MDg2NTk5IDczLjk2NDAxMDYsMzkuMTgwNzg2NyBDNzEuNjY5NTc1NiwzOC40NTIxMTYyIDcwLjU0MzA4NjEsMzYuNzQ1MjQxNSA3MC41NDMwODYxLDM2Ljc0NTI0MTUgQzcwLjU0MzA4NjEsMzYuNzQ1MjQxNSA3MS40MTEyNzIzLDM2Ljg2MTYzNzUgNzQuMTc0NDgsMzYuODYxNjM3NSBDNzYuOTM3Njg3NywzNi44NjE2Mzc1IDgwLjU0NTE2NDYsMzMuODI1Nzc2MiA4Mi4xNDUyMTAyLDMzLjMwMDQgQzgzLjc0NjA1MywzMi43NzU4MjExIDgzLjg4NjM2NTksMzIuMzE1ODE3OSA4Mi42MzM5MTM3LDMwLjg1NTI4ODEgQzgxLjM4MDY2NDMsMjkuMzk1NTU1NCA3OC4wODMzMTA4LDI5Ljg5NjIxNzQgNzguMDgzMzEwOCwyOS44OTYyMTc0IEM3OC4wODMzMTA4LDI5Ljg5NjIxNzQgNzMuNzY2Mjk3LDMyLjEwMTM2MjQgNzAuNDgyNDk2NSwzMS4xOTk2OTI1IEM2Ny4xOTg2OTYsMzAuMjk3MjI1MyA2Ny4zMjIyNjcsMjUuNDA2MjA0MiA2Ny4zMjIyNjcsMjUuNDA2MjA0MiBMNzEuNDExMjcyMywyNS4zMjAxMDMxIEw3MS40NDE1NjcxLDIxLjcyMTM5NTcgQzcxLjQ0MTU2NzEsMjEuNzIxMzk1NyA3NS44NzQ5NzY5LDE4LjMyNzU3NzEgNzYuOTUzNjMyNCwxNy4wNzQzMjc3IEM3OC4wMzMwODUxLDE1LjgyMTg3NTUgNzYuNzgwNjMyOSwxNS4wMTM0ODE4IDc2Ljc4MDYzMjksMTUuMDEzNDgxOCBMNzAuNTQ2Mjc1MSwxNS4wMTM0ODE4IEM3MC41NDYyNzUxLDEzLjcwMzYyODggNjkuNTg3MjA0NCwxMi4zMTMyNTU0IDY5LjU4NzIwNDQsMTIuMzEzMjU1NCBMNzEuNTU4NzYwMyw4LjE5Nzk0MTQzIEw2NS4yOTgwOTM4LDExLjczNjA1OTEgTDU4Ljg0MDUxMDgsMTEuMTU3MjY4MyBMNTguNDM2MzEzOSwxMC41ODI0NjM3IEM2My4yMzU2NTM0LDUuMjQ1Nzg5NjIgNzAuMjQ1NzE4NCwxLjg3MTEwNDU5IDc4LjA2NjU2ODksMS44NzExMDQ1OSBNNzguMDAwMzk4NiwwIEM2OS44MDg4MzUsMCA2Mi40NDAwMTU0LDMuNDY3OTYxMjIgNTcuMzIwMTg4NSw4Ljk5NTE3MzkgTDU1LjA3NTE4MTksNS44MDIyNTc4OCBMNTMuNTcwMDA3LDE0LjExNjU5NTIgQzUxLjMwMDI4NjEsMTguMTA0MzUyIDUwLDIyLjcwMDM5NzIgNTAsMjcuNTk4NTkzNSBDNTAsNDIuODQwODgwOSA2Mi41MzY0ODA1LDU1LjE5NzE4NjkgNzguMDAwMzk4Niw1NS4xOTcxODY5IEM5My40NjM1MTk1LDU1LjE5NzE4NjkgMTA2LDQyLjg0MDg4MDkgMTA2LDI3LjU5ODU5MzUgQzEwNiwxMi4zNTYzMDYgOTMuNDYzNTE5NSwwIDc4LjAwMDM5ODYsMCIgaWQ9IkZpbGwtMyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+)}.browser-warning__list>li[data-browser=chrome]{background-image:url(data:image/png;base64,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);background-image:none,url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNTZweCIgaGVpZ2h0PSI1NnB4IiB2aWV3Qm94PSIwIDAgNTYgNTYiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDQ2LjIgKDQ0NDk2KSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5GaWxsIDE8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iTm90aWZpY2F0aW9ucy0vLVVuc3VwcG9ydGVkLWJyb3dzZXIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJOb3RpZmljYXRpb25zLUJhbm5lci1iYXIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC02OTQuMDAwMDAwLCAtNTcwLjAwMDAwMCkiIGZpbGw9IiNGRkZGRkYiPgogICAgICAgICAgICA8ZyBpZD0iR3JvdXAtNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzE3LjAwMDAwMCwgMzE0LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQzLjAwMDAwMCwgMjU2LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJHcm91cC0zIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyODQuMDAwMDAwLCAwLjAwMDAwMCkiPgogICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNzQuMzUxNzI5Niw1NS43NjU0MzY2IEM2MC42MTExNjQ5LDUzLjk3NzA5MjUgNTAsNDIuMjI3ODkwNSA1MCwyOC4wMDA0MDQ0IEM1MCwyMi4zODU0NDA5IDUxLjY1MjQ1OSwxNy4xNTYyOTM4IDU0LjQ5Nzk1NjIsMTIuNzc0MDAxNiBMNjYuMjY2NTcwNCwzMy4xNTgzNzM3IEM2OC4yNTE0NjI0LDM3LjY2Njg0NDggNzIuNzU4MzE1OSw0MC44MTQwMzkxIDc4LjAwMDQwNDQsNDAuODE0MDM5MSBDODAuMDc4MzEzLDQwLjgxNDAzOTEgODIuMDQwNTU3NSw0MC4zMTkwMjk0IDgzLjc3NjMyNywzOS40NDA2Mjk3IEw3NC4zNTE3Mjk2LDU1Ljc2NTQzNjYgWiBNNzYuNDMyODczNSw1NS45NTcxMzE1IEw4Ny44MjM3NTk3LDM2LjIyNzkxOTQgQzg5LjY4OTc1MjMsMzQuMDAxOTkzMiA5MC44MTQwMzkxLDMxLjEzMjIzMDggOTAuODE0MDM5MSwyOC4wMDA0MDQ0IEM5MC44MTQwMzkxLDIzLjM4NTk3NTMgODguMzc0NTc5MywxOS4zNDA5NjkyIDg0LjcxNTM4OTYsMTcuMDg1MTE1OSBMMTAzLjc5MjY3NywxNy4wODUxMTU5IEMxMDUuMjE0NjE3LDIwLjQzOTM3MzEgMTA2LDI0LjEyNzY4MTEgMTA2LDI4LjAwMDQwNDQgQzEwNiw0My40NjQ2MDYxIDkzLjQ2Mzc5NzIsNTYuMDAwODA4OCA3OC4wMDA0MDQ0LDU2LjAwMDgwODggQzc3LjQ3Mzg0OTksNTYuMDAwODA4OCA3Ni45NTEzMzk2LDU1Ljk4NTQ0MDkgNzYuNDMyODczNSw1NS45NTcxMzE1IEw3Ni40MzI4NzM1LDU1Ljk1NzEzMTUgWiBNNTUuNzAxNTA5NCwxMS4wNjI0OTczIEM2MC44MTY2MTAxLDQuMzM5NDIzNyA2OC45MDA5NjA1LDAgNzguMDAwNDA0NCwwIEM4OC44NDY5NDE2LDAgOTguMjUyOTM1Nyw2LjE2NzQwMDg4IDEwMi45MDI5NTQsMTUuMTg2NzY5NyBMNzcuNTI1NjE1NywxNS4xODY3Njk3IEw3Ny41MjU2MTU3LDE1LjE5NDg1ODEgQzcwLjgzMjQ2OTEsMTUuNDM5MTI3NiA2NS40NDk2NDI1LDIwLjgxNjI5MjMgNjUuMTk1NjY2OSwyNy41MDYyMDM1IEw1NS43MDE1MDk0LDExLjA2MjQ5NzMgWiBNNzguMDAwNDA0NCwzNy45NjYxMTU0IEM3Mi40OTYyNTE5LDM3Ljk2NjExNTQgNjguMDMzODg0NiwzMy41MDQ1NTY5IDY4LjAzMzg4NDYsMjguMDAwNDA0NCBDNjguMDMzODg0NiwyMi40OTYyNTE5IDcyLjQ5NjI1MTksMTguMDMzODg0NiA3OC4wMDA0MDQ0LDE4LjAzMzg4NDYgQzgzLjUwMzc0ODEsMTguMDMzODg0NiA4Ny45NjYxMTU0LDIyLjQ5NjI1MTkgODcuOTY2MTE1NCwyOC4wMDA0MDQ0IEM4Ny45NjYxMTU0LDMzLjUwNDU1NjkgODMuNTAzNzQ4MSwzNy45NjYxMTU0IDc4LjAwMDQwNDQsMzcuOTY2MTE1NCBMNzguMDAwNDA0NCwzNy45NjYxMTU0IFoiIGlkPSJGaWxsLTEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==)} \ No newline at end of file diff --git a/client/src/boot/BootRoutes.js b/client/src/boot/BootRoutes.js index 6c32d8f89..f0a0d8267 100644 --- a/client/src/boot/BootRoutes.js +++ b/client/src/boot/BootRoutes.js @@ -5,14 +5,14 @@ import $ from 'jquery'; import React from 'react'; import { Provider } from 'react-redux'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { BrowserRouter as Router, Prompt } from 'react-router-dom'; -import { renderRoutes } from 'react-router-config'; +import renderReactRoutes from 'lib/renderReactRoutes'; import Config from 'lib/Config'; import pageRouter from 'lib/Router'; import reactRouteRegister from 'lib/ReactRouteRegister'; import App from 'containers/App/App'; -import { ApolloProvider } from 'react-apollo'; +import { ApolloProvider } from '@apollo/client'; // TODO If this doesn't work, checkout https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/#react-apollo import i18n from 'i18n'; import { isDirty } from 'redux-form'; import getFormState from 'lib/getFormState'; @@ -110,7 +110,8 @@ class BootRoutes { component: App, }); - ReactDOM.render( + const reactRoot = createRoot(document.getElementsByClassName('cms-content')[0]); + reactRoot.render( - {renderRoutes([reactRouteRegister.getRootRoute()])} + {renderReactRoutes([reactRouteRegister.getRootRoute()])} - , - document.getElementsByClassName('cms-content')[0] + ); } @@ -185,10 +185,8 @@ class BootRoutes { // with an event handler is rendered, which means the page router will intercept // events that should be caught by react component event handlers. // Note that this empty link is rendered into an element that doesn't exist in the DOM. - ReactDOM.render( - {}} />, - document.createElement('div') - ); + const root = createRoot(document.createElement('div')); + root.render( {}} />); // Start the page router pageRouter.start(); diff --git a/client/src/boot/apollo/buildCache.js b/client/src/boot/apollo/buildCache.js index 10547c2d2..704be2298 100644 --- a/client/src/boot/apollo/buildCache.js +++ b/client/src/boot/apollo/buildCache.js @@ -1,16 +1,20 @@ -import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; +import { InMemoryCache } from '@apollo/client/cache'; import dataIdFromObject from './dataIdFromObject'; -const buildCache = (introspectionQueryResultData) => ( - new InMemoryCache({ - fragmentMatcher: introspectionQueryResultData - ? new IntrospectionFragmentMatcher({ - introspectionQueryResultData, - }) - : null, +const buildCache = (introspectionQueryResultData) => { + const possibleTypes = {}; + if (introspectionQueryResultData) { + introspectionQueryResultData.__schema.types.forEach(supertype => { + if (supertype.possibleTypes) { + possibleTypes[supertype.name] = supertype.possibleTypes.map(subtype => subtype.name); + } + }); + } + return new InMemoryCache({ + possibleTypes, dataIdFromObject, addTypename: true, - }) -); + }); +}; export default buildCache; diff --git a/client/src/boot/apollo/buildClient.js b/client/src/boot/apollo/buildClient.js index 9df3e109a..3970f5d97 100644 --- a/client/src/boot/apollo/buildClient.js +++ b/client/src/boot/apollo/buildClient.js @@ -1,11 +1,9 @@ -/* global window */ -import ApolloClient from 'apollo-client'; -import { withClientState } from 'apollo-link-state'; -import { from } from 'apollo-link'; +// import { withClientState } from '@apollo/client/link/state'; // probably doesn't work +import { ApolloClient, from } from '@apollo/client'; +import Config from 'lib/Config'; import getGraphqlFragments from './getGraphqlFragments'; import buildNetworkComponents from './buildNetworkComponents'; import buildCache from './buildCache'; -import Config from 'lib/Config'; const buildClient = async (baseUrl) => { const graphQLConfig = Config.getSection('SilverStripe\\Admin\\LeftAndMain').graphql; @@ -19,11 +17,7 @@ const buildClient = async (baseUrl) => { } const cache = buildCache(fragmentData); const components = buildNetworkComponents(baseUrl); - const stateLink = withClientState({ - cache, - resolvers: {} - }); - const link = from([stateLink, ...components]); + const link = from(components); return new ApolloClient({ cache, link }); }; diff --git a/client/src/boot/apollo/buildNetworkComponents.js b/client/src/boot/apollo/buildNetworkComponents.js index 9a35f5dc1..f7b1d8a6e 100644 --- a/client/src/boot/apollo/buildNetworkComponents.js +++ b/client/src/boot/apollo/buildNetworkComponents.js @@ -1,6 +1,5 @@ -import { HttpLink } from 'apollo-link-http'; -import { onError } from 'apollo-link-error'; -import { ApolloLink } from 'apollo-link'; +import { ApolloLink, HttpLink } from '@apollo/client'; +import { onError } from '@apollo/client/link/error'; import Config from 'lib/Config'; const buildNetworkComponents = (baseUrl) => { diff --git a/client/src/bundles/bundle.js b/client/src/bundles/bundle.js index 5ae798bc0..631e82f9d 100644 --- a/client/src/bundles/bundle.js +++ b/client/src/bundles/bundle.js @@ -3,118 +3,116 @@ import/no-extraneous-dependencies, import/no-unresolved */ + // Legacy translation handler -require('i18n.js'); +import 'i18n.js'; // Expose fields (see webpack config for matching "externals" config) -require('expose-loader?SilverStripeComponent!lib/SilverStripeComponent'); -require('expose-loader?Backend!lib/Backend'); -require('expose-loader?schemaFieldValues!lib/schemaFieldValues'); -require('expose-loader?FormAlert!components/FormAlert/FormAlert'); -require('expose-loader?Injector!lib/Injector'); -require('expose-loader?reduxFieldReducer!lib/reduxFieldReducer'); -require('expose-loader?getFormState!lib/getFormState'); -require('expose-loader?PopoverField!components/PopoverField/PopoverField'); -require('expose-loader?FieldHolder!components/FieldHolder/FieldHolder'); -require('expose-loader?Form!components/Form/Form'); -require('expose-loader?FormConstants!components/Form/FormConstants'); -require('expose-loader?FormAction!components/FormAction/FormAction'); -require('expose-loader?SchemaActions!state/schema/SchemaActions'); -require('expose-loader?ToastsActions!state/toasts/ToastsActions'); -require('expose-loader?FileStatusIcon!components/FileStatusIcon/FileStatusIcon'); -require('expose-loader?FormBuilder!components/FormBuilder/FormBuilder'); -require('expose-loader?FormBuilderLoader!containers/FormBuilderLoader/FormBuilderLoader'); -require('expose-loader?FormBuilderModal!components/FormBuilderModal/FormBuilderModal'); -require('expose-loader?FileSchemaModalHandler!containers/InsertLinkModal/fileSchemaModalHandler'); -require('expose-loader?InsertLinkModal!containers/InsertLinkModal/InsertLinkModal'); -require('expose-loader?RecordsActions!state/records/RecordsActions'); -require('expose-loader?GridField!components/GridField/GridField'); -require('expose-loader?GridFieldCell!components/GridField/GridFieldCell'); -require('expose-loader?GridFieldHeader!components/GridField/GridFieldHeader'); -require('expose-loader?GridFieldHeaderCell!components/GridField/GridFieldHeaderCell'); -require('expose-loader?GridFieldRow!components/GridField/GridFieldRow'); -require('expose-loader?GridFieldTable!components/GridField/GridFieldTable'); -require('expose-loader?Accordion!components/Accordion/Accordion'); -require('expose-loader?AccordionBlock!components/Accordion/AccordionBlock'); -require('expose-loader?Button!components/Button/Button'); -require('expose-loader?BackButton!components/Button/BackButton'); -require('expose-loader?HiddenField!components/HiddenField/HiddenField'); -require('expose-loader?ListGroup!components/ListGroup/ListGroup'); -require('expose-loader?ListGroupItem!components/ListGroup/ListGroupItem'); -require('expose-loader?Loading!components/Loading/Loading'); -require('expose-loader?TextField!components/TextField/TextField'); -require('expose-loader?LiteralField!components/LiteralField/LiteralField'); -require('expose-loader?Toolbar!components/Toolbar/Toolbar'); -require('expose-loader?FileStatusIcon!components/FileStatusIcon/FileStatusIcon'); -require('expose-loader?Breadcrumb!components/Breadcrumb/Breadcrumb'); -require('expose-loader?ResizeAware!components/ResizeAware/ResizeAware'); -require('expose-loader?TabsActions!state/tabs/TabsActions'); -require('expose-loader?Tag!components/Tag/Tag'); -require('expose-loader?TagList!components/Tag/TagList'); -require('expose-loader?CompactTagList!components/Tag/CompactTagList'); -require('expose-loader?Tip!components/Tip/Tip'); -require('expose-loader?Search!components/Search/Search'); -require('expose-loader?SearchToggle!components/Search/SearchToggle'); -require('expose-loader?TreeDropdownFieldNode!components/TreeDropdownField/TreeDropdownFieldNode'); -require('expose-loader?TreeDropdownFieldMenu!components/TreeDropdownField/TreeDropdownFieldMenu'); -require('expose-loader?TreeDropdownField!components/TreeDropdownField/TreeDropdownField'); -require('expose-loader?BreadcrumbsActions!state/breadcrumbs/BreadcrumbsActions'); -require('expose-loader?RecordsActionTypes!state/records/RecordsActionTypes'); -require('expose-loader?UnsavedFormsActions!state/unsavedForms/UnsavedFormsActions'); -require('expose-loader?Badge!components/Badge/Badge'); -require('expose-loader?Button!components/Button/Button'); -require('expose-loader?BackButton!components/Button/BackButton'); -require('expose-loader?VersionedBadge!components/VersionedBadge/VersionedBadge'); -require('expose-loader?CheckboxSetField!components/CheckboxSetField/CheckboxSetField'); -require('expose-loader?Preview!components/Preview/Preview'); -require('expose-loader?ViewModeStates!state/viewMode/ViewModeStates'); -require('expose-loader?ViewModeActions!state/viewMode/ViewModeActions'); -require('expose-loader?ViewModeToggle!components/ViewModeToggle/ViewModeToggle'); -require('expose-loader?Focusedzone!components/Focusedzone/Focusedzone'); -require('expose-loader?Config!lib/Config'); -require('expose-loader?DataFormat!lib/DataFormat'); -require('expose-loader?ReactRouteRegister!lib/ReactRouteRegister'); -require('expose-loader?Router!lib/Router'); -require('expose-loader?TinyMCEActionRegistrar!lib/TinyMCEActionRegistrar'); -require('expose-loader?ShortcodeSerialiser!lib/ShortcodeSerialiser'); -require('expose-loader?formatWrittenNumber!lib/formatWrittenNumber'); -require('expose-loader?withDragDropContext!lib/withDragDropContext'); +import 'expose-loader?exposes=SilverStripeComponent!lib/SilverStripeComponent'; +import 'expose-loader?exposes=Backend!lib/Backend'; +import 'expose-loader?exposes=schemaFieldValues!lib/schemaFieldValues'; +import 'expose-loader?exposes=FormAlert!components/FormAlert/FormAlert'; +import 'expose-loader?exposes=Injector!lib/Injector'; +import 'expose-loader?exposes=reduxFieldReducer!lib/reduxFieldReducer'; +import 'expose-loader?exposes=getFormState!lib/getFormState'; +import 'expose-loader?exposes=PopoverField!components/PopoverField/PopoverField'; +import 'expose-loader?exposes=FieldHolder!components/FieldHolder/FieldHolder'; +import 'expose-loader?exposes=Form!components/Form/Form'; +import 'expose-loader?exposes=FormConstants!components/Form/FormConstants'; +import 'expose-loader?exposes=FormAction!components/FormAction/FormAction'; +import 'expose-loader?exposes=SchemaActions!state/schema/SchemaActions'; +import 'expose-loader?exposes=ToastsActions!state/toasts/ToastsActions'; +import 'expose-loader?exposes=FileStatusIcon!components/FileStatusIcon/FileStatusIcon'; +import 'expose-loader?exposes=FormBuilder!components/FormBuilder/FormBuilder'; +import 'expose-loader?exposes=FormBuilderLoader!containers/FormBuilderLoader/FormBuilderLoader'; +import 'expose-loader?exposes=FormBuilderModal!components/FormBuilderModal/FormBuilderModal'; +import 'expose-loader?exposes=FileSchemaModalHandler!containers/InsertLinkModal/fileSchemaModalHandler'; +import 'expose-loader?exposes=InsertLinkModal!containers/InsertLinkModal/InsertLinkModal'; +import 'expose-loader?exposes=RecordsActions!state/records/RecordsActions'; +import 'expose-loader?exposes=GridField!components/GridField/GridField'; +import 'expose-loader?exposes=GridFieldCell!components/GridField/GridFieldCell'; +import 'expose-loader?exposes=GridFieldHeader!components/GridField/GridFieldHeader'; +import 'expose-loader?exposes=GridFieldHeaderCell!components/GridField/GridFieldHeaderCell'; +import 'expose-loader?exposes=GridFieldRow!components/GridField/GridFieldRow'; +import 'expose-loader?exposes=GridFieldTable!components/GridField/GridFieldTable'; +import 'expose-loader?exposes=Accordion!components/Accordion/Accordion'; +import 'expose-loader?exposes=AccordionBlock!components/Accordion/AccordionBlock'; +import 'expose-loader?exposes=Button!components/Button/Button'; +import 'expose-loader?exposes=BackButton!components/Button/BackButton'; +import 'expose-loader?exposes=HiddenField!components/HiddenField/HiddenField'; +import 'expose-loader?exposes=ListGroup!components/ListGroup/ListGroup'; +import 'expose-loader?exposes=ListGroupItem!components/ListGroup/ListGroupItem'; +import 'expose-loader?exposes=Loading!components/Loading/Loading'; +import 'expose-loader?exposes=TextField!components/TextField/TextField'; +import 'expose-loader?exposes=LiteralField!components/LiteralField/LiteralField'; +import 'expose-loader?exposes=Toolbar!components/Toolbar/Toolbar'; +import 'expose-loader?exposes=Breadcrumb!components/Breadcrumb/Breadcrumb'; +import 'expose-loader?exposes=ResizeAware!components/ResizeAware/ResizeAware'; +import 'expose-loader?exposes=TabsActions!state/tabs/TabsActions'; +import 'expose-loader?exposes=Tag!components/Tag/Tag'; +import 'expose-loader?exposes=TagList!components/Tag/TagList'; +import 'expose-loader?exposes=CompactTagList!components/Tag/CompactTagList'; +import 'expose-loader?exposes=Tip!components/Tip/Tip'; +import 'expose-loader?exposes=Search!components/Search/Search'; +import 'expose-loader?exposes=SearchToggle!components/Search/SearchToggle'; +import 'expose-loader?exposes=TreeDropdownFieldNode!components/TreeDropdownField/TreeDropdownFieldNode'; +import 'expose-loader?exposes=TreeDropdownFieldMenu!components/TreeDropdownField/TreeDropdownFieldMenu'; +import 'expose-loader?exposes=TreeDropdownField!components/TreeDropdownField/TreeDropdownField'; +import 'expose-loader?exposes=BreadcrumbsActions!state/breadcrumbs/BreadcrumbsActions'; +import 'expose-loader?exposes=RecordsActionTypes!state/records/RecordsActionTypes'; +import 'expose-loader?exposes=UnsavedFormsActions!state/unsavedForms/UnsavedFormsActions'; +import 'expose-loader?exposes=Badge!components/Badge/Badge'; +import 'expose-loader?exposes=VersionedBadge!components/VersionedBadge/VersionedBadge'; +import 'expose-loader?exposes=CheckboxSetField!components/CheckboxSetField/CheckboxSetField'; +import 'expose-loader?exposes=Preview!components/Preview/Preview'; +import 'expose-loader?exposes=ViewModeStates!state/viewMode/ViewModeStates'; +import 'expose-loader?exposes=ViewModeActions!state/viewMode/ViewModeActions'; +import 'expose-loader?exposes=ViewModeToggle!components/ViewModeToggle/ViewModeToggle'; +import 'expose-loader?exposes=Focusedzone!components/Focusedzone/Focusedzone'; +import 'expose-loader?exposes=Config!lib/Config'; +import 'expose-loader?exposes=DataFormat!lib/DataFormat'; +import 'expose-loader?exposes=ReactRouteRegister!lib/ReactRouteRegister'; +import 'expose-loader?exposes=Router!lib/Router'; +import 'expose-loader?exposes=TinyMCEActionRegistrar!lib/TinyMCEActionRegistrar'; +import 'expose-loader?exposes=ShortcodeSerialiser!lib/ShortcodeSerialiser'; +import 'expose-loader?exposes=formatWrittenNumber!lib/formatWrittenNumber'; +import 'expose-loader?exposes=withDragDropContext!lib/withDragDropContext'; +import 'expose-loader?exposes=withRouter!lib/withRouter'; // Legacy CMS -require('../legacy/jquery.changetracker'); -require('../legacy/sspath'); -require('../legacy/ssui.core'); -require('../legacy/LeftAndMain'); -require('../legacy/LeftAndMain.ActionTabSet'); -require('../legacy/LeftAndMain.Panel'); -require('../legacy/LeftAndMain.Tree'); -require('../legacy/LeftAndMain.Content'); -require('../legacy/LeftAndMain.EditForm'); -require('../legacy/LeftAndMain.Menu'); -require('../legacy/LeftAndMain.MobileMenuToggle'); -require('../legacy/LeftAndMain.Preview'); -require('../legacy/LeftAndMain.BatchActions'); -require('../legacy/LeftAndMain.FieldHelp'); -require('../legacy/LeftAndMain.FieldDescriptionToggle'); -require('../legacy/LeftAndMain.TreeDropdownField'); -require('../legacy/AddToCampaignForm'); -require('../legacy/SecurityAdmin'); -require('../legacy/ModelAdmin'); -require('../legacy/ToastsContainer'); +import '../legacy/jquery.changetracker'; +import '../legacy/sspath'; +import '../legacy/ssui.core'; +import '../legacy/LeftAndMain'; +import '../legacy/LeftAndMain.ActionTabSet'; +import '../legacy/LeftAndMain.Panel'; +import '../legacy/LeftAndMain.Tree'; +import '../legacy/LeftAndMain.Content'; +import '../legacy/LeftAndMain.EditForm'; +import '../legacy/LeftAndMain.Menu'; +import '../legacy/LeftAndMain.MobileMenuToggle'; +import '../legacy/LeftAndMain.Preview'; +import '../legacy/LeftAndMain.BatchActions'; +import '../legacy/LeftAndMain.FieldHelp'; +import '../legacy/LeftAndMain.FieldDescriptionToggle'; +import '../legacy/LeftAndMain.TreeDropdownField'; +import '../legacy/AddToCampaignForm'; +import '../legacy/SecurityAdmin'; +import '../legacy/ModelAdmin'; +import '../legacy/ToastsContainer'; // Legacy form fields // Fields used by core legacy UIs, or available to users // To do: determine better way of using webpack to pull in optional javascript -require('../legacy/ConfirmedPasswordField'); -require('../legacy/SelectionGroup'); -require('../legacy/DateField'); -require('../legacy/ToggleCompositeField'); -require('../legacy/TreeDropdownField/TreeDropdownFieldEntwine'); -require('../legacy/UsedOnTable/UsedOnTableEntwine'); -require('../legacy/DateField'); -require('../legacy/DatetimeField'); -require('../legacy/HtmlEditorField'); -require('../legacy/TabSet'); -require('../legacy/GridField'); +import '../legacy/ConfirmedPasswordField'; +import '../legacy/SelectionGroup'; +import '../legacy/DateField'; +import '../legacy/ToggleCompositeField'; +import '../legacy/TreeDropdownField/TreeDropdownFieldEntwine'; +import '../legacy/UsedOnTable/UsedOnTableEntwine'; +import '../legacy/DatetimeField'; +import '../legacy/HtmlEditorField'; +import '../legacy/TabSet'; +import '../legacy/GridField'; -require('boot'); +import 'boot'; diff --git a/client/src/bundles/vendor.js b/client/src/bundles/vendor.js index 23a17a44d..fd1283faf 100644 --- a/client/src/bundles/vendor.js +++ b/client/src/bundles/vendor.js @@ -1,60 +1,56 @@ /* eslint-disable import/no-webpack-loader-syntax, - import/no-extraneous-dependencies, import/no-unresolved, import/extensions */ -// TODO Enable require(*.css) includes once https://github.com/webpack/extract-text-webpack-plugin/issues/179 +// TODO Enable import *.css) includes once https://github.com/webpack/extract-text-webpack-plugin/issues/179 // is resolved. Included in bundle.scss for now. -require('babel-polyfill'); -require('json-js'); +import 'core-js/stable'; // jQuery plugins require that the jQuery object is exposed as a global // webpack.ProvidePlugin is used to ensure that jQuery and $ are provided to all includes -require('script-loader!../../../thirdparty/jquery/jquery.js'); -require('expose-loader?jQuery!jquery'); +import '../../../thirdparty/jquery/jquery.js'; +// import 'expose-loader?exposes=$,jQuery!../../../thirdparty/jquery/jquery.js'; // Expose the libraries as globals for other modules to access // Note that these are order-dependent - earlier items should not depend on later ones -require('expose-loader?PropTypes!prop-types'); -require('expose-loader?classnames!classnames'); -require('expose-loader?DeepFreezeStrict!deep-freeze-strict'); -require('expose-loader?React!react'); -require('expose-loader?ReactDom!react-dom'); -require('expose-loader?ReactRouterDom!react-router-dom'); -require('expose-loader?Reactstrap!reactstrap'); -require('expose-loader?IsomorphicFetch!isomorphic-fetch'); -require('expose-loader?Redux!redux'); -require('expose-loader?ReactRedux!react-redux'); -require('expose-loader?ReduxThunk!redux-thunk'); -require('expose-loader?ReduxForm!redux-form'); -require('expose-loader?ReactSelect!react-select'); -require('expose-loader?ReactDND!react-dnd'); -require('expose-loader?ReactDNDHtml5Backend!react-dnd-html5-backend'); -require('expose-loader?Page!page.js'); -require('expose-loader?validator!validator'); -require('expose-loader?ApolloClient!apollo-client'); -require('expose-loader?ReactApollo!react-apollo'); -require('expose-loader?GraphQLTag!graphql-tag'); -require('expose-loader?GraphQLFragments!graphql-fragments'); -require('expose-loader?NodeUrl!url'); -require('expose-loader?qs!qs'); -require('expose-loader?modernizr!modernizr'); -require('expose-loader?history!history'); -require('expose-loader?moment!moment'); -require('expose-loader?merge!merge'); +import 'expose-loader?exposes=PropTypes!prop-types'; +import 'expose-loader?exposes=classnames!classnames'; +import 'expose-loader?exposes=DeepFreezeStrict!deep-freeze-strict'; +import 'expose-loader?exposes=React!react'; +import 'expose-loader?exposes=ReactDom!react-dom'; +import 'expose-loader?exposes=ReactRouterDom!react-router-dom'; +import 'expose-loader?exposes=Reactstrap!reactstrap'; +import 'expose-loader?exposes=IsomorphicFetch!isomorphic-fetch'; +import 'expose-loader?exposes=Redux!redux'; +import 'expose-loader?exposes=ReactRedux!react-redux'; +import 'expose-loader?exposes=ReduxThunk!redux-thunk'; +import 'expose-loader?exposes=ReduxForm!redux-form'; +import 'expose-loader?exposes=qs!qs'; +import 'expose-loader?exposes=ReactSelect!react-select'; +import 'expose-loader?exposes=ReactDND!react-dnd'; +import 'expose-loader?exposes=ReactDNDHtml5Backend!react-dnd-html5-backend'; +import 'expose-loader?exposes=Page!page.js'; +import 'expose-loader?exposes=validator!validator'; +// import 'expose-loader?exposes=ApolloClient!@apollo/client'; +import 'expose-loader?exposes=GraphQLTag!graphql-tag'; +import 'expose-loader?exposes=GraphQLFragments!graphql-fragments'; +import 'expose-loader?exposes=NodeUrl!url'; +import 'expose-loader?exposes=modernizr!modernizr'; +import 'expose-loader?exposes=moment!moment'; +import 'expose-loader?exposes=merge!merge'; -require('../../../thirdparty/jquery-ondemand/jquery.ondemand.js'); -require('../../../thirdparty/jquery-ui/jquery-ui.js'); -// require('../../../thirdparty/jquery-ui-themes/smoothness/jquery-ui.css'); -require('../../../thirdparty/jquery-entwine/dist/jquery.entwine-dist.js'); -require('../../../thirdparty/jquery-cookie/jquery.cookie.js'); -require('../../../thirdparty/jquery-query/jquery.query.js'); -require('../../../thirdparty/jquery-form/jquery.form.js'); -require('jquery-sizes/lib/jquery.sizes.js'); -require('../../../thirdparty/jstree/jquery.jstree.js'); -// require('../../../thirdparty/stree/themes/apple/style.css'); -require('../../../thirdparty/jquery-hoverIntent/jquery.hoverIntent.js'); +import '../../../thirdparty/jquery-ondemand/jquery.ondemand.js'; +import '../../../thirdparty/jquery-ui/jquery-ui.js'; +// import '../../../thirdparty/jquery-ui-themes/smoothness/jquery-ui.css'; +import '../../../thirdparty/jquery-entwine/dist/jquery.entwine-dist.js'; +import '../../../thirdparty/jquery-cookie/jquery.cookie.js'; +import '../../../thirdparty/jquery-query/jquery.query.js'; +import '../../../thirdparty/jquery-form/jquery.form.js'; +import 'jquery-sizes/lib/jquery.sizes.js'; +import '../../../thirdparty/jstree/jquery.jstree.js'; +// import '../../../thirdparty/stree/themes/apple/style.css'; +import '../../../thirdparty/jquery-hoverIntent/jquery.hoverIntent.js'; -require('chosen-js'); +import 'chosen-js'; diff --git a/client/src/components/GridFieldActions/GridFieldActions.js b/client/src/components/GridFieldActions/GridFieldActions.js index 2a0a88202..826c9c031 100644 --- a/client/src/components/GridFieldActions/GridFieldActions.js +++ b/client/src/components/GridFieldActions/GridFieldActions.js @@ -37,7 +37,7 @@ class GridFieldActions extends PureComponent { return groupsList; }, []); - const dropdownMenuProps = { right: true }; + const dropdownMenuProps = { end: true }; const dropdownToggleClassNames = [ 'action-menu__toggle', 'btn', diff --git a/client/src/components/Toasts/Toasts.js b/client/src/components/Toasts/Toasts.js index 9dcc9a0b9..13997bc5d 100644 --- a/client/src/components/Toasts/Toasts.js +++ b/client/src/components/Toasts/Toasts.js @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; -import Toast, { toastPropType } from './Toast'; +import Toast from './Toast'; /** * Time in milliseconds to wait before we action the pause/resume calls. @@ -44,7 +44,7 @@ const Toasts = ({ toasts, onDismiss, onPause, onResume }) => { }; Toasts.propTypes = { - toasts: PropTypes.arrayOf(PropTypes.shape(toastPropType)).isRequired, + toasts: PropTypes.arrayOf(PropTypes.shape(Toast.propTypes)).isRequired, onDismiss: PropTypes.func.isRequired, onPause: PropTypes.func.isRequired, onResume: PropTypes.func.isRequired, diff --git a/client/src/components/TreeDropdownField/TreeDropdownField.js b/client/src/components/TreeDropdownField/TreeDropdownField.js index 1ebcb8d50..227445ef6 100644 --- a/client/src/components/TreeDropdownField/TreeDropdownField.js +++ b/client/src/components/TreeDropdownField/TreeDropdownField.js @@ -701,30 +701,30 @@ class TreeDropdownField extends Component { // Hack! Temporary fix until we can do a proper upgrade of react-select to >= 2.0. // eslint-disable-next-line func-names -Select.prototype.componentWillReceiveProps = function (nextProps) { - function handleRequired(value, multi) { - if (!value) { - return true; - } - return multi ? value.length === 0 : Object.keys(value).length === 0; - } - - const valueArray = this.getValueArray(nextProps.value, nextProps); - - if (nextProps.required) { - this.setState({ - required: handleRequired(valueArray[0], nextProps.multi) - }); - } else if (this.props.required) { - // Used to be required but it's not any more - this.setState({ required: false }); - } - // Array comparison in react-select is broken. - const [current, next] = [this.props.value, nextProps.value].map(JSON.stringify); - if (this.state.inputValue && current !== next && nextProps.onSelectResetsInput) { - this.setState({ inputValue: this.handleInputValueChange('') }); - } -}; +// Select.prototype.componentWillReceiveProps = function (nextProps) { +// function handleRequired(value, multi) { +// if (!value) { +// return true; +// } +// return multi ? value.length === 0 : Object.keys(value).length === 0; +// } + +// const valueArray = this.getValueArray(nextProps.value, nextProps); + +// if (nextProps.required) { +// this.setState({ +// required: handleRequired(valueArray[0], nextProps.multi) +// }); +// } else if (this.props.required) { +// // Used to be required but it's not any more +// this.setState({ required: false }); +// } +// // Array comparison in react-select is broken. +// const [current, next] = [this.props.value, nextProps.value].map(JSON.stringify); +// if (this.state.inputValue && current !== next && nextProps.onSelectResetsInput) { +// this.setState({ inputValue: this.handleInputValueChange('') }); +// } +// }; TreeDropdownField.propTypes = { extraClass: PropTypes.string, diff --git a/client/src/components/TreeDropdownField/TreeDropdownField.scss b/client/src/components/TreeDropdownField/TreeDropdownField.scss index 18118f692..b2eb003cd 100644 --- a/client/src/components/TreeDropdownField/TreeDropdownField.scss +++ b/client/src/components/TreeDropdownField/TreeDropdownField.scss @@ -1,5 +1,3 @@ -@import "~react-select/dist/react-select.css"; - .treedropdownfield__option+.treedropdownfield__option { border-top: 1px solid $border-color-light; } diff --git a/client/src/components/TreeDropdownField/treeUtils.js b/client/src/components/TreeDropdownField/treeUtils.js index 92e111a62..b2d57d0dd 100644 --- a/client/src/components/TreeDropdownField/treeUtils.js +++ b/client/src/components/TreeDropdownField/treeUtils.js @@ -35,7 +35,7 @@ export const findTreeByPath = (tree, path) => { * @param {*} id - id property of node to find path for * @return {Object} - The tree if found, or null if not found. */ -const findTreeByID = (tree, id) => { +export const findTreeByID = (tree, id) => { // No valid tree if (!id || !tree || !tree.children || Object.keys(tree).length === 0) { return null; diff --git a/client/src/containers/App/App.js b/client/src/containers/App/App.js index a9db4f66d..b42f89a54 100644 --- a/client/src/containers/App/App.js +++ b/client/src/containers/App/App.js @@ -1,13 +1,13 @@ import React from 'react'; import { provideInjector } from 'lib/Injector'; -import { renderRoutes } from 'react-router-config'; +import renderReactRoutes from 'lib/renderReactRoutes'; /** * Empty container for the moment, will eventually contain the CMS menu` * and apply to document.body, rather than just one specific DOM element. */ const App = ({ route }) => ( - {renderRoutes(route.routes())} + {renderReactRoutes(route.routes())} ); export default provideInjector(App); diff --git a/client/src/legacy/AddToCampaignForm.js b/client/src/legacy/AddToCampaignForm.js index 56be14b48..190b20048 100644 --- a/client/src/legacy/AddToCampaignForm.js +++ b/client/src/legacy/AddToCampaignForm.js @@ -3,6 +3,7 @@ import i18n from 'i18n'; import jQuery from 'jquery'; import React from 'react'; import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { loadComponent } from 'lib/Injector'; const FormBuilderModal = loadComponent('FormBuilderModal'); @@ -44,6 +45,7 @@ jQuery.entwine('ss', ($) => { * The "add to campaign" dialog is used in a similar fashion in AssetAdmin. */ $('#add-to-campaign__dialog-wrapper').entwine({ + ReactRoot: null, onunmatch() { // solves errors given by ReactDOM "no matched root found" error. @@ -69,7 +71,11 @@ jQuery.entwine('ss', ($) => { const modalSchemaUrl = `${sectionConfig.form.AddToCampaignForm.schemaUrl}/${id}`; const title = i18n._t('Admin.ADD_TO_CAMPAIGN', 'Add to campaign'); - ReactDOM.render( + let root = this.getReactRoot(); + if (!root) { + root = createRoot(this[0]); + } + root.render( { responseClassBad="modal__response modal__response--error" responseClassGood="modal__response modal__response--good" identifier="Admin.AddToCampaign" - />, - this[0] + /> ); + this.setReactRoot(root); }, _clearModal() { - ReactDOM.unmountComponentAtNode(this[0]); + const root = this.getReactRoot(); + if (root) { + root.unmount(); + this.setReactRoot(null); + } // this.empty(); }, diff --git a/client/src/legacy/ConfirmedPasswordField.js b/client/src/legacy/ConfirmedPasswordField.js index bc4a5ccab..464e4d265 100644 --- a/client/src/legacy/ConfirmedPasswordField.js +++ b/client/src/legacy/ConfirmedPasswordField.js @@ -1,7 +1,7 @@ import $ from 'jquery'; // TODO Enable once https://github.com/webpack/extract-text-webpack-plugin/issues/179 is resolved. Included in bundle.scss for now. -// require('../styles/legacy/ConfirmedPasswordField.scss'); +// import '../styles/legacy/ConfirmedPasswordField.scss'; $(document).on('click', '.confirmedpassword .showOnClick a', function () { var $container = $('.showOnClickContainer', $(this).parent()); diff --git a/client/src/legacy/DatetimeField.js b/client/src/legacy/DatetimeField.js index b1feb2c02..92dee8a47 100644 --- a/client/src/legacy/DatetimeField.js +++ b/client/src/legacy/DatetimeField.js @@ -6,7 +6,7 @@ import i18n from 'i18n'; import moment from 'moment'; import modernizr from 'modernizr'; -require('../../../thirdparty/jquery-entwine/dist/jquery.entwine-dist.js'); +import '../../../thirdparty/jquery-entwine/dist/jquery.entwine-dist.js'; jQuery.entwine('ss', ($) => { $('input[type=datetime-local]').entwine({ diff --git a/client/src/legacy/GridField.js b/client/src/legacy/GridField.js index adef98cc0..2705a5773 100644 --- a/client/src/legacy/GridField.js +++ b/client/src/legacy/GridField.js @@ -2,15 +2,16 @@ import $ from 'jquery'; import i18n from 'i18n'; import React from 'react'; import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import Search from 'components/Search/Search.js'; import { schemaMerge } from 'lib/schemaFieldValues'; import { loadComponent } from 'lib/Injector'; -require('../../../thirdparty/jquery-ui/jquery-ui.js'); -require('../../../thirdparty/jquery-entwine/dist/jquery.entwine-dist.js'); +import '../../../thirdparty/jquery-ui/jquery-ui.js'; +import '../../../thirdparty/jquery-entwine/dist/jquery.entwine-dist.js'; // TODO Enable once https://github.com/webpack/extract-text-webpack-plugin/issues/179 is resolved. Included in bundle.scss for now. -// require('../styles/legacy/GridField.scss'); +// import '../styles/legacy/GridField.scss'; $.entwine('ss', function($) { $('.grid-field').entwine({ @@ -218,9 +219,9 @@ $.entwine('ss', function($) { * Function buildURLString splits string to "key => value" array * and replaces values for existing keys with the new value * and returns string with unique keys only - * - * @param {string} url - * @returns string + * + * @param {string} url + * @returns string */ buildURLString: function(url) { const link = [window.location.origin, url].join('/'); @@ -249,6 +250,7 @@ $.entwine('ss', function($) { Timer: null, Component: null, Actions: null, + ReactRoot: null, onmatch() { this._super(); @@ -275,10 +277,10 @@ $.entwine('ss', function($) { onunmatch() { this._super(); - // solves errors given by ReactDOM "no matched root found" error. - const container = this[0]; - if (container) { - ReactDOM.unmountComponentAtNode(container); + const root = this.getReactRoot(); + if (root) { + root.unmount(); + this.setReactRoot(null); } const actions = this.getActions(); @@ -296,10 +298,14 @@ $.entwine('ss', function($) { const GridFieldActions = this.getComponent(); // TODO: rework entwine so that react has control of holder - ReactDOM.render( - , - this[0] + let root = this.getReactRoot(); + if (!root) { + root = createRoot(this[0]); + } + root.render( + ); + this.setReactRoot(root); }, }) @@ -631,6 +637,7 @@ $.entwine('ss', function($) { $('.js-injector-boot .grid-field .grid-field__search-holder').entwine({ Component: null, + ReactRoot: null, onmatch() { this._super(); @@ -651,10 +658,10 @@ $.entwine('ss', function($) { onunmatch() { this._super(); - // solves errors given by ReactDOM "no matched root found" error. - const container = this[0]; - if (container) { - ReactDOM.unmountComponentAtNode(container); + const root = this.getReactRoot(); + if (root) { + root.unmount(); + this.setReactRoot(null); } }, @@ -722,7 +729,11 @@ $.entwine('ss', function($) { const handleSearch = (data) => this.search(data); const idName = String(props.gridfield).replace(/\-/g, '.'); - ReactDOM.render( + let root = this.getReactRoot(); + if (!root) { + root = createRoot(this[0]); + } + root.render( , - this[0] + /> ); + this.setReactRoot(root); }, }); @@ -798,7 +809,7 @@ $.entwine('ss', function($) { const gridField = $(this).getGridField(); const successCallback = function() { gridField.keepStateInHistory(); - }; + }; gridField.reload({ data: ajaxData }, successCallback); diff --git a/client/src/legacy/LeftAndMain.MobileMenuToggle.js b/client/src/legacy/LeftAndMain.MobileMenuToggle.js index 4cd402ccb..815d32392 100644 --- a/client/src/legacy/LeftAndMain.MobileMenuToggle.js +++ b/client/src/legacy/LeftAndMain.MobileMenuToggle.js @@ -1,7 +1,7 @@ import $ from 'jquery'; import MobileMenuToggleContainer from 'components/MobileMenuToggle/MobileMenuToggleContainer'; import { closeMobileMenu } from 'state/mobileMenu/MobileMenuActions'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; $.entwine('ss', function($){ @@ -10,10 +10,8 @@ $.entwine('ss', function($){ onmatch: function() { const menuToggleWrapper = $('.cms-mobile-menu-toggle-wrapper'); if (menuToggleWrapper.length > 0) { - ReactDOM.render( - , - menuToggleWrapper[0] - ); + const root = createRoot(menuToggleWrapper[0]); + root.render(); } const store = window.ss.store; diff --git a/client/src/legacy/LeftAndMain.js b/client/src/legacy/LeftAndMain.js index 7a608bf79..3d5f2d20c 100644 --- a/client/src/legacy/LeftAndMain.js +++ b/client/src/legacy/LeftAndMain.js @@ -4,13 +4,14 @@ import $ from 'jquery'; import React from 'react'; import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import IframeDialog from 'components/IframeDialog/IframeDialog'; import Search from 'components/Search/Search'; import Loading from 'components/Loading/Loading'; import { schemaMerge } from 'lib/schemaFieldValues'; import { loadComponent } from 'lib/Injector'; -require('../legacy/ssui.core.js'); +import '../legacy/ssui.core.js'; $.noConflict(); @@ -1045,7 +1046,11 @@ $.entwine('ss', function($) { BackURL: window.location.href, }); - ReactDOM.render( + let root = this.getReactRoot(); + if (!root) { + root = createRoot(this[0]); + } + root.render( , - this[0] + /> ); }, @@ -1081,20 +1085,24 @@ $.entwine('ss', function($) { * like the breadcrumbs showing unnecessary loading status. */ $('form.loading,.cms-content.loading,.cms-content-fields.loading,.cms-content-view.loading,.ss-gridfield-item.loading').entwine({ + ReactRoot: null, onmatch: function() { this._super(); const container = $(''); this.append(container); - ReactDOM.render( - , - container[0] - ); + const root = createRoot(container[0]); + root.render(); + this.setReactRoot(root); }, onunmatch: function() { this._super(); const container = this.find('.cms-loading-container'); if (container && container.length) { - ReactDOM.unmountComponentAtNode(container[0]); + const root = this.getReactRoot(); + if (root) { + root.unmount(); + this.setReactRoot(null); + } container.remove(); } } @@ -1447,6 +1455,7 @@ $.entwine('ss', function($) { $('.js-injector-boot .search-holder').entwine({ Component: null, + ReactRoot: null, onmatch() { this._super(); @@ -1466,10 +1475,10 @@ $.entwine('ss', function($) { onunmatch() { this._super(); - // solves errors given by ReactDOM "no matched root found" error. - const container = this[0]; - if (container) { - ReactDOM.unmountComponentAtNode(container); + const root = this.getReactRoot(); + if (root) { + root.unmount(); + this.setReactRoot(null); } }, @@ -1523,7 +1532,11 @@ $.entwine('ss', function($) { const handleSearch = (data) => this.search(data); const narrowView = this.closest('.cms-content-tools').attr('id') === 'cms-content-tools-CMSMain'; - ReactDOM.render( + let root = this.getReactRoot(); + if (!root) { + root = createRoot(this[0]); + } + root.render( , - this[0] + /> ); + this.setReactRoot(root); }, }); }); diff --git a/client/src/legacy/ModelAdmin.js b/client/src/legacy/ModelAdmin.js index 170a6707d..3aef908f5 100644 --- a/client/src/legacy/ModelAdmin.js +++ b/client/src/legacy/ModelAdmin.js @@ -3,7 +3,7 @@ */ import $ from 'jquery'; -require('./LeftAndMain.js'); +import './LeftAndMain.js'; $.entwine('ss', function($){ $('.cms-content-tools #Form_SearchForm').entwine({ diff --git a/client/src/legacy/PermissionCheckboxSetField.js b/client/src/legacy/PermissionCheckboxSetField.js index a81bc99b5..c28dea047 100644 --- a/client/src/legacy/PermissionCheckboxSetField.js +++ b/client/src/legacy/PermissionCheckboxSetField.js @@ -1,7 +1,7 @@ import $ from 'jquery'; // TODO Enable once https://github.com/webpack/extract-text-webpack-plugin/issues/179 is resolved. Included in bundle.scss for now. -// require('../styles/legacy/CheckboxSetField.scss'); +// import '../styles/legacy/CheckboxSetField.scss'; $.entwine('ss', function($){ /** diff --git a/client/src/legacy/SecurityAdmin.js b/client/src/legacy/SecurityAdmin.js index a382e8f63..504918d39 100644 --- a/client/src/legacy/SecurityAdmin.js +++ b/client/src/legacy/SecurityAdmin.js @@ -3,8 +3,8 @@ */ import $ from 'jquery'; -require('./LeftAndMain.js'); -require('./PermissionCheckboxSetField.js'); +import './LeftAndMain.js'; +import './PermissionCheckboxSetField.js'; var refreshAfterImport = function(e) { // Check for a message , an indication that the form has been submitted. diff --git a/client/src/legacy/SelectionGroup.js b/client/src/legacy/SelectionGroup.js index bfb31f692..f8af79976 100644 --- a/client/src/legacy/SelectionGroup.js +++ b/client/src/legacy/SelectionGroup.js @@ -1,7 +1,7 @@ import $ from 'jquery'; // TODO Enable once https://github.com/webpack/extract-text-webpack-plugin/issues/179 is resolved. Included in bundle.scss for now. -// require('../styles/legacy/SelectionGroup.scss'); +// import '../styles/legacy/SelectionGroup.scss'; $(document).ready(function() { diff --git a/client/src/legacy/TabSet.js b/client/src/legacy/TabSet.js index 965b0300d..d6390d1ee 100644 --- a/client/src/legacy/TabSet.js +++ b/client/src/legacy/TabSet.js @@ -1,11 +1,11 @@ import $ from 'jquery'; -require('../../../thirdparty/jquery-ui/jquery-ui.js'); -require('../../../thirdparty/jquery-cookie/jquery.cookie.js'); -require('../../../thirdparty/jquery-entwine/dist/jquery.entwine-dist.js'); +import '../../../thirdparty/jquery-ui/jquery-ui.js'; +import '../../../thirdparty/jquery-cookie/jquery.cookie.js'; +import '../../../thirdparty/jquery-entwine/dist/jquery.entwine-dist.js'; // TODO Enable once https://github.com/webpack/extract-text-webpack-plugin/issues/179 is resolved. Included in bundle.scss for now. -// require('../../../thirdparty/jquery-ui-themes/smoothness/jquery-ui.css'); +// import '../../../thirdparty/jquery-ui-themes/smoothness/jquery-ui.css'; $.entwine('ss', function($){ $('.ss-tabset, .cms-tabset').entwine({ diff --git a/client/src/legacy/TinyMCE_sslink-email.js b/client/src/legacy/TinyMCE_sslink-email.js index 62e182ff2..7ae58d049 100644 --- a/client/src/legacy/TinyMCE_sslink-email.js +++ b/client/src/legacy/TinyMCE_sslink-email.js @@ -2,7 +2,7 @@ import i18n from 'i18n'; import TinyMCEActionRegistrar from 'lib/TinyMCEActionRegistrar'; import React from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import jQuery from 'jquery'; import { createInsertLinkModal } from 'containers/InsertLinkModal/InsertLinkModal'; import { loadComponent } from 'lib/Injector'; @@ -66,7 +66,11 @@ jQuery.entwine('ss', ($) => { const requireLinkText = tagName !== 'A' && selectionContent.trim() === ''; // create/update the react component - ReactDOM.render( + let root = this.getReactRoot(); + if (!root) { + root = createRoot(this[0]); + } + root.render( { fileAttributes={attrs} identifier="Admin.InsertLinkEmailModal" requireLinkText={requireLinkText} - />, - this[0] + /> ); }, diff --git a/client/src/legacy/TinyMCE_sslink-external.js b/client/src/legacy/TinyMCE_sslink-external.js index 4ae80c7a5..fae4caa9e 100644 --- a/client/src/legacy/TinyMCE_sslink-external.js +++ b/client/src/legacy/TinyMCE_sslink-external.js @@ -2,7 +2,7 @@ import i18n from 'i18n'; import TinyMCEActionRegistrar from 'lib/TinyMCEActionRegistrar'; import React from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import jQuery from 'jquery'; import { createInsertLinkModal } from 'containers/InsertLinkModal/InsertLinkModal'; import { loadComponent } from 'lib/Injector'; @@ -61,7 +61,11 @@ jQuery.entwine('ss', ($) => { const requireLinkText = tagName !== 'A' && selectionContent.trim() === ''; // create/update the react component - ReactDOM.render( + let root = this.getReactRoot(); + if (!root) { + root = createRoot(this[0]); + } + root.render( { fileAttributes={attrs} identifier="Admin.InsertLinkExternalModal" requireLinkText={requireLinkText} - />, - this[0] + /> ); }, diff --git a/client/src/legacy/ToastsContainer.js b/client/src/legacy/ToastsContainer.js index 71d83a99a..84147040c 100644 --- a/client/src/legacy/ToastsContainer.js +++ b/client/src/legacy/ToastsContainer.js @@ -1,7 +1,7 @@ /* global window */ import jQuery from 'jquery'; import React from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import Injector, { loadComponent } from 'lib/Injector'; import { display } from 'state/toasts/ToastsActions'; @@ -15,7 +15,8 @@ jQuery.entwine('ss', ($) => { onmatch() { const container = $(''); this.append(container); - ReactDOM.render(, container[0]); + const root = createRoot(container[0]); + root.render(); }, }); }); diff --git a/client/src/legacy/ToggleCompositeField.js b/client/src/legacy/ToggleCompositeField.js index 8a59ee04f..062a90a62 100644 --- a/client/src/legacy/ToggleCompositeField.js +++ b/client/src/legacy/ToggleCompositeField.js @@ -1,10 +1,10 @@ import $ from 'jquery'; // entwine also required, but can't be included more than once without error -require('../../../thirdparty/jquery-ui/jquery-ui.js'); +import '../../../thirdparty/jquery-ui/jquery-ui.js'; // TODO Enable once https://github.com/webpack/extract-text-webpack-plugin/issues/179 is resolved. Included in bundle.scss for now. -// require('../../../thirdparty/jquery-ui-themes/smoothness/jquery-ui.css'); +// import '../../../thirdparty/jquery-ui-themes/smoothness/jquery-ui.css'; $.entwine('ss', function($){ $('.ss-toggle').entwine({ diff --git a/client/src/legacy/TreeDropdownField/TreeDropdownFieldEntwine.js b/client/src/legacy/TreeDropdownField/TreeDropdownFieldEntwine.js index f380f34fd..46208cf7e 100644 --- a/client/src/legacy/TreeDropdownField/TreeDropdownFieldEntwine.js +++ b/client/src/legacy/TreeDropdownField/TreeDropdownFieldEntwine.js @@ -2,6 +2,7 @@ import jQuery from 'jquery'; import React from 'react'; import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { schemaMerge } from 'lib/schemaFieldValues'; import { MULTI_EMPTY_VALUE } from 'components/TreeDropdownField/TreeDropdownField'; import { loadComponent } from 'lib/Injector'; @@ -11,6 +12,7 @@ jQuery.entwine('ss', ($) => { Value: null, Timer: null, Component: null, + ReactRoot: null, onmatch() { this._super(); @@ -42,10 +44,10 @@ jQuery.entwine('ss', ($) => { onunmatch() { this._super(); - // solves errors given by ReactDOM "no matched root found" error. - const container = this[0]; - if (container) { - ReactDOM.unmountComponentAtNode(container); + const root = this.getReactRoot(); + if (root) { + root.unmount(); + this.setReactRoot(null); } }, @@ -67,15 +69,19 @@ jQuery.entwine('ss', ($) => { const TreeDropdownField = this.getComponent(); // TODO: rework entwine so that react has control of holder - ReactDOM.render( + let root = this.getReactRoot(); + if (!root) { + root = createRoot(this[0]); + } + root.render( , - this[0] + /> ); + this.setReactRoot(root); }, getAttributes() { diff --git a/client/src/legacy/UsedOnTable/UsedOnTableEntwine.js b/client/src/legacy/UsedOnTable/UsedOnTableEntwine.js index 82ef7a75c..0d6ea9070 100644 --- a/client/src/legacy/UsedOnTable/UsedOnTableEntwine.js +++ b/client/src/legacy/UsedOnTable/UsedOnTableEntwine.js @@ -2,6 +2,7 @@ import jQuery from 'jquery'; import React from 'react'; import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { schemaMerge } from 'lib/schemaFieldValues'; import { loadComponent } from 'lib/Injector'; @@ -9,6 +10,7 @@ jQuery.entwine('ss', ($) => { $('.js-injector-boot .used-on__polyfill-holder').entwine({ Timer: null, Component: null, + ReactRoot: null, onmatch() { this._super(); @@ -26,10 +28,10 @@ jQuery.entwine('ss', ($) => { onunmatch() { this._super(); - // solves errors given by ReactDOM "no matched root found" error. - const container = this[0]; - if (container) { - ReactDOM.unmountComponentAtNode(container); + const root = this.getReactRoot(); + if (root) { + root.unmount(); + this.setReactRoot(null); } }, @@ -39,10 +41,12 @@ jQuery.entwine('ss', ($) => { const UsedOnTable = this.getComponent(); // TODO: rework entwine so that react has control of holder - ReactDOM.render( - , - this[0] - ); + let root = this.getReactRoot(); + if (!root) { + root = createRoot(this[0]); + } + root.render(); + this.setReactRoot(root); }, getAttributes() { diff --git a/client/src/legacy/ssui.core.js b/client/src/legacy/ssui.core.js index 81d055062..3488cda08 100644 --- a/client/src/legacy/ssui.core.js +++ b/client/src/legacy/ssui.core.js @@ -1,6 +1,6 @@ import $ from 'jquery'; -require('../../../thirdparty/jquery-ui/jquery-ui.js'); +import '../../../thirdparty/jquery-ui/jquery-ui.js'; /** * Extends jQueryUI dialog with iframe abilities (and related resizing logic), diff --git a/client/src/lib/dependency-injection/ApolloGraphqlProxy.js b/client/src/lib/dependency-injection/ApolloGraphqlProxy.js index c69d4e6de..1701fce2f 100644 --- a/client/src/lib/dependency-injection/ApolloGraphqlProxy.js +++ b/client/src/lib/dependency-injection/ApolloGraphqlProxy.js @@ -1,4 +1,4 @@ -import { graphql } from 'react-apollo'; +import { graphql } from '@apollo/client/react/hoc'; // TODO If this doesn't work, checkout https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/#react-apollo class ApolloGraphqlProxy { /** diff --git a/client/src/lib/dependency-injection/loadComponent.js b/client/src/lib/dependency-injection/loadComponent.js index aa517aa7d..c7c624f84 100644 --- a/client/src/lib/dependency-injection/loadComponent.js +++ b/client/src/lib/dependency-injection/loadComponent.js @@ -1,11 +1,11 @@ /* global window */ import React, { Component } from 'react'; import { Provider } from 'react-redux'; -import { ApolloProvider } from 'react-apollo'; +import { ApolloProvider } from '@apollo/client'; // TODO If this doesn't work, checkout https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/#react-apollo +import NotFoundComponent from 'components/NotFoundComponent/NotFoundComponent'; import provideInjector from './provideInjector'; import withInjector from './withInjector'; import Injector from './Container'; -import NotFoundComponent from 'components/NotFoundComponent/NotFoundComponent'; import contextType from './injectorContext'; /** diff --git a/client/src/lib/dependency-injection/tests/loadComponent-test.js b/client/src/lib/dependency-injection/tests/loadComponent-test.js index 3f5526cca..21bb3136a 100644 --- a/client/src/lib/dependency-injection/tests/loadComponent-test.js +++ b/client/src/lib/dependency-injection/tests/loadComponent-test.js @@ -46,7 +46,7 @@ jest.mock('../provideInjector', () => function mockInjector(Injected) { }); jest.mock('../Container', () => ({ ready: (callback) => { callback(); } })); -jest.mock('react-apollo', () => ({ +jest.mock('@apollo/client', () => ({ // TODO If this doesn't work, checkout https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/#react-apollo ApolloProvider: ({ children }) => {children}, })); diff --git a/client/src/lib/renderReactRoutes.js b/client/src/lib/renderReactRoutes.js new file mode 100644 index 000000000..aec75c5ac --- /dev/null +++ b/client/src/lib/renderReactRoutes.js @@ -0,0 +1,19 @@ +import React from 'react'; +import { Routes, Route } from 'react-router'; + +const renderReactRoutes = (routes) => (routes ? ( + + {routes.map((route) => ( + ( + // eslint-disable-next-line react/jsx-props-no-spreading + + )} + /> + ))} + +) : null); + +export default renderReactRoutes; diff --git a/client/src/styles/browser-warning.scss b/client/src/styles/browser-warning.scss deleted file mode 100644 index 34c15500f..000000000 --- a/client/src/styles/browser-warning.scss +++ /dev/null @@ -1,10 +0,0 @@ -// For IE version 9 and below. These browsers doesn't handle large -// resource files so need to break browser detection and warning code into -// its own file - -// Variables -@import "variables"; -@import "~bootstrap/scss/mixins"; - -// Components -@import "../components/BrowserWarning/BrowserWarning"; diff --git a/client/src/styles/legacy/_actionTabs.scss b/client/src/styles/legacy/_actionTabs.scss index 2ffc0f3df..d27faac73 100644 --- a/client/src/styles/legacy/_actionTabs.scss +++ b/client/src/styles/legacy/_actionTabs.scss @@ -206,13 +206,12 @@ $border: 1px solid darken(#D9D9D9, 15%); border: none; } &.loading { - background: transparent url("../images/network-save.gif") no-repeat ($spacer / 2) center; + background: transparent url('../../images/network-save.gif') no-repeat ($spacer / 2) center; .ui-button-text { padding-left: $spacer /* icon */ + ($spacer/4); } } } - } } } diff --git a/client/src/styles/legacy/_forms.scss b/client/src/styles/legacy/_forms.scss index 0e74fd6c3..3e6fb9c75 100644 --- a/client/src/styles/legacy/_forms.scss +++ b/client/src/styles/legacy/_forms.scss @@ -307,7 +307,7 @@ input.loading, button.loading, input.ui-state-default.loading, .ui-widget-content input.ui-state-default.loading, .ui-widget-header input.ui-state-default.loading { .ui-icon { - background: transparent url("../images/network-save.gif") no-repeat 0 0; + background: transparent url('../../images/network-save.gif') no-repeat 0 0; } color: $body-color; @@ -317,7 +317,7 @@ input.ui-state-default.loading, .ui-widget-content input.ui-state-default.loadin input.loading, button.loading { &.ss-ui-action-constructive .ui-icon { - background: transparent url("../images/network-save-constructive.gif") no-repeat 0 0; + background: transparent url('../../images/network-save-constructive.gif') no-repeat 0 0; } } @@ -473,7 +473,7 @@ button.loading { } .ss-ui-loading-icon { - background: url("../images/network-save.gif") no-repeat; + background: url('../../images/network-save.gif') no-repeat; display: block; width: 16px; height: 16px; diff --git a/client/src/styles/legacy/_retina.scss b/client/src/styles/legacy/_retina.scss index 08c385467..ab81076eb 100644 --- a/client/src/styles/legacy/_retina.scss +++ b/client/src/styles/legacy/_retina.scss @@ -17,7 +17,7 @@ .tree-holder, .cms-tree { &.jstree-apple { ins { - background-image: url(../images/sitetree_ss_default_icons@2x.png); + background-image: url('../../images/sitetree_ss_default_icons@2x.png'); background-size: 108px 72px; } } diff --git a/client/src/styles/legacy/_sprity.scss b/client/src/styles/legacy/_sprity.scss index 04b53953d..31289bf64 100644 --- a/client/src/styles/legacy/_sprity.scss +++ b/client/src/styles/legacy/_sprity.scss @@ -37,5 +37,5 @@ $sprites-32x32-2x-dialog-close-over: -0px -506px 60px 60px; } @mixin icon-sprites($dimension) { - background-image: url('../images/sprites/sprite-sprites-#{$dimension}.png'); + background-image: url('../../images/sprites/sprite-sprites-#{$dimension}.png'); } diff --git a/client/src/styles/legacy/_style.scss b/client/src/styles/legacy/_style.scss index c07064d2f..842c1881d 100644 --- a/client/src/styles/legacy/_style.scss +++ b/client/src/styles/legacy/_style.scss @@ -1405,7 +1405,7 @@ form.member-profile-form { text-indent: -9999em; display: inline-block; width: 20px; - background: url(../images/question.png) no-repeat 0px 0px; + background: url('../../images/question.png') no-repeat 0px 0px; } } @@ -1597,7 +1597,7 @@ form.member-profile-form { font-size: $font-size-root +1; padding: 0; border: 0; - background: transparent url(../images/textures/cms_content_header.png) repeat; + background: transparent url('../../images/textures/cms_content_header.png') repeat; box-shadow: $shadow-level-4 0 0 ($spacer / 4) inset; .ui-dialog-title { @@ -1610,7 +1610,7 @@ form.member-profile-form { overflow: auto; // TODO Replace with proper $.layout grid &.loading { - background-image: url("../images/spinner.gif"); + background-image: url('../../images/spinner.gif'); background-position: 50% 50%; background-repeat: no-repeat; } @@ -1652,7 +1652,7 @@ form.member-profile-form { } &.loading { - background-image: url("../images/spinner.gif"); + background-image: url('../../images/spinner.gif'); background-position: 50% 50%; background-repeat: no-repeat; } diff --git a/client/src/styles/legacy/_tree.scss b/client/src/styles/legacy/_tree.scss index 8c40a58d7..6cf5a76fe 100644 --- a/client/src/styles/legacy/_tree.scss +++ b/client/src/styles/legacy/_tree.scss @@ -489,7 +489,7 @@ } ins { background-color: transparent; - background-image: url(../images/sitetree_ss_default_icons.png); + background-image: url('../../images/sitetree_ss_default_icons.png'); &.font-icon-drag-handle { background: none; @@ -743,7 +743,7 @@ a .jstree-pageicon { &.jstree-loading { li#record-0 > .jstree-icon { - background: url(../images/throbber.gif) top left no-repeat; + background: url('../../images/throbber.gif') top left no-repeat; } } @@ -754,7 +754,7 @@ a .jstree-pageicon { background-image: none !important; } .jstree-pageicon { - background: url(../images/throbber.gif) top left no-repeat; + background: url('../../images/throbber.gif') top left no-repeat; } } } diff --git a/client/src/styles/legacy/_uitheme.scss b/client/src/styles/legacy/_uitheme.scss index 783d633cb..616ad5dfa 100644 --- a/client/src/styles/legacy/_uitheme.scss +++ b/client/src/styles/legacy/_uitheme.scss @@ -77,7 +77,7 @@ /** sorry about the !important but the specificity of other selectors mandates it over writing out very specific selectors **/ &-loading { - background-image: url(../images/throbber.gif) !important; + background-image: url('../../images/throbber.gif') !important; background-position: 97% center !important; background-repeat: no-repeat !important; background-size: auto !important; diff --git a/code/LeftAndMain.php b/code/LeftAndMain.php index bc72fa42f..564369d20 100644 --- a/code/LeftAndMain.php +++ b/code/LeftAndMain.php @@ -684,7 +684,7 @@ protected function init() Requirements::javascript('silverstripe/admin: thirdparty/bootstrap/js/dist/collapse.js'); Requirements::javascript('silverstripe/admin: thirdparty/bootstrap/js/dist/tooltip.js'); Requirements::customScript( - "window.jQuery('body').tooltip({ selector: '[data-toggle=tooltip]' });", + "window.jQuery('body').tooltip({ selector: '[data-bs-toggle=tooltip]' });", 'bootstrap.tooltip-boot' ); diff --git a/templates/SilverStripe/Admin/Includes/BackLink_Button.ss b/templates/SilverStripe/Admin/Includes/BackLink_Button.ss index 2253fda11..2c94243da 100644 --- a/templates/SilverStripe/Admin/Includes/BackLink_Button.ss +++ b/templates/SilverStripe/Admin/Includes/BackLink_Button.ss @@ -1,5 +1,5 @@ <% if $Backlink %> - <%t SilverStripe\Admin\LeftAndMain.NavigateUp "Navigate up a folder" %> + <%t SilverStripe\Admin\LeftAndMain.NavigateUp "Navigate up a folder" %> <% end_if %> diff --git a/templates/SilverStripe/Admin/Includes/BrowserWarning.ss b/templates/SilverStripe/Admin/Includes/BrowserWarning.ss deleted file mode 100644 index 0ced12b62..000000000 --- a/templates/SilverStripe/Admin/Includes/BrowserWarning.ss +++ /dev/null @@ -1,34 +0,0 @@ -<% require css('silverstripe/admin: client/dist/styles/browser-warning.css') %> - - - - - SilverStripe - <%t SilverStripe\Admin\LeftAndMain.BROWSER_WARNING_HEADING 'Unsupported browser' %> - - - <%t SilverStripe\Admin\LeftAndMain.BROWSER_WARNING_TEXT 'You're using a web browser that's not supported by SilverStripe.Please upgrade to one of the following options.' %> - - - Internet Explorer(11+) - - Mozilla Firefox - - Google Chrome - - - - - -<% require javascript('silverstripe/admin: client/dist/js/browserWarning.js') %> - - diff --git a/templates/SilverStripe/Admin/Includes/LeftAndMain_EditForm.ss b/templates/SilverStripe/Admin/Includes/LeftAndMain_EditForm.ss index 86d4bd6c0..fb3584f05 100644 --- a/templates/SilverStripe/Admin/Includes/LeftAndMain_EditForm.ss +++ b/templates/SilverStripe/Admin/Includes/LeftAndMain_EditForm.ss @@ -57,9 +57,9 @@ <% if $hasExtraClass('cms-previewable') %> <% if $Actions.last.id == 'Form_ItemEditForm_RightGroup' %> - <% include SilverStripe\\Admin\\LeftAndMain_ViewModeSelector SelectID="preview-mode-dropdown-in-content", ExtraClass="ml-0" %> + <% include SilverStripe\\Admin\\LeftAndMain_ViewModeSelector SelectID="preview-mode-dropdown-in-content", ExtraClass="ms-0" %> <% else %> - <% include SilverStripe\\Admin\\LeftAndMain_ViewModeSelector SelectID="preview-mode-dropdown-in-content", ExtraClass="ml-auto" %> + <% include SilverStripe\\Admin\\LeftAndMain_ViewModeSelector SelectID="preview-mode-dropdown-in-content", ExtraClass="ms-auto" %> <% end_if %> <% end_if %> diff --git a/templates/SilverStripe/Admin/Includes/LeftAndMain_MenuToggle.ss b/templates/SilverStripe/Admin/Includes/LeftAndMain_MenuToggle.ss index 0daff7dc2..30e037067 100644 --- a/templates/SilverStripe/Admin/Includes/LeftAndMain_MenuToggle.ss +++ b/templates/SilverStripe/Admin/Includes/LeftAndMain_MenuToggle.ss @@ -4,7 +4,7 @@ $ApplicationName - + <% if $CMSVersionNumber %> - $CMSVersion)">$CMSVersionNumber <% end_if %> @@ -27,5 +27,5 @@ <%t SilverStripe\Admin\LeftAndMain.MenuToggleAuto "Auto" %> -" aria-label="<%t SilverStripe\Admin\LeftAndMain.ExpandPanel "Expand panel" %>">» -" aria-label="<%t SilverStripe\Admin\LeftAndMain.CollapsePanel "Collapse panel" %>">« +" aria-label="<%t SilverStripe\Admin\LeftAndMain.ExpandPanel "Expand panel" %>">» +" aria-label="<%t SilverStripe\Admin\LeftAndMain.CollapsePanel "Collapse panel" %>">« diff --git a/templates/SilverStripe/Admin/LeftAndMain.ss b/templates/SilverStripe/Admin/LeftAndMain.ss index 90e4c8fb7..1bd4a59a1 100644 --- a/templates/SilverStripe/Admin/LeftAndMain.ss +++ b/templates/SilverStripe/Admin/LeftAndMain.ss @@ -16,7 +16,5 @@ $Content $PreviewPanel - - <% include SilverStripe\\Admin\\BrowserWarning %>
SilverStripe
- <%t SilverStripe\Admin\LeftAndMain.BROWSER_WARNING_TEXT 'You're using a web browser that's not supported by SilverStripe.Please upgrade to one of the following options.' %> -