From 20f2fd29feb0c12a08fda5638f1a8881e5893387 Mon Sep 17 00:00:00 2001 From: Nicolas Giard Date: Sun, 16 Sep 2018 11:59:22 -0400 Subject: [PATCH] feat: add editor selection + code editor + grapejs POC --- client/app.js | 6 +- client/components/editor.vue | 52 +- client/components/editor/editor-code.vue | 251 +-------- client/components/editor/editor-markdown.vue | 497 ++++++++++++++++++ client/components/editor/editor-wysiwyg.vue | 62 +++ dev/webpack/webpack.dev.js | 16 +- package.json | 2 + server/modules/editor/markdown/definition.yml | 2 +- server/modules/editor/wysiwyg/definition.yml | 6 + yarn.lock | Bin 450618 -> 459240 bytes 10 files changed, 639 insertions(+), 255 deletions(-) create mode 100644 client/components/editor/editor-markdown.vue create mode 100644 client/components/editor/editor-wysiwyg.vue create mode 100644 server/modules/editor/wysiwyg/definition.yml diff --git a/client/app.js b/client/app.js index fe6edf32..af359669 100644 --- a/client/app.js +++ b/client/app.js @@ -156,9 +156,9 @@ let bootstrap = () => { // Load Icons // ==================================== - import(/* webpackChunkName: "icons" */ './svg/icons.svg').then(icons => { - document.body.insertAdjacentHTML('beforeend', icons.default) - }) + // import(/* webpackChunkName: "icons" */ './svg/icons.svg').then(icons => { + // document.body.insertAdjacentHTML('beforeend', icons.default) + // }) } window.boot.onDOMReady(bootstrap) diff --git a/client/components/editor.vue b/client/components/editor.vue index b41a321c..8dd24532 100644 --- a/client/components/editor.vue +++ b/client/components/editor.vue @@ -26,7 +26,7 @@ v-icon(color='blue', :left='$vuetify.breakpoint.lgAndUp') sort_by_alpha span.white--text(v-if='$vuetify.breakpoint.lgAndUp') {{ $t('editor:page') }} v-content - editor-code + component(:is='currentEditor') component(:is='currentModal') v-dialog(v-model='dialogProgress', persistent, max-width='350') v-card(color='blue darken-3', dark) @@ -38,6 +38,39 @@ ) .subheading {{ $t('editor:save.processing') }} .caption.blue--text.text--lighten-3 {{ $t('editor:save.pleaseWait') }} + v-dialog(v-model='dialogEditorSelector', persistent, max-width='550') + v-card(color='blue darken-3', dark) + v-card-text.text-xs-center.py-4 + .subheading Which editor do you want to use? + v-container(grid-list-lg, fluid) + v-layout(row, wrap, justify-center) + v-flex(xs4) + v-card( + hover + light + ripple + ) + v-card-text.text-xs-center(@click='selectEditor("code")') + v-icon(large, color='primary') code + .body-2.mt-2 Code + v-flex(xs4) + v-card( + hover + light + ripple + ) + v-card-text.text-xs-center(@click='selectEditor("markdown")') + v-icon(large, color='primary') list_alt + .body-2.mt-2 Markdown + v-flex(xs4) + v-card.grey( + hover + light + ripple + ) + v-card-text.text-xs-center(@click='selectEditor("wysiwyg")') + v-icon(large, color='grey darken-1') web + .body-2.mt-2.grey--text.text--darken-2 Visual Builder v-snackbar( :color='notification.style' @@ -69,12 +102,16 @@ export default { components: { AtomSpinner, editorCode: () => import(/* webpackChunkName: "editor-code" */ './editor/editor-code.vue'), + editorMarkdown: () => import(/* webpackChunkName: "editor-markdown" */ './editor/editor-markdown.vue'), + editorWysiwyg: () => import(/* webpackChunkName: "editor-wysiwyg" */ './editor/editor-wysiwyg.vue'), editorModalProperties: () => import(/* webpackChunkName: "editor" */ './editor/editor-modal-properties.vue') }, data() { return { currentModal: '', - dialogProgress: false + currentEditor: '', + dialogProgress: false, + dialogEditorSelector: false } }, computed: { @@ -85,11 +122,20 @@ export default { mounted() { if (this.mode === 'create') { _.delay(() => { - this.openModal('properties') + this.dialogEditorSelector = true }, 500) } }, methods: { + selectEditor(name) { + this.currentEditor = `editor${_.startCase(name)}` + this.dialogEditorSelector = false + if (this.mode === 'create') { + _.delay(() => { + this.openModal('properties') + }, 500) + } + }, openModal(name) { this.currentModal = `editorModal${_.startCase(name)}` }, diff --git a/client/components/editor/editor-code.vue b/client/components/editor/editor-code.vue index 68d9241e..2da081b5 100644 --- a/client/components/editor/editor-code.vue +++ b/client/components/editor/editor-code.vue @@ -1,74 +1,8 @@ @@ -296,84 +133,6 @@ export default { } } - &-preview { - flex: 1 1 50%; - background-color: mc('grey', '100'); - position: relative; - height: calc(100vh - 100px); - overflow: hidden; - - @include until($tablet) { - display: none; - } - - &-enter-active, &-leave-active { - transition: max-width .5s ease; - max-width: 50vw; - - .editor-code-preview-content { - width: 50vw; - overflow:hidden; - } - } - &-enter, &-leave-to { - max-width: 0; - } - - &-content { - height: calc(100vh - 100px); - overflow-y: scroll; - padding: 30px 1rem 1rem 1rem; - width: calc(100% + 1rem + 17px) - // -ms-overflow-style: none; - - // &::-webkit-scrollbar { - // width: 0px; - // background: transparent; - // } - } - - &-title { - background-color: rgba(mc('blue', '100'), .75); - border-bottom-right-radius: 5px; - display: inline-flex; - height: 30px; - justify-content: center; - align-items: center; - padding: 0 1rem; - color: mc('blue', '800'); - position: absolute; - top: 0; - left: 0; - z-index: 2; - text-transform: uppercase; - font-size: .7rem; - cursor: pointer; - } - } - - &-toolbar { - background-color: mc('blue', '700'); - background-image: linear-gradient(to bottom, mc('blue', '700') 0%, mc('blue','800') 100%); - color: #FFF; - - .v-toolbar__content { - padding-left: 16px; - - @include until($tablet) { - padding-left: 8px; - } - } - } - - // ========================================== - // Fix FAB revealing under codemirror - // ========================================== - - .speed-dial--fixed { - z-index: 8; - } - // ========================================== // CODE MIRROR // ========================================== diff --git a/client/components/editor/editor-markdown.vue b/client/components/editor/editor-markdown.vue new file mode 100644 index 00000000..68d9241e --- /dev/null +++ b/client/components/editor/editor-markdown.vue @@ -0,0 +1,497 @@ + + + + + diff --git a/client/components/editor/editor-wysiwyg.vue b/client/components/editor/editor-wysiwyg.vue new file mode 100644 index 00000000..ef189403 --- /dev/null +++ b/client/components/editor/editor-wysiwyg.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/dev/webpack/webpack.dev.js b/dev/webpack/webpack.dev.js index fddbddb2..4656268a 100644 --- a/dev/webpack/webpack.dev.js +++ b/dev/webpack/webpack.dev.js @@ -121,7 +121,8 @@ module.exports = { { test: /\.svg$/, exclude: [ - path.join(process.cwd(), 'client/svg') + path.join(process.cwd(), 'client/svg'), + path.join(process.cwd(), 'node_modules/grapesjs') ], use: [ { @@ -136,7 +137,8 @@ module.exports = { { test: /\.svg$/, include: [ - path.join(process.cwd(), 'client/svg') + path.join(process.cwd(), 'client/svg'), + path.join(process.cwd(), 'node_modules/grapesjs/src/styles/fonts/main-fonts.svg') ], use: [ { @@ -152,6 +154,16 @@ module.exports = { { loader: 'graphql-tag/loader' } ] }, + { + test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, + use: [{ + loader: 'file-loader', + options: { + name: '[name].[ext]', + outputPath: 'fonts/' + } + }] + }, { test: /.jsx$/, loader: 'babel-loader', diff --git a/package.json b/package.json index 59649010..f4179448 100644 --- a/package.json +++ b/package.json @@ -203,6 +203,7 @@ "eslint-plugin-standard": "4.0.0", "eslint-plugin-vue": "4.7.1", "file-loader": "2.0.0", + "grapesjs": "0.14.29", "graphiql": "0.11.11", "graphql-persisted-document-loader": "1.0.1", "graphql-tag": "^2.9.2", @@ -230,6 +231,7 @@ "raw-loader": "0.5.1", "react": "16.5.0", "react-dom": "16.5.0", + "resolve-url-loader": "3.0.0", "sass-loader": "7.1.0", "sass-resources-loader": "1.3.3", "script-ext-html-webpack-plugin": "2.0.1", diff --git a/server/modules/editor/markdown/definition.yml b/server/modules/editor/markdown/definition.yml index 8a72c37a..25304ae4 100644 --- a/server/modules/editor/markdown/definition.yml +++ b/server/modules/editor/markdown/definition.yml @@ -1,6 +1,6 @@ key: markdown title: Markdown -description: Default Markdown editor +description: Basic Markdown editor contentType: markdown author: requarks.io props: {} diff --git a/server/modules/editor/wysiwyg/definition.yml b/server/modules/editor/wysiwyg/definition.yml new file mode 100644 index 00000000..e84ec3f5 --- /dev/null +++ b/server/modules/editor/wysiwyg/definition.yml @@ -0,0 +1,6 @@ +key: wysiwyg +title: WYSIWYG +description: Advanced Visual HTML Builder +contentType: html +author: requarks.io +props: {} diff --git a/yarn.lock b/yarn.lock index 424081869fb622533be206230d49cb1c5fcf857d..11787a8b73c34ba307f4333d1ba4b5b19761bbd3 100644 GIT binary patch delta 5662 zcmaJ_ZH!#kS=OB|vs)88iL<+oV|TL9D!|V8oO|xM_a0YHw(h31MNLRsl{O)3pHF9< z-I?votQ#W~Hwvht2vk^` z=iECpJ8N84`(x%kXU_Yc_v3k=_dNa8LvK8K%abQA&zUn@{XwhW-Rfz(Avas=U1@C3 zUpil%^UV)cZt_PySD91t+S`t{j{b<17H!9E(jJ`trJt~jIb#L4oERlsEOQcDmL{2H zl$zLSP6*LHTB`HQYPWA&i5DF+YWH>54b3q5<!}z+E}?;_KGjzYUL+fg|w66Dn{5WRg`9oS(5WqXp$$Hw3%W;#d%5;BPvVy;_R&K z^;%}lIe%+hUl~5T7=3o{>{3(qp?a{q>M!J#1Ag{MwLSdRqtX7KdWY(EY-_7yx>y@7 zS5Dleq<(NBgfY9mw+KwV#7881#-6~awRA7wG@;MOF< za!VOC$~oy`u0?866Kl=1B>uwpYYSdntnEE;`*GUNLbPYc2g3&!E0q&>j=%3##E=^y zuM(|uVr8ZkO&OIs$&x%5+9t%sE>}9unTmzjzHnl`P}B&D^7imIJ`uhCp8ZQZiM5P$ zi~W0>(T#qy7A^T-e=M3CKL0z><1>f*5422oBWz&p>=^R#tnKyJx}D%b=6~xyqxPM$ z+yfhtq{Vh540e|`S|Xf)F~|_cM4EDy&aoygA91I?- zR6gL(KNrn>yfu=nbxsEbU1K-adcAIMN?xRAS!sEO)cj)7_2DX=!n--J%w1e-vY3 zO`35>nbthvgc?Q!Co;)X=Tey|$)uvWzxC#5Vc)1+3z$H`4&VE7bn3c#IEiil^&kCY z0c8H$uSd7VK~`3eqXuOXj&zwZamXX;tg?iQlyjo_XjP(+P7^qV>x_wvx>zZh%9KzWYb3tO zsG_mRg@371UGP8rT4kSq@?F(E{<$B=r>}_mtY7$Uec{FtR&Mpy9x6Z*g+Ba~{gub} zRhFrL>3HS#6nf26a%CJT%ayYnk)TGVLh@XR#3bA$nk$l|vEjLY_WRNNe%t3Q`_P~~ z83;Ulf3tGx!z+bw8IVj70>0E7Z5v6%j^N>93r%*VWFbrZJyC7x&e1PnBs zEB$jDs=E$(=r6RCcW|@TU`;;=6aZ>XAFzz3g5QUWOiuOtey)D!ho=O+!s^L-51|bi z88A&|#sb7>LM7o+Bnn+7NeF<<5LB6RQsj;)|JpxC3m+@gmxk{0Hbeip+Wys%{e`vV zrIt%sY3oSzu)lC!^~48vZay-#Tt;ES35B7`5n^59j8v(TR3)j^DpP3;WYd{7JfmFe ztT6QE|7++tzQZRrDnI<>Y-iAtpSJz(hV{q(t-5lT>+VQk!SvTw5}HL}L+(&uC@zYk zm8e{2NTvu{j36iq;dD;9q>K%J_xZ|yk$2kunf@}eBx%Ru>b!!?KXJIWYK0#aN>S7?O|1f0iNx-2p zE@NrY?~4*aGcT9MEoAhAY|($`*BUpS2RM(`uhjvH%>d|f%e1qwQn;&JdC;EQkbR_j z@q={CiZ*-QjWyu(W_SIZTU$r6ujcUZ=(zr-)nw4y+Gy$SdbhWUv>zRSP35_uE$E86 z+bb!W0E~V1zbjvO<{hQBfRd>{_)2ug-4hGo-N|QQ3~VW!YpJw6G3e?7z1*RMiAq!a z=MJ1vNGg(4!}+K>{QT_pYcH-0KlK;Y_Z*s0Ac!DWYp4B77pwFB)wtUBr@m3$^O2L2 zl@64ycMY0!drF9$9uw7Evs@B^ZU6>>)G-7MMmUYDSLJ= zOaV`h7;z;nLL$L-8M`^xiDB<+vFn56$kbjvi`o4yDv1QefL5U>Jr#^OqevF zR7uR8w0VL#0*MFGt^_gHLol0Wb3REmhKy%|b zW;Pb70$dXbdK!YI5W2)a`?r_@zW&8VBb~0u9shogMMiq3Fcj{{#k8C_D*kY*v_C|B+$vtM%zF6 zN)@O!mhVJxtv?YKWijF988bQ8sf?327Y_Y7O_@pr#T39;?f@R(oI42=&gsb#l-}A` zT`ClQu#oLmhD}A9l;krLAowZ=Rsxe~97_i-o+pWvLTMNP;_J{1`LOzOwO8N%_KOGn z;VV&D@BVMDRBt@GM1CoRxI_KO_Wr!j=$uH$ZD_Alzfqr=gsbrVGs8-0?A;UjjyonII3yjFu7D#Fi@C%)#)t$~h6#x# zT;!?FIU1UZNly4M{+DXwzS%K%1j~*{bo`?eG6^k{&r`Hp%RDtG8sL3SQ=tfr3C^?3 z=uo0c7==+U)(C88P21L>cdmHH7(RMOZRuwYg-4J;uki*l#^7Rng=G8sZ?^oGy0wO1 zJyV+_*in=M0e6;Jf@c{g4f-*rRv>?#DkG6y426&a2P7YU;Y{s~muDul!9Vh|(VX`O z5$n&qul{46uhegeb2zC?P)0CQ;fTb5C*{BgoS}J+`6bUR%@b*jL+dreM_1~dj~*Gl z(gZ$@N19!xL*gSBweFgJ&Vl!)zZTO{iE9$Y>=KT$$OApiQpwYtuuM~x+LT~&;zFRn zhyU*DCy)5UZ`VHLn@`pE+|%0Xt&g6=iqreu^|N@RnFx!bC@+V%htN4FD5ptdkanYE zYaNXhla5QEXO?m8=}i6LJFoqchMWx4nk@Rq|FN-fOF+J>C*@Jvvfr*9K7?VhH)2EDtGV{@LG* z4)~}4xUqM8|7<v(C`038;$-@aj^$(I9)Z2zWHo{>Yc>@4q9QwR31;Vv&?UX9Bzl&keB(^CyuK zydTpM(I&|`L%{)pwx76le!Ee-sTt;}5!=S>Tso%UWWCd>^?-fI-*Yiq8OmqsC-MVJ z&GPj#O!O^OcnGuqy=N*b!*6}Bestyryd_>mfBnB6k5=vv%=qdR*nTZB91|#YnDCT{ zLF7O&V=%ca3vY(p<&0BHH3`iIeV9-(ocTfh&HHXy+~L-Eikp6?b6a9shJJD1qS0S}k$1pzLX@RjB6x3J&=Sq_)E?*XB=Ht_*(C<0_+lfcmymruX&YM2Aj7OeFoHo$!UZ?