From d80683c1af907364ca6140c2941e61e005f160a3 Mon Sep 17 00:00:00 2001 From: Victor Vlasenko Date: Tue, 21 Nov 2017 15:12:34 +0200 Subject: [PATCH 001/327] Reduce node_modules size by removing tcomb --- .spinrc.json | 2 +- .spinrc.prod.json | 2 +- package.json | 3 - yarn.lock | 199 ++++++++++++++++++++++++---------------------- 4 files changed, 106 insertions(+), 100 deletions(-) diff --git a/.spinrc.json b/.spinrc.json index 1dbeb64e83..3bbeb62390 100644 --- a/.spinrc.json +++ b/.spinrc.json @@ -27,7 +27,7 @@ "frontendBuildDir": "build/client", "dllBuildDir": "build/dll", "overridesConfig": "tools/webpackAppConfig.js", - "stack": ["apollo", "react", "styled-components", "sass", "less", "es6", "tcomb", "webpack"], + "stack": ["apollo", "react", "styled-components", "sass", "less", "es6", "webpack"], "backendUrl": "http://localhost:8080/graphql", "ssr": true, "webpackDll": true, diff --git a/.spinrc.prod.json b/.spinrc.prod.json index 82d884f12d..73a35cc82e 100644 --- a/.spinrc.prod.json +++ b/.spinrc.prod.json @@ -28,7 +28,7 @@ "frontendBuildDir": "build/client", "dllBuildDir": "build/dll", "overridesConfig": "tools/webpackAppConfig.js", - "stack": ["apollo", "react", "styled-components", "sass", "less", "es6", "tcomb", "webpack"], + "stack": ["apollo", "react", "styled-components", "sass", "less", "es6", "webpack"], "backendUrl": "https://apollo-universal-starter-kit.herokuapp.com/graphql", "ssr": true, "webpackDll": true, diff --git a/package.json b/package.json index fe56483c43..4442d721ff 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,6 @@ "babel-eslint": "^8.0.2", "babel-loader": "^7.1.2", "babel-plugin-styled-components": "^1.3.0", - "babel-plugin-tcomb": "^0.3.26", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-decorators-legacy": "^1.3.4", "babel-plugin-transform-react-remove-prop-types": "^0.4.10", @@ -170,7 +169,6 @@ "file-loader": "^1.1.5", "flow-bin": "^0.59.0", "freeport-async": "^1.1.1", - "fs-extra": "^4.0.2", "haul": "1.0.0-beta.10", "html-webpack-plugin": "^2.30.1", "http-proxy-middleware": "^0.17.4", @@ -203,7 +201,6 @@ "source-list-map": "^2.0.0", "spinjs": "^0.4.41", "style-loader": "^0.19.0", - "tcomb": "^3.2.24", "url-loader": "^0.6.2", "wait-on": "^2.0.2", "webpack": "^3.8.1", diff --git a/yarn.lock b/yarn.lock index 14713ba658..7c80ce8685 100644 --- a/yarn.lock +++ b/yarn.lock @@ -339,8 +339,8 @@ ansicolors@~0.2.1: resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef" antd@^3.0.0-beta.7: - version "3.0.0-beta.7" - resolved "https://registry.yarnpkg.com/antd/-/antd-3.0.0-beta.7.tgz#4f752502b63c2a4c91f0bbed20938ae5cc0aa2e0" + version "3.0.0-rc.1" + resolved "https://registry.yarnpkg.com/antd/-/antd-3.0.0-rc.1.tgz#5ab140523dd6448cd8e0c3d84e68c382c4616033" dependencies: array-tree-filter "~1.0.0" babel-runtime "6.x" @@ -355,28 +355,28 @@ antd@^3.0.0-beta.7: rc-animate "^2.4.1" rc-calendar "~9.2.0" rc-cascader "~0.12.0" - rc-checkbox "~2.0.3" + rc-checkbox "~2.1.1" rc-collapse "~1.7.5" rc-dialog "~7.0.0" rc-dropdown "~2.1.0" rc-editor-mention "^1.0.2" - rc-form "~1.5.0" - rc-input-number "~3.6.0" + rc-form "~2.0.0" + rc-input-number "~4.0.0" rc-menu "~6.1.0" rc-notification "~3.0.0" rc-pagination "~1.12.4" rc-progress "~2.2.2" - rc-rate "~2.1.1" - rc-select "~7.1.0" + rc-rate "~2.2.0" + rc-select "~7.2.0" rc-slider "~8.4.0" rc-steps "~3.0.0" - rc-switch "~1.5.1" - rc-table "~5.6.9" + rc-switch "~1.6.0" + rc-table "~6.1.0" rc-tabs "~9.1.2" - rc-time-picker "~3.1.0" + rc-time-picker "~3.2.1" rc-tooltip "~3.7.0" rc-tree "~1.7.0" - rc-tree-select "~1.11.0" + rc-tree-select "~1.12.0" rc-upload "~2.4.0" rc-util "^4.0.4" react-lazy-load "^3.0.12" @@ -800,7 +800,7 @@ atob@~1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" -attr-accept@^1.0.3, attr-accept@^1.1.0: +attr-accept@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-1.1.0.tgz#b5cd35227f163935a8f1de10ed3eba16941f6be6" @@ -925,18 +925,6 @@ babel-eslint@^8.0.2: "@babel/types" "^7.0.0-beta.31" babylon "^7.0.0-beta.31" -babel-generator@6.19.0: - version "6.19.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.19.0.tgz#9b2f244204777a3d6810ec127c673c87b349fac5" - dependencies: - babel-messages "^6.8.0" - babel-runtime "^6.9.0" - babel-types "^6.19.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.2.0" - source-map "^0.5.0" - babel-generator@^6.24.1, babel-generator@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" @@ -1084,7 +1072,7 @@ babel-loader@^7.1.2: loader-utils "^1.0.2" mkdirp "^0.5.1" -babel-messages@^6.23.0, babel-messages@^6.8.0: +babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" dependencies: @@ -1179,12 +1167,6 @@ babel-plugin-syntax-trailing-function-commas@^6.20.0, babel-plugin-syntax-traili version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" -babel-plugin-tcomb@^0.3.26: - version "0.3.26" - resolved "https://registry.yarnpkg.com/babel-plugin-tcomb/-/babel-plugin-tcomb-0.3.26.tgz#f8fa81d63ca68ba045f873fe6cc2a53736a361cb" - dependencies: - babel-generator "6.19.0" - babel-plugin-transform-async-generator-functions@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" @@ -1739,7 +1721,7 @@ babel-register@^6.24.0, babel-register@^6.24.1, babel-register@^6.26.0: mkdirp "^0.5.1" source-map-support "^0.4.15" -babel-runtime@6.x, babel-runtime@^6.0.0, babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.25.0, babel-runtime@^6.26.0, babel-runtime@^6.9.0, babel-runtime@^6.9.2: +babel-runtime@6.x, babel-runtime@^6.0.0, babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.25.0, babel-runtime@^6.26.0, babel-runtime@^6.9.2: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" dependencies: @@ -5106,7 +5088,7 @@ hoek@4.x.x: version "4.2.0" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" -hoist-non-react-statics@1.x, hoist-non-react-statics@^1.2.0: +hoist-non-react-statics@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb" @@ -6584,6 +6566,10 @@ lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" +lodash.merge@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" + lodash.mergewith@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" @@ -7029,6 +7015,14 @@ min-document@^2.19.0: dependencies: dom-walk "^0.1.0" +mini-store@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/mini-store/-/mini-store-1.0.3.tgz#190e90831be7a3862baa532168b579273b00d818" + dependencies: + hoist-non-react-statics "^2.3.1" + prop-types "^15.6.0" + shallowequal "^1.0.2" + minilog@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/minilog/-/minilog-3.1.0.tgz#d2d0f1887ca363d1acf0ea86d5c4df293b3fb675" @@ -7133,7 +7127,11 @@ mocha@^4.0.1: mkdirp "0.5.1" supports-color "4.4.0" -moment@2.x, moment@2.x.x, moment@^2.10.6, moment@^2.18.1: +moment@2.x, moment@^2.18.1: + version "2.19.2" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.2.tgz#8a7f774c95a64550b4c7ebd496683908f9419dbe" + +moment@2.x.x, moment@^2.10.6: version "2.19.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.1.tgz#56da1a2d1cbf01d38b7e1afc31c10bcfa1929167" @@ -7216,8 +7214,8 @@ mv@^2.1.1, mv@~2: rimraf "~2.4.0" mysql2@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-1.5.0.tgz#12c67fe7be718fb71ec9124c1adc85a0086ca4f9" + version "1.5.1" + resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-1.5.1.tgz#2411d6fb958af86b2304b7a53bc54b26e77e682b" dependencies: cardinal "1.0.0" denque "^1.1.1" @@ -8857,9 +8855,9 @@ rc-cascader@~0.12.0: rc-util "^4.0.4" shallow-equal "^1.0.0" -rc-checkbox@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/rc-checkbox/-/rc-checkbox-2.0.3.tgz#436a9d508948e224980f0535ea738b48177a8f25" +rc-checkbox@~2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/rc-checkbox/-/rc-checkbox-2.1.1.tgz#7b2d3632285eaad9cad78612a6643d7d34589e72" dependencies: babel-runtime "^6.23.0" classnames "2.x" @@ -8916,15 +8914,15 @@ rc-editor-mention@^1.0.2: rc-animate "^2.3.0" rc-editor-core "~0.7.7" -rc-form@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/rc-form/-/rc-form-1.5.0.tgz#9c78ab93e998e66af02921b99eea12296c68205c" +rc-form@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/rc-form/-/rc-form-2.0.0.tgz#af69b0f14abf5bc925566d0b8da93f3297705f27" dependencies: async-validator "1.x" babel-runtime "6.x" create-react-class "^15.5.3" dom-scroll-into-view "1.x" - hoist-non-react-statics "1.x" + hoist-non-react-statics "^2.3.1" lodash "^4.17.4" warning "^3.0.0" @@ -8936,19 +8934,31 @@ rc-hammerjs@~0.6.0: hammerjs "^2.0.8" prop-types "^15.5.9" -rc-input-number@~3.6.0: - version "3.6.9" - resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-3.6.9.tgz#1ea872dd68b8f297aef8400c63f05673a2ac03b8" +rc-input-number@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-4.0.0.tgz#a7302d875e6fb8e7c3aa177c57f0d96bdedc1d8c" dependencies: babel-runtime "6.x" classnames "^2.2.0" - create-react-class "^15.5.2" prop-types "^15.5.7" - rc-touchable "^1.0.0" + rmc-feedback "^1.0.0" + +rc-menu@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-6.2.1.tgz#5d4515c1ac09b1984b1cb34d4abc4411989c0747" + dependencies: + babel-runtime "6.x" + classnames "2.x" + create-react-class "^15.5.2" + dom-scroll-into-view "1.x" + prop-types "^15.5.6" + rc-animate "2.x" + rc-trigger "^2.3.0" + rc-util "^4.1.0" -rc-menu@^6.1.0, rc-menu@~6.1.0: - version "6.1.2" - resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-6.1.2.tgz#b68dbb52702d324ac497f75af262f50b91af7c79" +rc-menu@~6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-6.1.3.tgz#ff6bb587ebbb39b1d97997fc89368176a6181956" dependencies: babel-runtime "6.x" classnames "2.x" @@ -8983,16 +8993,17 @@ rc-progress@~2.2.2: babel-runtime "6.x" prop-types "^15.5.8" -rc-rate@~2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/rc-rate/-/rc-rate-2.1.1.tgz#88aeda8b3d6470bbae4f6518c652a02a959bddc5" +rc-rate@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/rc-rate/-/rc-rate-2.2.0.tgz#6b095900fe2289b8a889a17ae3513ca9989e8122" dependencies: + babel-runtime "^6.26.0" classnames "^2.2.5" prop-types "^15.5.8" -rc-select@~7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-7.1.0.tgz#eaebab34b21ea5abaf51f3ed6978bb3276e8fab5" +rc-select@~7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-7.2.0.tgz#9a3a12ea15cb04bf27611d7d2bd4ac1d4f0d4818" dependencies: babel-runtime "^6.23.0" classnames "2.x" @@ -9026,24 +9037,26 @@ rc-steps@~3.0.0: lodash.debounce "^4.0.8" prop-types "^15.5.7" -rc-switch@~1.5.1: - version "1.5.3" - resolved "https://registry.yarnpkg.com/rc-switch/-/rc-switch-1.5.3.tgz#283c2608bac57ebd7cdc4033269de14b6753eb39" +rc-switch@~1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/rc-switch/-/rc-switch-1.6.0.tgz#c2d7369bdb87c1fd45e84989a27c1fb2f201d2fd" dependencies: babel-runtime "^6.23.0" classnames "^2.2.1" prop-types "^15.5.6" -rc-table@~5.6.9: - version "5.6.13" - resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-5.6.13.tgz#ca73021dc6a3aa0af2846d07ee80c01c713ff0de" +rc-table@~6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-6.1.0.tgz#72ab51e7c960454c823049b7d1b6cbfe7dff07a5" dependencies: babel-runtime "6.x" component-classes "^1.2.6" lodash.get "^4.4.2" + lodash.merge "^4.6.0" + mini-store "^1.0.2" prop-types "^15.5.8" - rc-util "4.x" - shallowequal "^0.2.2" + rc-util "^4.0.4" + shallowequal "^1.0.2" warning "^3.0.0" rc-tabs@~9.1.2: @@ -9059,9 +9072,9 @@ rc-tabs@~9.1.2: rc-util "^4.0.4" warning "^3.0.0" -rc-time-picker@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/rc-time-picker/-/rc-time-picker-3.1.0.tgz#85553e03d0a20d7f7bd4c21803ddfffcd7a93a47" +rc-time-picker@~3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/rc-time-picker/-/rc-time-picker-3.2.1.tgz#e105fed32814bb95f37dbc60b49495cd787abfa2" dependencies: babel-runtime "6.x" classnames "2.x" @@ -9077,15 +9090,9 @@ rc-tooltip@^3.7.0, rc-tooltip@~3.7.0: prop-types "^15.5.8" rc-trigger "^2.2.2" -rc-touchable@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/rc-touchable/-/rc-touchable-1.2.3.tgz#5f498324e3d0b9ba601a9c4834958eaa2c713618" - dependencies: - babel-runtime "6.x" - -rc-tree-select@~1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/rc-tree-select/-/rc-tree-select-1.11.0.tgz#edfc14bd6f7ae53a319eb071dabc8f5d4c4f4f96" +rc-tree-select@~1.12.0: + version "1.12.1" + resolved "https://registry.yarnpkg.com/rc-tree-select/-/rc-tree-select-1.12.1.tgz#8eade37cf6044845676d25988b2d41a2c62c5531" dependencies: babel-runtime "^6.23.0" classnames "^2.2.1" @@ -9097,8 +9104,8 @@ rc-tree-select@~1.11.0: rc-util "^4.0.2" rc-tree@~1.7.0, rc-tree@~1.7.1: - version "1.7.8" - resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-1.7.8.tgz#9c5cd86a901474c655c94be1956c486de0648012" + version "1.7.9" + resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-1.7.9.tgz#5cefaff0c1a9f1179702782b265846e3b494a08a" dependencies: babel-runtime "^6.23.0" classnames "2.x" @@ -9107,30 +9114,29 @@ rc-tree@~1.7.0, rc-tree@~1.7.1: rc-util "^4.0.4" warning "^3.0.0" -rc-trigger@^2.2.0, rc-trigger@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-2.2.2.tgz#b0c666b37cce4ed27300a7e710d67bf7444d12ad" +rc-trigger@^2.2.0, rc-trigger@^2.2.2, rc-trigger@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-2.3.0.tgz#f42cfe4bc17dab4e4cd613a1d4a156738d252728" dependencies: babel-runtime "6.x" create-react-class "15.x" prop-types "15.x" rc-align "2.x" rc-animate "2.x" - rc-util "^4.2.0" + rc-util "^4.3.0" rc-upload@~2.4.0: - version "2.4.3" - resolved "https://registry.yarnpkg.com/rc-upload/-/rc-upload-2.4.3.tgz#df793c1dccd5d6815ad256fe776b870bb593edfc" + version "2.4.4" + resolved "https://registry.yarnpkg.com/rc-upload/-/rc-upload-2.4.4.tgz#28e1e6a3e44d1b1f92e57e21927cfa2763ac2a21" dependencies: - attr-accept "^1.1.0" babel-runtime "6.x" classnames "^2.2.5" prop-types "^15.5.7" warning "2.x" -rc-util@4.x, rc-util@^4.0.2, rc-util@^4.0.4, rc-util@^4.1.0, rc-util@^4.1.1, rc-util@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.2.0.tgz#dacec50735675a211f1c94571306a90e8b97248f" +rc-util@4.x, rc-util@^4.0.2, rc-util@^4.0.4, rc-util@^4.1.0, rc-util@^4.1.1, rc-util@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.3.0.tgz#31c61e747e3e107acfe78049f98b275a8051a398" dependencies: add-dom-event-listener "1.x" babel-runtime "6.x" @@ -10065,6 +10071,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^2.0.0" inherits "^2.0.1" +rmc-feedback@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/rmc-feedback/-/rmc-feedback-1.0.3.tgz#efd9d75c51998857c7a9a495ee507313a81aaee9" + dependencies: + babel-runtime "6.x" + classnames "^2.2.5" + rndm@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c" @@ -10339,7 +10352,7 @@ shallowequal@^0.2.2: dependencies: lodash.keys "^3.1.2" -shallowequal@^1.0.1: +shallowequal@^1.0.1, shallowequal@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.0.2.tgz#1561dbdefb8c01408100319085764da3fcf83f8f" @@ -10533,7 +10546,7 @@ source-map@0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" -source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3, source-map@~0.5.6: +source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3, source-map@~0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -11041,10 +11054,6 @@ tar@^4.0.2: mkdirp "^0.5.0" yallist "^3.0.2" -tcomb@^3.2.24: - version "3.2.24" - resolved "https://registry.yarnpkg.com/tcomb/-/tcomb-3.2.24.tgz#7f427053cc393b5997c4c3d859ca20411180887b" - temp@0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" From 8e622d2dcde79f1745715fe7432e45f022cd476a Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Tue, 21 Nov 2017 14:32:30 +0100 Subject: [PATCH 002/327] update fragment .graphql file --- tools/cli.js | 5 ++- tools/cli/module.js | 39 +++++++++++++++++++ .../module/client/graphql/ModuleQuery.graphql | 4 +- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/tools/cli.js b/tools/cli.js index 1a535a90d3..374483673a 100644 --- a/tools/cli.js +++ b/tools/cli.js @@ -20,6 +20,9 @@ prog ['both', 'server', 'client'], 'both' ) - .action((args, options, logger) => moduleCmd('deletemodule', args, options, logger)); + .action((args, options, logger) => moduleCmd('deletemodule', args, options, logger)) + .command('updateschema', 'Update Module Schema') + .argument('', 'Module name') + .action((args, options, logger) => moduleCmd('updateschema', args, options, logger)); prog.parse(process.argv); diff --git a/tools/cli/module.js b/tools/cli/module.js index afc6d43ebc..4db99025ee 100644 --- a/tools/cli/module.js +++ b/tools/cli/module.js @@ -1,3 +1,7 @@ +/* eslint-disable import/no-dynamic-require */ +require('babel-register')({ presets: ['env'], plugins: ['transform-class-properties'] }); +require('babel-polyfill'); + const shell = require('shelljs'); const fs = require('fs'); @@ -105,6 +109,36 @@ function deleteFiles(logger, templatePath, module, location) { } } +function updateSchema(logger, module) { + logger.info(`Updating ${module} Schema…`); + + // get fragment file + const path = `${__dirname}/../../src/client/modules/${module}/graphql/`; + const file = `${module.toCamelCase().capitalize()}.graphql`; + const re = /\{([^()]+)\}/g; + + // get module schema + const schema = require(`../../src/server/modules/${module}/schema`); + + // regenerate graphql fragment + let graphql = '{\n'; + for (const key of Object.keys(schema[module.toCamelCase().capitalize()].values)) { + graphql += ` ${key}\n`; + } + graphql += '}'; + + // override graphql fragment file + shell.cd(path); + // remove all new lines + shell.exec(`tr -d '\n' < ${file} > ${file}.tmp`); + // replace content + shell.sed('-i', re, graphql, `${file}.tmp`); + // remove old file + shell.rm(file); + // rename tmp file + shell.mv(`${file}.tmp`, file); +} + module.exports = (action, args, options, logger) => { const templatePath = `${__dirname}/../templates/module`; @@ -130,4 +164,9 @@ module.exports = (action, args, options, logger) => { deleteFiles(logger, templatePath, args.module, 'server'); } } + + // update schema + if (action === 'updateschema') { + updateSchema(logger, args.module); + } }; diff --git a/tools/templates/module/client/graphql/ModuleQuery.graphql b/tools/templates/module/client/graphql/ModuleQuery.graphql index f16c43a24b..61470c8960 100644 --- a/tools/templates/module/client/graphql/ModuleQuery.graphql +++ b/tools/templates/module/client/graphql/ModuleQuery.graphql @@ -1 +1,3 @@ -# GraphQL queries +fragment $Module$Info on $Module$ { + id +} \ No newline at end of file From 595ffd51856d949b63f0dd6801254b9aa5df6c48 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Tue, 21 Nov 2017 14:41:01 +0100 Subject: [PATCH 003/327] remove graphql related stuff in yarn addmodule --- .../module/client/containers/Module.jsx | 6 +---- .../module/client/graphql/ModuleQuery.graphql | 3 --- tools/templates/module/server/Module.spec.js | 23 ------------------- tools/templates/module/server/index.js | 9 +------- tools/templates/module/server/resolvers.js | 6 ----- tools/templates/module/server/schema.graphqls | 5 ---- tools/templates/module/server/sql.js | 4 ---- 7 files changed, 2 insertions(+), 54 deletions(-) delete mode 100644 tools/templates/module/client/graphql/ModuleQuery.graphql delete mode 100644 tools/templates/module/server/Module.spec.js delete mode 100644 tools/templates/module/server/resolvers.js delete mode 100644 tools/templates/module/server/schema.graphqls delete mode 100644 tools/templates/module/server/sql.js diff --git a/tools/templates/module/client/containers/Module.jsx b/tools/templates/module/client/containers/Module.jsx index 59510a61c5..2eb0c5d34e 100644 --- a/tools/templates/module/client/containers/Module.jsx +++ b/tools/templates/module/client/containers/Module.jsx @@ -1,6 +1,4 @@ -/*eslint-disable no-unused-vars*/ import React from 'react'; -import { graphql, compose } from 'react-apollo'; import $Module$View from '../components/$Module$View'; @@ -10,6 +8,4 @@ class $Module$ extends React.Component { } } -const $Module$WithApollo = compose()($Module$); - -export default $Module$WithApollo; +export default $Module$; diff --git a/tools/templates/module/client/graphql/ModuleQuery.graphql b/tools/templates/module/client/graphql/ModuleQuery.graphql deleted file mode 100644 index 61470c8960..0000000000 --- a/tools/templates/module/client/graphql/ModuleQuery.graphql +++ /dev/null @@ -1,3 +0,0 @@ -fragment $Module$Info on $Module$ { - id -} \ No newline at end of file diff --git a/tools/templates/module/server/Module.spec.js b/tools/templates/module/server/Module.spec.js deleted file mode 100644 index 223aad95c8..0000000000 --- a/tools/templates/module/server/Module.spec.js +++ /dev/null @@ -1,23 +0,0 @@ -/*eslint-disable no-unused-vars*/ -import chai from 'chai'; -import { step } from 'mocha-steps'; -import { getServer, getApollo } from '../../testHelpers/integrationSetup'; - -describe('$Module$ API works', () => { - let server, apollo; - - before(() => { - server = getServer(); - apollo = getApollo(); - }); - - step('Has GraphiQL endpoint', () => { - return chai - .request(server) - .get('/graphiql') - .end((err, res) => { - res.status.should.be(200); - res.body.should.be('{}'); - }); - }); -}); diff --git a/tools/templates/module/server/index.js b/tools/templates/module/server/index.js index 250cfbc59f..eec5baca53 100644 --- a/tools/templates/module/server/index.js +++ b/tools/templates/module/server/index.js @@ -1,10 +1,3 @@ -import $Module$ from './sql'; -import schema from './schema.graphqls'; -import createResolvers from './resolvers'; import Feature from '../connector'; -export default new Feature({ - schema, - createResolversFunc: createResolvers, - createContextFunc: () => ({ $Module$: new $Module$() }) -}); +export default new Feature({}); diff --git a/tools/templates/module/server/resolvers.js b/tools/templates/module/server/resolvers.js deleted file mode 100644 index 13582f9182..0000000000 --- a/tools/templates/module/server/resolvers.js +++ /dev/null @@ -1,6 +0,0 @@ -/*eslint-disable no-unused-vars*/ -export default pubsub => ({ - Query: {}, - Mutation: {}, - Subscription: {} -}); diff --git a/tools/templates/module/server/schema.graphqls b/tools/templates/module/server/schema.graphqls deleted file mode 100644 index b224b3517b..0000000000 --- a/tools/templates/module/server/schema.graphqls +++ /dev/null @@ -1,5 +0,0 @@ -extend type Query {} - -extend type Mutation {} - -extend type Subscription {} diff --git a/tools/templates/module/server/sql.js b/tools/templates/module/server/sql.js deleted file mode 100644 index a358efaab1..0000000000 --- a/tools/templates/module/server/sql.js +++ /dev/null @@ -1,4 +0,0 @@ -/*eslint-disable no-unused-vars*/ -import knex from '../../../server/sql/connector'; - -export default class $Module$ {} From 052d707ada9f6344195806348c3cd466273604fa Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Tue, 21 Nov 2017 14:51:49 +0100 Subject: [PATCH 004/327] separate template folder for `addcrud` --- tools/cli.js | 3 ++ tools/cli/module.js | 31 ++++++++++++------- .../crud/client/components/ModuleView.jsx | 31 +++++++++++++++++++ .../crud/client/components/ModuleView.web.jsx | 28 +++++++++++++++++ .../crud/client/containers/Module.jsx | 15 +++++++++ .../crud/client/containers/Module.spec.js | 17 ++++++++++ .../crud/client/graphql/ModuleQuery.graphql | 3 ++ tools/templates/crud/client/index.jsx | 21 +++++++++++++ tools/templates/crud/client/index.web.jsx | 19 ++++++++++++ tools/templates/crud/client/reducers/index.js | 8 +++++ tools/templates/crud/server/Module.spec.js | 23 ++++++++++++++ tools/templates/crud/server/index.js | 10 ++++++ tools/templates/crud/server/resolvers.js | 6 ++++ tools/templates/crud/server/schema.graphqls | 5 +++ tools/templates/crud/server/sql.js | 4 +++ 15 files changed, 213 insertions(+), 11 deletions(-) create mode 100644 tools/templates/crud/client/components/ModuleView.jsx create mode 100644 tools/templates/crud/client/components/ModuleView.web.jsx create mode 100644 tools/templates/crud/client/containers/Module.jsx create mode 100644 tools/templates/crud/client/containers/Module.spec.js create mode 100644 tools/templates/crud/client/graphql/ModuleQuery.graphql create mode 100644 tools/templates/crud/client/index.jsx create mode 100644 tools/templates/crud/client/index.web.jsx create mode 100644 tools/templates/crud/client/reducers/index.js create mode 100644 tools/templates/crud/server/Module.spec.js create mode 100644 tools/templates/crud/server/index.js create mode 100644 tools/templates/crud/server/resolvers.js create mode 100644 tools/templates/crud/server/schema.graphqls create mode 100644 tools/templates/crud/server/sql.js diff --git a/tools/cli.js b/tools/cli.js index 374483673a..5a48ff1378 100644 --- a/tools/cli.js +++ b/tools/cli.js @@ -12,6 +12,9 @@ prog 'both' ) .action((args, options, logger) => moduleCmd('addmodule', args, options, logger)) + .command('addcrud', 'Create a new Module with CRUD') + .argument('', 'Module name') + .action((args, options, logger) => moduleCmd('addcrud', args, options, logger)) .command('deletemodule', 'Delete a Module') .argument('', 'Module name') .argument( diff --git a/tools/cli/module.js b/tools/cli/module.js index 4db99025ee..042831def3 100644 --- a/tools/cli/module.js +++ b/tools/cli/module.js @@ -140,33 +140,42 @@ function updateSchema(logger, module) { } module.exports = (action, args, options, logger) => { - const templatePath = `${__dirname}/../templates/module`; + const module = args.module; + let location = 'both'; + if (args.location) { + location = args.location; + } + + let templatePath = `${__dirname}/../templates/module`; + if (action === 'addcrud') { + templatePath = `${__dirname}/../templates/crud`; + } if (!fs.existsSync(templatePath)) { - logger.error(`The requested location for ${args.location} wasn't found.`); + logger.error(`The requested location for ${location} wasn't found.`); process.exit(1); } // client - if (args.location === 'client' || args.location === 'both') { - if (action === 'addmodule') { - copyFiles(logger, templatePath, args.module, 'client'); + if (location === 'client' || location === 'both') { + if (action === 'addmodule' || action === 'addcrud') { + copyFiles(logger, templatePath, module, 'client'); } else if (action === 'deletemodule') { - deleteFiles(logger, templatePath, args.module, 'client'); + deleteFiles(logger, templatePath, module, 'client'); } } // server - if (args.location === 'server' || args.location === 'both') { - if (action === 'addmodule') { - copyFiles(logger, templatePath, args.module, 'server'); + if (location === 'server' || location === 'both') { + if (action === 'addmodule' || action === 'addcrud') { + copyFiles(logger, templatePath, module, 'server'); } else if (action === 'deletemodule') { - deleteFiles(logger, templatePath, args.module, 'server'); + deleteFiles(logger, templatePath, module, 'server'); } } // update schema if (action === 'updateschema') { - updateSchema(logger, args.module); + updateSchema(logger, module); } }; diff --git a/tools/templates/crud/client/components/ModuleView.jsx b/tools/templates/crud/client/components/ModuleView.jsx new file mode 100644 index 0000000000..04c16384fe --- /dev/null +++ b/tools/templates/crud/client/components/ModuleView.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +const $Module$View = () => { + return ( + + + Hello $Module$! + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + alignItems: 'center', + justifyContent: 'center' + }, + element: { + paddingTop: 30 + }, + box: { + textAlign: 'center', + marginLeft: 15, + marginRight: 15 + } +}); + +export default $Module$View; diff --git a/tools/templates/crud/client/components/ModuleView.web.jsx b/tools/templates/crud/client/components/ModuleView.web.jsx new file mode 100644 index 0000000000..49bca7ba8b --- /dev/null +++ b/tools/templates/crud/client/components/ModuleView.web.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import Helmet from 'react-helmet'; +import { PageLayout } from '../../common/components/web'; + +const renderMetaData = () => ( + +); + +const $Module$View = () => { + return ( + + {renderMetaData()} +
+

Hello $Module$!

+
+
+ ); +}; + +export default $Module$View; diff --git a/tools/templates/crud/client/containers/Module.jsx b/tools/templates/crud/client/containers/Module.jsx new file mode 100644 index 0000000000..59510a61c5 --- /dev/null +++ b/tools/templates/crud/client/containers/Module.jsx @@ -0,0 +1,15 @@ +/*eslint-disable no-unused-vars*/ +import React from 'react'; +import { graphql, compose } from 'react-apollo'; + +import $Module$View from '../components/$Module$View'; + +class $Module$ extends React.Component { + render() { + return <$Module$View {...this.props} />; + } +} + +const $Module$WithApollo = compose()($Module$); + +export default $Module$WithApollo; diff --git a/tools/templates/crud/client/containers/Module.spec.js b/tools/templates/crud/client/containers/Module.spec.js new file mode 100644 index 0000000000..29ebdb682e --- /dev/null +++ b/tools/templates/crud/client/containers/Module.spec.js @@ -0,0 +1,17 @@ +import { expect } from 'chai'; +import { step } from 'mocha-steps'; +import Renderer from '../../../../client/testHelpers/Renderer'; +import Routes from '../../../../client/app/Routes'; + +describe('$Module$ UI works', () => { + const renderer = new Renderer({}); + let app; + let content; + + step('$Module$ page renders on mount', () => { + app = renderer.mount(Routes); + renderer.history.push('/$module$'); + content = app.find('#content'); + expect(content).to.not.be.empty; + }); +}); diff --git a/tools/templates/crud/client/graphql/ModuleQuery.graphql b/tools/templates/crud/client/graphql/ModuleQuery.graphql new file mode 100644 index 0000000000..61470c8960 --- /dev/null +++ b/tools/templates/crud/client/graphql/ModuleQuery.graphql @@ -0,0 +1,3 @@ +fragment $Module$Info on $Module$ { + id +} \ No newline at end of file diff --git a/tools/templates/crud/client/index.jsx b/tools/templates/crud/client/index.jsx new file mode 100644 index 0000000000..e61b873a24 --- /dev/null +++ b/tools/templates/crud/client/index.jsx @@ -0,0 +1,21 @@ +import { Ionicons } from '@expo/vector-icons'; +import { createTabBarIconWrapper } from '../common/components/native'; +import $Module$ from './containers/$Module$'; +import reducers from './reducers'; + +import Feature from '../connector'; + +export default new Feature({ + tabItem: { + $Module$: { + screen: $Module$, + navigationOptions: { + tabBarIcon: createTabBarIconWrapper(Ionicons, { + name: 'ios-browsers-outline', + size: 30 + }) + } + } + }, + reducer: { $module$: reducers } +}); diff --git a/tools/templates/crud/client/index.web.jsx b/tools/templates/crud/client/index.web.jsx new file mode 100644 index 0000000000..ba6a70cd43 --- /dev/null +++ b/tools/templates/crud/client/index.web.jsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Route, NavLink } from 'react-router-dom'; +import { MenuItem } from '../../modules/common/components/web'; +import $Module$ from './containers/$Module$'; +import reducers from './reducers'; + +import Feature from '../connector'; + +export default new Feature({ + route: , + navItem: ( + + + $Module$ + + + ), + reducer: { $module$: reducers } +}); diff --git a/tools/templates/crud/client/reducers/index.js b/tools/templates/crud/client/reducers/index.js new file mode 100644 index 0000000000..6c6ee75a42 --- /dev/null +++ b/tools/templates/crud/client/reducers/index.js @@ -0,0 +1,8 @@ +const defaultState = {}; + +export default function(state = defaultState, action) { + switch (action.type) { + default: + return state; + } +} diff --git a/tools/templates/crud/server/Module.spec.js b/tools/templates/crud/server/Module.spec.js new file mode 100644 index 0000000000..223aad95c8 --- /dev/null +++ b/tools/templates/crud/server/Module.spec.js @@ -0,0 +1,23 @@ +/*eslint-disable no-unused-vars*/ +import chai from 'chai'; +import { step } from 'mocha-steps'; +import { getServer, getApollo } from '../../testHelpers/integrationSetup'; + +describe('$Module$ API works', () => { + let server, apollo; + + before(() => { + server = getServer(); + apollo = getApollo(); + }); + + step('Has GraphiQL endpoint', () => { + return chai + .request(server) + .get('/graphiql') + .end((err, res) => { + res.status.should.be(200); + res.body.should.be('{}'); + }); + }); +}); diff --git a/tools/templates/crud/server/index.js b/tools/templates/crud/server/index.js new file mode 100644 index 0000000000..250cfbc59f --- /dev/null +++ b/tools/templates/crud/server/index.js @@ -0,0 +1,10 @@ +import $Module$ from './sql'; +import schema from './schema.graphqls'; +import createResolvers from './resolvers'; +import Feature from '../connector'; + +export default new Feature({ + schema, + createResolversFunc: createResolvers, + createContextFunc: () => ({ $Module$: new $Module$() }) +}); diff --git a/tools/templates/crud/server/resolvers.js b/tools/templates/crud/server/resolvers.js new file mode 100644 index 0000000000..13582f9182 --- /dev/null +++ b/tools/templates/crud/server/resolvers.js @@ -0,0 +1,6 @@ +/*eslint-disable no-unused-vars*/ +export default pubsub => ({ + Query: {}, + Mutation: {}, + Subscription: {} +}); diff --git a/tools/templates/crud/server/schema.graphqls b/tools/templates/crud/server/schema.graphqls new file mode 100644 index 0000000000..b224b3517b --- /dev/null +++ b/tools/templates/crud/server/schema.graphqls @@ -0,0 +1,5 @@ +extend type Query {} + +extend type Mutation {} + +extend type Subscription {} diff --git a/tools/templates/crud/server/sql.js b/tools/templates/crud/server/sql.js new file mode 100644 index 0000000000..a358efaab1 --- /dev/null +++ b/tools/templates/crud/server/sql.js @@ -0,0 +1,4 @@ +/*eslint-disable no-unused-vars*/ +import knex from '../../../server/sql/connector'; + +export default class $Module$ {} From 206fca5880f733717a8ffd770e31deb05a06ed82 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Tue, 21 Nov 2017 14:58:12 +0100 Subject: [PATCH 005/327] add domain schema packages --- package.json | 4 ++++ yarn.lock | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/package.json b/package.json index 4442d721ff..4e41979c2f 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,10 @@ "bootstrap": "4.0.0-beta.2", "cors": "^2.8.4", "dataloader": "^1.3.0", + "domain-graphql": "^0.0.7", + "domain-knex": "^0.0.7", + "domain-react-forms": "^0.0.7", + "domain-schema": "^0.0.7", "dotenv": "^4.0.0", "expo": "^23.0.0", "express": "^4.16.2", diff --git a/yarn.lock b/yarn.lock index 7c80ce8685..14e0c08ef1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3383,6 +3383,24 @@ domain-browser@^1.1.1: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" +domain-graphql@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/domain-graphql/-/domain-graphql-0.0.7.tgz#c7e2d8f9a4025dad859a7f9805306faf0054fb9e" + +domain-knex@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/domain-knex/-/domain-knex-0.0.7.tgz#134ae39221f523fbed5d717f200a8b3aaa1758d9" + dependencies: + humps "^2.0.1" + +domain-react-forms@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/domain-react-forms/-/domain-react-forms-0.0.7.tgz#8d3979a36e451568d9d0b3e1f09c1fae23448427" + +domain-schema@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/domain-schema/-/domain-schema-0.0.7.tgz#14daf81202438b02206036cd7723f21110f6e51b" + domelementtype@1, domelementtype@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" From 4984eae75d3049f5da14a83358e6cce1f77d55cb Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Tue, 21 Nov 2017 15:13:56 +0100 Subject: [PATCH 006/327] initial setup for cli `addcrud` --- tools/cli/module.js | 19 ++++++++++--------- .../crud/database/migrations/_Module.js | 7 +++++++ .../templates/crud/database/seeds/_Module.js | 9 +++++++++ tools/templates/crud/server/schema.js | 9 +++++++++ 4 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 tools/templates/crud/database/migrations/_Module.js create mode 100644 tools/templates/crud/database/seeds/_Module.js create mode 100644 tools/templates/crud/server/schema.js diff --git a/tools/cli/module.js b/tools/cli/module.js index 042831def3..c0895cfcf2 100644 --- a/tools/cli/module.js +++ b/tools/cli/module.js @@ -16,7 +16,7 @@ String.prototype.capitalize = function() { return this.charAt(0).toUpperCase() + this.slice(1); }; -function copyFiles(logger, templatePath, module, location) { +function copyFiles(logger, templatePath, module, action, location) { logger.info(`Copying ${location} files…`); // create new module directory @@ -64,11 +64,15 @@ function copyFiles(logger, templatePath, module, location) { // add module to Feature function shell.sed('-i', re, `Feature(${module}, ${match[1]})`, 'index.js'); + if (action === 'addcrud' && location === 'server') { + console.log('copy database files'); + } + logger.info(`✔ Module for ${location} successfully created!`); } } -function deleteFiles(logger, templatePath, module, location) { +function deleteFiles(logger, templatePath, module, action, location) { logger.info(`Deleting ${location} files…`); const modulePath = `${__dirname}/../../src/${location}/modules/${module}`; @@ -80,9 +84,6 @@ function deleteFiles(logger, templatePath, module, location) { // change to destination directory shell.cd(`${__dirname}/../../src/${location}/modules/`); - // add module to Feature function - //let ok = shell.sed('-i', `import ${module} from '.\/${module}';`, '', 'index.js'); - // get module input data const path = `${__dirname}/../../src/${location}/modules/index.js`; let data = fs.readFileSync(path); @@ -159,18 +160,18 @@ module.exports = (action, args, options, logger) => { // client if (location === 'client' || location === 'both') { if (action === 'addmodule' || action === 'addcrud') { - copyFiles(logger, templatePath, module, 'client'); + copyFiles(logger, templatePath, module, action, 'client'); } else if (action === 'deletemodule') { - deleteFiles(logger, templatePath, module, 'client'); + deleteFiles(logger, templatePath, module, action, 'client'); } } // server if (location === 'server' || location === 'both') { if (action === 'addmodule' || action === 'addcrud') { - copyFiles(logger, templatePath, module, 'server'); + copyFiles(logger, templatePath, module, action, 'server'); } else if (action === 'deletemodule') { - deleteFiles(logger, templatePath, module, 'server'); + deleteFiles(logger, templatePath, module, action, 'server'); } } diff --git a/tools/templates/crud/database/migrations/_Module.js b/tools/templates/crud/database/migrations/_Module.js new file mode 100644 index 0000000000..661a1a3b26 --- /dev/null +++ b/tools/templates/crud/database/migrations/_Module.js @@ -0,0 +1,7 @@ +import KnexGenerator from 'domain-knex'; + +import { $Module$ } from '../../modules/$module$/schema'; + +exports.up = knex => new KnexGenerator(knex).createTables($Module$); + +exports.down = knex => new KnexGenerator(knex).dropTables($Module$); diff --git a/tools/templates/crud/database/seeds/_Module.js b/tools/templates/crud/database/seeds/_Module.js new file mode 100644 index 0000000000..050959a956 --- /dev/null +++ b/tools/templates/crud/database/seeds/_Module.js @@ -0,0 +1,9 @@ +import truncateTables from '../../../common/db'; + +export async function seed(knex, Promise) { + await truncateTables(knex, Promise, ['$module$']); + + await knex('$module$') + .returning('id') + .insert({}); +} diff --git a/tools/templates/crud/server/schema.js b/tools/templates/crud/server/schema.js new file mode 100644 index 0000000000..ffe8d19155 --- /dev/null +++ b/tools/templates/crud/server/schema.js @@ -0,0 +1,9 @@ +import DomainSchema, { Schema } from 'domain-schema'; + +/* eslint import/prefer-default-export: 0 */ + +export const $Module$ = new DomainSchema( + class $Module$ extends Schema { + id = DomainSchema.Integer; + } +); From 74d6585fa6e405d0642c807e1d70eb6c7db6e9b7 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Tue, 21 Nov 2017 15:46:02 +0100 Subject: [PATCH 007/327] add database files --- tools/cli/module.js | 64 +++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/tools/cli/module.js b/tools/cli/module.js index c0895cfcf2..09981ff916 100644 --- a/tools/cli/module.js +++ b/tools/cli/module.js @@ -16,6 +16,29 @@ String.prototype.capitalize = function() { return this.charAt(0).toUpperCase() + this.slice(1); }; +function renameFiles(destinationPath, templatePath, module, location) { + shell.cp('-R', `${templatePath}/${location}/*`, destinationPath); + + // change to destination directory + shell.cd(destinationPath); + + // rename files + shell.ls('-Rl', '.').forEach(entry => { + if (entry.isFile()) { + const moduleFile = entry.name.replace('Module', module.capitalize()); + shell.mv(entry.name, moduleFile); + } + }); + + // replace module names + shell.ls('-Rl', '.').forEach(entry => { + if (entry.isFile()) { + shell.sed('-i', /\$module\$/g, module, entry.name); + shell.sed('-i', /\$Module\$/g, module.toCamelCase().capitalize(), entry.name); + } + }); +} + function copyFiles(logger, templatePath, module, action, location) { logger.info(`Copying ${location} files…`); @@ -25,29 +48,10 @@ function copyFiles(logger, templatePath, module, action, location) { // continue only if directory does not jet exist if (mkdir.code === 0) { const destinationPath = `${__dirname}/../../src/${location}/modules/${module}`; - shell.cp('-R', `${templatePath}/${location}/*`, destinationPath); + renameFiles(destinationPath, templatePath, module, location); logger.info(`✔ The ${location} files have been copied!`); - // change to destination directory - shell.cd(destinationPath); - - // rename files - shell.ls('-Rl', '.').forEach(entry => { - if (entry.isFile()) { - const moduleFile = entry.name.replace('Module', module.capitalize()); - shell.mv(entry.name, moduleFile); - } - }); - - // replace module names - shell.ls('-Rl', '.').forEach(entry => { - if (entry.isFile()) { - shell.sed('-i', /\$module\$/g, module, entry.name); - shell.sed('-i', /\$Module\$/g, module.toCamelCase().capitalize(), entry.name); - } - }); - shell.cd('..'); // get module input data const path = `${__dirname}/../../src/${location}/modules/index.js`; @@ -66,6 +70,16 @@ function copyFiles(logger, templatePath, module, action, location) { if (action === 'addcrud' && location === 'server') { console.log('copy database files'); + const destinationPath = `${__dirname}/../../src/${location}/database`; + renameFiles(destinationPath, templatePath, module, 'database'); + + const timestamp = new Date().getTime(); + shell.cd(`${__dirname}/../../src/${location}/database/migrations`); + shell.mv(`_${module.toCamelCase().capitalize()}.js`, `${timestamp}_${module.toCamelCase().capitalize()}.js`); + shell.cd(`${__dirname}/../../src/${location}/database/seeds`); + shell.mv(`_${module.toCamelCase().capitalize()}.js`, `${timestamp}_${module.toCamelCase().capitalize()}.js`); + + logger.info(`✔ The database files have been copied!`); } logger.info(`✔ Module for ${location} successfully created!`); @@ -103,6 +117,16 @@ function deleteFiles(logger, templatePath, module, action, location) { // remove module from Feature function shell.sed('-i', re, `Feature(${modules.toString().trim()})`, 'index.js'); + if (action === 'addcrud' && location === 'server') { + // change to destination directory + shell.cd(`${__dirname}/../../src/${location}/database/migrations`); + // TODO: remove database files + /*const aa = shell.find('.').filter(function(file) { + return file.match(/\.js$/); + }); + console.log(aa);*/ + } + // continue only if directory does not jet exist logger.info(`✔ Module for ${location} successfully deleted!`); } else { From 4792baa26a81ba64b6bd8f01417a42c82f694eab Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 22 Nov 2017 08:11:20 +0100 Subject: [PATCH 008/327] handle migration files, add log colors, fix `schemaupdate` --- tools/cli/module.js | 91 +++++++++++-------- .../{ModuleQuery.graphql => Module.graphql} | 0 2 files changed, 55 insertions(+), 36 deletions(-) rename tools/templates/crud/client/graphql/{ModuleQuery.graphql => Module.graphql} (100%) diff --git a/tools/cli/module.js b/tools/cli/module.js index 09981ff916..75e2a72242 100644 --- a/tools/cli/module.js +++ b/tools/cli/module.js @@ -4,6 +4,7 @@ require('babel-polyfill'); const shell = require('shelljs'); const fs = require('fs'); +const chalk = require('chalk'); String.prototype.toCamelCase = function() { return this.replace(/^([A-Z])|\s(\w)/g, function(match, p1, p2) { @@ -50,7 +51,7 @@ function copyFiles(logger, templatePath, module, action, location) { const destinationPath = `${__dirname}/../../src/${location}/modules/${module}`; renameFiles(destinationPath, templatePath, module, location); - logger.info(`✔ The ${location} files have been copied!`); + logger.info(chalk.green(`✔ The ${location} files have been copied!`)); shell.cd('..'); // get module input data @@ -79,14 +80,14 @@ function copyFiles(logger, templatePath, module, action, location) { shell.cd(`${__dirname}/../../src/${location}/database/seeds`); shell.mv(`_${module.toCamelCase().capitalize()}.js`, `${timestamp}_${module.toCamelCase().capitalize()}.js`); - logger.info(`✔ The database files have been copied!`); + logger.info(chalk.green(`✔ The database files have been copied!`)); } - logger.info(`✔ Module for ${location} successfully created!`); + logger.info(chalk.green(`✔ Module for ${location} successfully created!`)); } } -function deleteFiles(logger, templatePath, module, action, location) { +function deleteFiles(logger, templatePath, module, location) { logger.info(`Deleting ${location} files…`); const modulePath = `${__dirname}/../../src/${location}/modules/${module}`; @@ -117,20 +118,32 @@ function deleteFiles(logger, templatePath, module, action, location) { // remove module from Feature function shell.sed('-i', re, `Feature(${modules.toString().trim()})`, 'index.js'); - if (action === 'addcrud' && location === 'server') { - // change to destination directory + if (location === 'server') { + // change to database migrations directory shell.cd(`${__dirname}/../../src/${location}/database/migrations`); - // TODO: remove database files - /*const aa = shell.find('.').filter(function(file) { - return file.match(/\.js$/); - }); - console.log(aa);*/ + // check if any migrations files for this module exist + if (shell.find('.').filter(file => file.search(`_${module.toCamelCase().capitalize()}.js`) > -1).length > 0) { + let okMigrations = shell.rm(`*_${module.toCamelCase().capitalize()}.js`); + if (okMigrations) { + logger.info(chalk.green(`✔ Database migrations files successfully deleted!`)); + } + } + + // change to database seeds directory + shell.cd(`${__dirname}/../../src/${location}/database/seeds`); + // check if any seed files for this module exist + if (shell.find('.').filter(file => file.search(`_${module.toCamelCase().capitalize()}.js`) > -1).length > 0) { + let okSeeds = shell.rm(`*_${module.toCamelCase().capitalize()}.js`); + if (okSeeds) { + logger.info(chalk.green(`✔ Database seed files successfully deleted!`)); + } + } } // continue only if directory does not jet exist - logger.info(`✔ Module for ${location} successfully deleted!`); + logger.info(chalk.green(`✔ Module for ${location} successfully deleted!`)); } else { - logger.info(`✔ Module ${location} location for ${modulePath} wasn't found!`); + logger.info(chalk.red(`✘ Module ${location} location for ${modulePath} not found!`)); } } @@ -139,29 +152,35 @@ function updateSchema(logger, module) { // get fragment file const path = `${__dirname}/../../src/client/modules/${module}/graphql/`; - const file = `${module.toCamelCase().capitalize()}.graphql`; - const re = /\{([^()]+)\}/g; + if (fs.existsSync(path)) { + const file = `${module.toCamelCase().capitalize()}.graphql`; + const re = /\{([^()]+)\}/g; - // get module schema - const schema = require(`../../src/server/modules/${module}/schema`); + // get module schema + const schema = require(`../../src/server/modules/${module}/schema`); - // regenerate graphql fragment - let graphql = '{\n'; - for (const key of Object.keys(schema[module.toCamelCase().capitalize()].values)) { - graphql += ` ${key}\n`; + // regenerate graphql fragment + let graphql = '{\n'; + for (const key of Object.keys(schema[module.toCamelCase().capitalize()].values)) { + graphql += ` ${key}\n`; + } + graphql += '}'; + + // override graphql fragment file + shell.cd(path); + // remove all new lines + shell.exec(`tr -d '\n' < ${file} > ${file}.tmp`); + // replace content + shell.sed('-i', re, graphql, `${file}.tmp`); + // remove old file + shell.rm(file); + // rename tmp file + shell.mv(`${file}.tmp`, file); + + logger.info(chalk.green(`✔ Fragment in ${path}${file} successfully updated!`)); + } else { + logger.error(chalk.red(`✘ Path ${path} not found!`)); } - graphql += '}'; - - // override graphql fragment file - shell.cd(path); - // remove all new lines - shell.exec(`tr -d '\n' < ${file} > ${file}.tmp`); - // replace content - shell.sed('-i', re, graphql, `${file}.tmp`); - // remove old file - shell.rm(file); - // rename tmp file - shell.mv(`${file}.tmp`, file); } module.exports = (action, args, options, logger) => { @@ -177,7 +196,7 @@ module.exports = (action, args, options, logger) => { } if (!fs.existsSync(templatePath)) { - logger.error(`The requested location for ${location} wasn't found.`); + logger.error(chalk.red(`The requested location for ${location} not found.`)); process.exit(1); } @@ -186,7 +205,7 @@ module.exports = (action, args, options, logger) => { if (action === 'addmodule' || action === 'addcrud') { copyFiles(logger, templatePath, module, action, 'client'); } else if (action === 'deletemodule') { - deleteFiles(logger, templatePath, module, action, 'client'); + deleteFiles(logger, templatePath, module, 'client'); } } @@ -195,7 +214,7 @@ module.exports = (action, args, options, logger) => { if (action === 'addmodule' || action === 'addcrud') { copyFiles(logger, templatePath, module, action, 'server'); } else if (action === 'deletemodule') { - deleteFiles(logger, templatePath, module, action, 'server'); + deleteFiles(logger, templatePath, module, 'server'); } } diff --git a/tools/templates/crud/client/graphql/ModuleQuery.graphql b/tools/templates/crud/client/graphql/Module.graphql similarity index 100% rename from tools/templates/crud/client/graphql/ModuleQuery.graphql rename to tools/templates/crud/client/graphql/Module.graphql From 01d6db62f7c025f1fc5f99c3ca15d882fb9b744a Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 22 Nov 2017 08:57:23 +0100 Subject: [PATCH 009/327] auto generate select --- knexfile.js | 2 +- src/server/modules/user/sql.js | 1 - tools/templates/crud/server/index.js | 5 ++++- tools/templates/crud/server/resolvers.js | 6 +++++- tools/templates/crud/server/schema.graphqls | 4 +++- tools/templates/crud/server/sql.js | 9 +++++++-- 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/knexfile.js b/knexfile.js index 280055a346..23f3d2caf8 100644 --- a/knexfile.js +++ b/knexfile.js @@ -1,5 +1,5 @@ /* eslint import/no-extraneous-dependencies: 0 */ -require('babel-register')({ presets: ['env'] }); +require('babel-register')({ presets: ['env'], plugins: ['transform-class-properties'] }); require('babel-polyfill'); const config = require('./knexdata'); diff --git a/src/server/modules/user/sql.js b/src/server/modules/user/sql.js index 4be3a1f7a1..3e989b4822 100644 --- a/src/server/modules/user/sql.js +++ b/src/server/modules/user/sql.js @@ -1,4 +1,3 @@ -// Helpers import { camelizeKeys, decamelizeKeys, decamelize } from 'humps'; import { has } from 'lodash'; import bcrypt from 'bcryptjs'; diff --git a/tools/templates/crud/server/index.js b/tools/templates/crud/server/index.js index 250cfbc59f..4dad072b00 100644 --- a/tools/templates/crud/server/index.js +++ b/tools/templates/crud/server/index.js @@ -1,10 +1,13 @@ +import GraphQLGenerator from 'domain-graphql'; + +import { $Module$ as $Module$Schema } from './schema'; import $Module$ from './sql'; import schema from './schema.graphqls'; import createResolvers from './resolvers'; import Feature from '../connector'; export default new Feature({ - schema, + schema: [schema, new GraphQLGenerator().generateTypes($Module$Schema)], createResolversFunc: createResolvers, createContextFunc: () => ({ $Module$: new $Module$() }) }); diff --git a/tools/templates/crud/server/resolvers.js b/tools/templates/crud/server/resolvers.js index 13582f9182..a55f46ac02 100644 --- a/tools/templates/crud/server/resolvers.js +++ b/tools/templates/crud/server/resolvers.js @@ -1,6 +1,10 @@ /*eslint-disable no-unused-vars*/ export default pubsub => ({ - Query: {}, + Query: { + $module$s: (obj, args, { $Module$ }) => { + return $Module$.get$Module$s(); + } + }, Mutation: {}, Subscription: {} }); diff --git a/tools/templates/crud/server/schema.graphqls b/tools/templates/crud/server/schema.graphqls index b224b3517b..6dc1ba5533 100644 --- a/tools/templates/crud/server/schema.graphqls +++ b/tools/templates/crud/server/schema.graphqls @@ -1,4 +1,6 @@ -extend type Query {} +extend type Query { + $module$s: [$Module$] +} extend type Mutation {} diff --git a/tools/templates/crud/server/sql.js b/tools/templates/crud/server/sql.js index a358efaab1..628f840a83 100644 --- a/tools/templates/crud/server/sql.js +++ b/tools/templates/crud/server/sql.js @@ -1,4 +1,9 @@ -/*eslint-disable no-unused-vars*/ +import { camelizeKeys } from 'humps'; + import knex from '../../../server/sql/connector'; -export default class $Module$ {} +export default class $Module$ { + async get$Module$s() { + return camelizeKeys(await knex.select('id').from('$module$')); + } +} From c3f66e22c4abc0dd06dbc058d11904f4194b56b8 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 22 Nov 2017 11:21:18 +0100 Subject: [PATCH 010/327] module list --- .../modules/user/containers/UsersList.jsx | 5 --- tools/cli/module.js | 1 + .../{ModuleView.jsx => ModuleListView.jsx} | 4 +-- .../client/components/ModuleListView.web.jsx | 32 +++++++++++++++++++ .../crud/client/components/ModuleView.web.jsx | 28 ---------------- .../crud/client/containers/Module.jsx | 15 --------- .../crud/client/containers/ModuleList.jsx | 26 +++++++++++++++ .../crud/client/graphql/ModulesQuery.graphql | 7 ++++ tools/templates/crud/client/index.jsx | 4 +-- tools/templates/crud/client/index.web.jsx | 4 +-- .../client/components/ModuleView.web.jsx | 2 +- 11 files changed, 73 insertions(+), 55 deletions(-) rename tools/templates/crud/client/components/{ModuleView.jsx => ModuleListView.jsx} (88%) create mode 100644 tools/templates/crud/client/components/ModuleListView.web.jsx delete mode 100644 tools/templates/crud/client/components/ModuleView.web.jsx delete mode 100644 tools/templates/crud/client/containers/Module.jsx create mode 100644 tools/templates/crud/client/containers/ModuleList.jsx create mode 100644 tools/templates/crud/client/graphql/ModulesQuery.graphql diff --git a/src/client/modules/user/containers/UsersList.jsx b/src/client/modules/user/containers/UsersList.jsx index a220c7850b..0f89ac0eea 100644 --- a/src/client/modules/user/containers/UsersList.jsx +++ b/src/client/modules/user/containers/UsersList.jsx @@ -1,15 +1,10 @@ /*eslint-disable no-unused-vars*/ -// React import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; - -// Apollo import { graphql, compose } from 'react-apollo'; -// Components import UsersListView from '../components/UsersListView'; - import USERS_QUERY from '../graphql/UsersQuery.graphql'; import DELETE_USER from '../graphql/DeleteUser.graphql'; diff --git a/tools/cli/module.js b/tools/cli/module.js index 75e2a72242..c9642eea61 100644 --- a/tools/cli/module.js +++ b/tools/cli/module.js @@ -36,6 +36,7 @@ function renameFiles(destinationPath, templatePath, module, location) { if (entry.isFile()) { shell.sed('-i', /\$module\$/g, module, entry.name); shell.sed('-i', /\$Module\$/g, module.toCamelCase().capitalize(), entry.name); + shell.sed('-i', /\$MODULE\$/g, module.toUpperCase(), entry.name); } }); } diff --git a/tools/templates/crud/client/components/ModuleView.jsx b/tools/templates/crud/client/components/ModuleListView.jsx similarity index 88% rename from tools/templates/crud/client/components/ModuleView.jsx rename to tools/templates/crud/client/components/ModuleListView.jsx index 04c16384fe..8397d51928 100644 --- a/tools/templates/crud/client/components/ModuleView.jsx +++ b/tools/templates/crud/client/components/ModuleListView.jsx @@ -1,7 +1,7 @@ import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; -const $Module$View = () => { +const $Module$ListView = () => { return ( @@ -28,4 +28,4 @@ const styles = StyleSheet.create({ } }); -export default $Module$View; +export default $Module$ListView; diff --git a/tools/templates/crud/client/components/ModuleListView.web.jsx b/tools/templates/crud/client/components/ModuleListView.web.jsx new file mode 100644 index 0000000000..8e2b8530f8 --- /dev/null +++ b/tools/templates/crud/client/components/ModuleListView.web.jsx @@ -0,0 +1,32 @@ +import React from 'react'; +import Helmet from 'react-helmet'; +import { PageLayout } from '../../common/components/web'; + +class $Module$ListView extends React.PureComponent { + renderMetaData = () => ( + + ); + + render() { + const { loading, $module$s } = this.props; + console.log($module$s); + return ( + + {this.renderMetaData()} +
+

Hello $Module$ list!

+
+
+ ); + } +}; + +export default $Module$ListView; diff --git a/tools/templates/crud/client/components/ModuleView.web.jsx b/tools/templates/crud/client/components/ModuleView.web.jsx deleted file mode 100644 index 49bca7ba8b..0000000000 --- a/tools/templates/crud/client/components/ModuleView.web.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import Helmet from 'react-helmet'; -import { PageLayout } from '../../common/components/web'; - -const renderMetaData = () => ( - -); - -const $Module$View = () => { - return ( - - {renderMetaData()} -
-

Hello $Module$!

-
-
- ); -}; - -export default $Module$View; diff --git a/tools/templates/crud/client/containers/Module.jsx b/tools/templates/crud/client/containers/Module.jsx deleted file mode 100644 index 59510a61c5..0000000000 --- a/tools/templates/crud/client/containers/Module.jsx +++ /dev/null @@ -1,15 +0,0 @@ -/*eslint-disable no-unused-vars*/ -import React from 'react'; -import { graphql, compose } from 'react-apollo'; - -import $Module$View from '../components/$Module$View'; - -class $Module$ extends React.Component { - render() { - return <$Module$View {...this.props} />; - } -} - -const $Module$WithApollo = compose()($Module$); - -export default $Module$WithApollo; diff --git a/tools/templates/crud/client/containers/ModuleList.jsx b/tools/templates/crud/client/containers/ModuleList.jsx new file mode 100644 index 0000000000..e0f1f26cf5 --- /dev/null +++ b/tools/templates/crud/client/containers/ModuleList.jsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { graphql, compose } from 'react-apollo'; + +import $Module$ListView from '../components/$Module$ListView'; +import $MODULE$S_QUERY from '../graphql/$Module$sQuery.graphql'; + +class $Module$ extends React.Component { + render() { + return <$Module$ListView {...this.props} />; + } +} + +const $Module$WithApollo = compose( + graphql($MODULE$S_QUERY, { + options: () => { + return { + fetchPolicy: 'cache-and-network' + }; + }, + props({ data: { loading, $module$s, refetch, error } }) { + return { loading, $module$s, refetch, errors: error ? error.graphQLErrors : null }; + } + }), +)($Module$); + +export default $Module$WithApollo; diff --git a/tools/templates/crud/client/graphql/ModulesQuery.graphql b/tools/templates/crud/client/graphql/ModulesQuery.graphql new file mode 100644 index 0000000000..b818cb8fbc --- /dev/null +++ b/tools/templates/crud/client/graphql/ModulesQuery.graphql @@ -0,0 +1,7 @@ +#import "./$Module$.graphql" + +query $module$s { + $module$s { + ...$Module$Info + } +} diff --git a/tools/templates/crud/client/index.jsx b/tools/templates/crud/client/index.jsx index e61b873a24..907df0b37c 100644 --- a/tools/templates/crud/client/index.jsx +++ b/tools/templates/crud/client/index.jsx @@ -1,6 +1,6 @@ import { Ionicons } from '@expo/vector-icons'; import { createTabBarIconWrapper } from '../common/components/native'; -import $Module$ from './containers/$Module$'; +import $Module$List from './containers/$Module$List'; import reducers from './reducers'; import Feature from '../connector'; @@ -8,7 +8,7 @@ import Feature from '../connector'; export default new Feature({ tabItem: { $Module$: { - screen: $Module$, + screen: $Module$List, navigationOptions: { tabBarIcon: createTabBarIconWrapper(Ionicons, { name: 'ios-browsers-outline', diff --git a/tools/templates/crud/client/index.web.jsx b/tools/templates/crud/client/index.web.jsx index ba6a70cd43..560e9ea9b3 100644 --- a/tools/templates/crud/client/index.web.jsx +++ b/tools/templates/crud/client/index.web.jsx @@ -1,13 +1,13 @@ import React from 'react'; import { Route, NavLink } from 'react-router-dom'; import { MenuItem } from '../../modules/common/components/web'; -import $Module$ from './containers/$Module$'; +import $Module$List from './containers/$Module$List'; import reducers from './reducers'; import Feature from '../connector'; export default new Feature({ - route: , + route: , navItem: ( diff --git a/tools/templates/module/client/components/ModuleView.web.jsx b/tools/templates/module/client/components/ModuleView.web.jsx index 49bca7ba8b..0f3c1bfe3e 100644 --- a/tools/templates/module/client/components/ModuleView.web.jsx +++ b/tools/templates/module/client/components/ModuleView.web.jsx @@ -18,7 +18,7 @@ const $Module$View = () => { return ( {renderMetaData()} -
+

Hello $Module$!

From 4c21c15beaba4a838d54f84b363cd7418ee76563 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 22 Nov 2017 11:46:05 +0100 Subject: [PATCH 011/327] list table --- .../modules/ui-bootstrap/components/Table.jsx | 8 +-- .../client/components/ModuleListView.web.jsx | 49 +++++++++++++++++-- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/client/modules/ui-bootstrap/components/Table.jsx b/src/client/modules/ui-bootstrap/components/Table.jsx index 4cb4e0f62f..82e44d8374 100644 --- a/src/client/modules/ui-bootstrap/components/Table.jsx +++ b/src/client/modules/ui-bootstrap/components/Table.jsx @@ -24,20 +24,22 @@ const renderData = (columns, entry) => { }); }; -const Table = ({ dataSource, columns, ...props }) => { +const Table = ({ dataSource, columns, pagination, loading, ...props }) => { return ( {renderHead(columns)} - {renderBody(columns, dataSource)} + {dataSource && renderBody(columns, dataSource)} ); }; Table.propTypes = { dataSource: PropTypes.array, - columns: PropTypes.array + columns: PropTypes.array, + pagination: PropTypes.bool, + loading: PropTypes.bool }; export default Table; diff --git a/tools/templates/crud/client/components/ModuleListView.web.jsx b/tools/templates/crud/client/components/ModuleListView.web.jsx index 8e2b8530f8..df185ad32b 100644 --- a/tools/templates/crud/client/components/ModuleListView.web.jsx +++ b/tools/templates/crud/client/components/ModuleListView.web.jsx @@ -1,6 +1,9 @@ import React from 'react'; +import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; -import { PageLayout } from '../../common/components/web'; +import { Link } from 'react-router-dom'; + +import { PageLayout, Table, Button } from '../../common/components/web'; class $Module$ListView extends React.PureComponent { renderMetaData = () => ( @@ -15,18 +18,54 @@ class $Module$ListView extends React.PureComponent { /> ); + hendleDelete$Module$ = async id => { + console.log(id); + /*const { deleteUser } = this.props; + const result = await deleteUser(id); + if (result && result.errors) { + this.setState({ errors: result.errors }); + } else { + this.setState({ errors: [] }); + }*/ + }; + + columns = [ + { + title: 'Id', + dataIndex: 'id', + key: 'id', + render: (text, record) => ( + + {text} + + ) + }, + { + title: 'Actions', + key: 'actions', + render: (text, record) => ( + + ) + } + ]; + render() { const { loading, $module$s } = this.props; - console.log($module$s); + return ( {this.renderMetaData()} -
-

Hello $Module$ list!

-
+ ); } +} + +$Module$ListView.propTypes = { + loading: PropTypes.bool.isRequired, + $module$s: PropTypes.array }; export default $Module$ListView; From 1edfdecb4405fad7415bed8ac2484b998a677ad3 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 22 Nov 2017 13:09:35 +0100 Subject: [PATCH 012/327] refactor update schema --- tools/cli/module.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/tools/cli/module.js b/tools/cli/module.js index c9642eea61..2d9ff01e84 100644 --- a/tools/cli/module.js +++ b/tools/cli/module.js @@ -155,28 +155,19 @@ function updateSchema(logger, module) { const path = `${__dirname}/../../src/client/modules/${module}/graphql/`; if (fs.existsSync(path)) { const file = `${module.toCamelCase().capitalize()}.graphql`; - const re = /\{([^()]+)\}/g; // get module schema const schema = require(`../../src/server/modules/${module}/schema`); // regenerate graphql fragment - let graphql = '{\n'; + let graphql = ''; for (const key of Object.keys(schema[module.toCamelCase().capitalize()].values)) { graphql += ` ${key}\n`; } - graphql += '}'; - // override graphql fragment file shell.cd(path); - // remove all new lines - shell.exec(`tr -d '\n' < ${file} > ${file}.tmp`); - // replace content - shell.sed('-i', re, graphql, `${file}.tmp`); - // remove old file - shell.rm(file); - // rename tmp file - shell.mv(`${file}.tmp`, file); + // override graphql fragment file + shell.ShellString(shell.cat(file).replace(/Crud {(.|\n)*\n}/, `Crud {\n${graphql}}`)).to(file); logger.info(chalk.green(`✔ Fragment in ${path}${file} successfully updated!`)); } else { From 97b1fe3937ffed121f0a90b2b5593c870b124ed2 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 22 Nov 2017 13:42:45 +0100 Subject: [PATCH 013/327] make it work if adding new field to schema --- src/client/modules/common/util.js | 43 +++++++++++++++++++ .../client/components/ModuleListView.web.jsx | 31 ++++--------- tools/templates/crud/server/sql.js | 2 +- 3 files changed, 52 insertions(+), 24 deletions(-) create mode 100644 src/client/modules/common/util.js diff --git a/src/client/modules/common/util.js b/src/client/modules/common/util.js new file mode 100644 index 0000000000..1583440f42 --- /dev/null +++ b/src/client/modules/common/util.js @@ -0,0 +1,43 @@ +/* eslint-disable react/display-name */ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { Button } from './components/web'; + +const createTableColumns = schema => { + let columns = []; + + for (const key of Object.keys(schema.values)) { + if (key === 'id') { + columns.push({ + title: 'Id', + dataIndex: 'id', + key: 'id', + render: (text, record) => ( + + {text} + + ) + }); + } else { + columns.push({ + title: key, + dataIndex: key, + key: key + }); + } + } + + columns.push({ + title: 'Actions', + key: 'actions', + render: (text, record) => ( + + ) + }); + + return columns; +}; + +export default createTableColumns; diff --git a/tools/templates/crud/client/components/ModuleListView.web.jsx b/tools/templates/crud/client/components/ModuleListView.web.jsx index df185ad32b..1cf0ec414e 100644 --- a/tools/templates/crud/client/components/ModuleListView.web.jsx +++ b/tools/templates/crud/client/components/ModuleListView.web.jsx @@ -4,6 +4,8 @@ import Helmet from 'react-helmet'; import { Link } from 'react-router-dom'; import { PageLayout, Table, Button } from '../../common/components/web'; +import createTableColumns from '../../common/util'; +import { $Module$ as $Module$Schema } from '../../../../server/modules/$module$/schema'; class $Module$ListView extends React.PureComponent { renderMetaData = () => ( @@ -29,35 +31,18 @@ class $Module$ListView extends React.PureComponent { }*/ }; - columns = [ - { - title: 'Id', - dataIndex: 'id', - key: 'id', - render: (text, record) => ( - - {text} - - ) - }, - { - title: 'Actions', - key: 'actions', - render: (text, record) => ( - - ) - } - ]; - render() { const { loading, $module$s } = this.props; return ( {this.renderMetaData()} -
+
); } diff --git a/tools/templates/crud/server/sql.js b/tools/templates/crud/server/sql.js index 628f840a83..0041714244 100644 --- a/tools/templates/crud/server/sql.js +++ b/tools/templates/crud/server/sql.js @@ -4,6 +4,6 @@ import knex from '../../../server/sql/connector'; export default class $Module$ { async get$Module$s() { - return camelizeKeys(await knex.select('id').from('$module$')); + return camelizeKeys(await knex.select('*').from('$module$')); } } From 0b45c88e3ec1e1d968d81d0ed639773c7b3046bd Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 22 Nov 2017 14:14:02 +0100 Subject: [PATCH 014/327] delete entry --- src/client/modules/common/util.js | 4 +-- .../client/components/ModuleListView.web.jsx | 20 ++++++--------- .../crud/client/containers/ModuleList.jsx | 20 +++++++++++++++ .../crud/client/graphql/DeleteModule.graphql | 11 ++++++++ tools/templates/crud/server/resolvers.js | 25 ++++++++++++++++++- tools/templates/crud/server/schema.graphqls | 9 ++++++- tools/templates/crud/server/sql.js | 10 ++++++++ 7 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 tools/templates/crud/client/graphql/DeleteModule.graphql diff --git a/src/client/modules/common/util.js b/src/client/modules/common/util.js index 1583440f42..a5ea41ecc9 100644 --- a/src/client/modules/common/util.js +++ b/src/client/modules/common/util.js @@ -3,7 +3,7 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { Button } from './components/web'; -const createTableColumns = schema => { +const createTableColumns = (schema, hendleDelete) => { let columns = []; for (const key of Object.keys(schema.values)) { @@ -31,7 +31,7 @@ const createTableColumns = schema => { title: 'Actions', key: 'actions', render: (text, record) => ( - ) diff --git a/tools/templates/crud/client/components/ModuleListView.web.jsx b/tools/templates/crud/client/components/ModuleListView.web.jsx index 1cf0ec414e..40c0a1042f 100644 --- a/tools/templates/crud/client/components/ModuleListView.web.jsx +++ b/tools/templates/crud/client/components/ModuleListView.web.jsx @@ -1,9 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; -import { Link } from 'react-router-dom'; -import { PageLayout, Table, Button } from '../../common/components/web'; +import { PageLayout, Table } from '../../common/components/web'; import createTableColumns from '../../common/util'; import { $Module$ as $Module$Schema } from '../../../../server/modules/$module$/schema'; @@ -20,15 +19,9 @@ class $Module$ListView extends React.PureComponent { /> ); - hendleDelete$Module$ = async id => { - console.log(id); - /*const { deleteUser } = this.props; - const result = await deleteUser(id); - if (result && result.errors) { - this.setState({ errors: result.errors }); - } else { - this.setState({ errors: [] }); - }*/ + hendleDelete$Module$ = id => { + const { delete$Module$ } = this.props; + delete$Module$(id); }; render() { @@ -39,7 +32,7 @@ class $Module$ListView extends React.PureComponent { {this.renderMetaData()}
@@ -50,7 +43,8 @@ class $Module$ListView extends React.PureComponent { $Module$ListView.propTypes = { loading: PropTypes.bool.isRequired, - $module$s: PropTypes.array + $module$s: PropTypes.array, + delete$Module$: PropTypes.func.isRequired }; export default $Module$ListView; diff --git a/tools/templates/crud/client/containers/ModuleList.jsx b/tools/templates/crud/client/containers/ModuleList.jsx index e0f1f26cf5..0bf57d2e17 100644 --- a/tools/templates/crud/client/containers/ModuleList.jsx +++ b/tools/templates/crud/client/containers/ModuleList.jsx @@ -3,6 +3,7 @@ import { graphql, compose } from 'react-apollo'; import $Module$ListView from '../components/$Module$ListView'; import $MODULE$S_QUERY from '../graphql/$Module$sQuery.graphql'; +import DELETE_$MODULE$ from '../graphql/Delete$Module$.graphql'; class $Module$ extends React.Component { render() { @@ -21,6 +22,25 @@ const $Module$WithApollo = compose( return { loading, $module$s, refetch, errors: error ? error.graphQLErrors : null }; } }), + graphql(DELETE_$MODULE$, { + props: ({ ownProps: { refetch }, mutate }) => ({ + delete$Module$: async id => { + try { + const { data: { delete$Module$ } } = await mutate({ + variables: { id } + }); + + if (delete$Module$.errors) { + return { errors: delete$Module$.errors }; + } + + refetch(); + } catch (e) { + console.log(e.graphQLErrors); + } + } + }) + }) )($Module$); export default $Module$WithApollo; diff --git a/tools/templates/crud/client/graphql/DeleteModule.graphql b/tools/templates/crud/client/graphql/DeleteModule.graphql new file mode 100644 index 0000000000..2274ef6473 --- /dev/null +++ b/tools/templates/crud/client/graphql/DeleteModule.graphql @@ -0,0 +1,11 @@ +mutation delete$Module$($id: Int!) { + delete$Module$(id: $id) { + $module$ { + id + } + errors { + field + message + } + } +} diff --git a/tools/templates/crud/server/resolvers.js b/tools/templates/crud/server/resolvers.js index a55f46ac02..9002051ec6 100644 --- a/tools/templates/crud/server/resolvers.js +++ b/tools/templates/crud/server/resolvers.js @@ -1,10 +1,33 @@ /*eslint-disable no-unused-vars*/ +import FieldError from '../../../common/FieldError'; + export default pubsub => ({ Query: { $module$s: (obj, args, { $Module$ }) => { return $Module$.get$Module$s(); } }, - Mutation: {}, + Mutation: { + delete$Module$: async (obj, { id }, { $Module$ }) => { + try { + const e = new FieldError(); + const $module$ = await $Module$.get$Module$(id); + if (!$module$) { + e.setError('delete', '$Module$ does not exist.'); + e.throwIf(); + } + + const isDeleted = await $Module$.delete$Module$(id); + if (isDeleted) { + return { $module$ }; + } else { + e.setError('delete', 'Could not delete $module$. Please try again later.'); + e.throwIf(); + } + } catch (e) { + return { errors: e }; + } + } + }, Subscription: {} }); diff --git a/tools/templates/crud/server/schema.graphqls b/tools/templates/crud/server/schema.graphqls index 6dc1ba5533..61fadd66cb 100644 --- a/tools/templates/crud/server/schema.graphqls +++ b/tools/templates/crud/server/schema.graphqls @@ -1,7 +1,14 @@ +type $Module$Payload { + $module$: $Module$ + errors: [FieldError!] +} + extend type Query { $module$s: [$Module$] } -extend type Mutation {} +extend type Mutation { + delete$Module$(id: Int!): $Module$Payload! +} extend type Subscription {} diff --git a/tools/templates/crud/server/sql.js b/tools/templates/crud/server/sql.js index 0041714244..4a461d3862 100644 --- a/tools/templates/crud/server/sql.js +++ b/tools/templates/crud/server/sql.js @@ -6,4 +6,14 @@ export default class $Module$ { async get$Module$s() { return camelizeKeys(await knex.select('*').from('$module$')); } + + async get$Module$() { + return camelizeKeys(await knex.select('*').from('$module$').first()); + } + + delete$Module$(id) { + return knex('$module$') + .where('id', '=', id) + .del(); + } } From 4fdf5b908ce30bafd4f6c107fd0562972152b51a Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 22 Nov 2017 15:40:58 +0100 Subject: [PATCH 015/327] add, edit module wip --- src/client/modules/common/util.js | 4 +- src/client/modules/user/index.web.jsx | 2 +- .../crud/client/components/ModuleEditView.jsx | 31 +++++++ .../client/components/ModuleEditView.web.jsx | 75 +++++++++++++++++ .../crud/client/components/ModuleForm.web.jsx | 39 +++++++++ .../client/components/ModuleListView.web.jsx | 10 ++- .../crud/client/containers/ModuleEdit.jsx | 82 +++++++++++++++++++ .../crud/client/graphql/AddModule.graphql | 13 +++ .../crud/client/graphql/EditModule.graphql | 13 +++ .../crud/client/graphql/ModuleQuery.graphql | 8 ++ tools/templates/crud/client/index.web.jsx | 6 +- tools/templates/crud/server/resolvers.js | 27 ++++++ tools/templates/crud/server/schema.graphqls | 9 +- tools/templates/crud/server/sql.js | 12 +++ 14 files changed, 324 insertions(+), 7 deletions(-) create mode 100644 tools/templates/crud/client/components/ModuleEditView.jsx create mode 100644 tools/templates/crud/client/components/ModuleEditView.web.jsx create mode 100644 tools/templates/crud/client/components/ModuleForm.web.jsx create mode 100644 tools/templates/crud/client/containers/ModuleEdit.jsx create mode 100644 tools/templates/crud/client/graphql/AddModule.graphql create mode 100644 tools/templates/crud/client/graphql/EditModule.graphql create mode 100644 tools/templates/crud/client/graphql/ModuleQuery.graphql diff --git a/src/client/modules/common/util.js b/src/client/modules/common/util.js index a5ea41ecc9..cb60d4f34f 100644 --- a/src/client/modules/common/util.js +++ b/src/client/modules/common/util.js @@ -3,7 +3,7 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { Button } from './components/web'; -const createTableColumns = (schema, hendleDelete) => { +const createTableColumns = (schema, path, hendleDelete) => { let columns = []; for (const key of Object.keys(schema.values)) { @@ -13,7 +13,7 @@ const createTableColumns = (schema, hendleDelete) => { dataIndex: 'id', key: 'id', render: (text, record) => ( - + {text} ) diff --git a/src/client/modules/user/index.web.jsx b/src/client/modules/user/index.web.jsx index 088696acca..e98e749f01 100644 --- a/src/client/modules/user/index.web.jsx +++ b/src/client/modules/user/index.web.jsx @@ -43,7 +43,7 @@ export default new Feature({ route: [ , , - , + , , , , diff --git a/tools/templates/crud/client/components/ModuleEditView.jsx b/tools/templates/crud/client/components/ModuleEditView.jsx new file mode 100644 index 0000000000..427ca99db9 --- /dev/null +++ b/tools/templates/crud/client/components/ModuleEditView.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +const $Module$EditView = () => { + return ( + + + Hello $Module$ Edit! + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + alignItems: 'center', + justifyContent: 'center' + }, + element: { + paddingTop: 30 + }, + box: { + textAlign: 'center', + marginLeft: 15, + marginRight: 15 + } +}); + +export default $Module$EditView; diff --git a/tools/templates/crud/client/components/ModuleEditView.web.jsx b/tools/templates/crud/client/components/ModuleEditView.web.jsx new file mode 100644 index 0000000000..80d97d804d --- /dev/null +++ b/tools/templates/crud/client/components/ModuleEditView.web.jsx @@ -0,0 +1,75 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Helmet from 'react-helmet'; +import { Link } from 'react-router-dom'; +import { SubmissionError } from 'redux-form'; +import { PageLayout } from '../../common/components/web'; + +import $Module$Form from './$Module$Form'; +import settings from '../../../../../settings'; + +class $Module$EditView extends React.PureComponent { + onSubmit = async values => { + const { $module$, add$Module$, edit$Module$ } = this.props; + let result = null; + + if ($module$) { + result = await edit$Module$({ id: $module$.id, ...values }); + } else { + result = await add$Module$(values); + } + + if (result.errors) { + let submitError = { + _error: 'Edit $module$ failed!' + }; + result.errors.map(error => (submitError[error.field] = error.message)); + throw new SubmissionError(submitError); + } + }; + + renderMetaData = () => ( + + ); + + render() { + const { loading, $module$ } = this.props; + + if (loading && !$module$) { + return ( + + {this.renderMetaData()} +
Loading...
+
+ ); + } else { + return ( + + {this.renderMetaData()} + + Back + +

{$module$ ? 'Edit' : 'Create'} $Module$

+ <$Module$Form onSubmit={this.onSubmit} initialValues={$module$} /> +
+ ); + } + } +} + +$Module$EditView.propTypes = { + loading: PropTypes.bool.isRequired, + $module$: PropTypes.object, + add$Module$: PropTypes.func.isRequired, + edit$Module$: PropTypes.func.isRequired +}; + +export default $Module$EditView; diff --git a/tools/templates/crud/client/components/ModuleForm.web.jsx b/tools/templates/crud/client/components/ModuleForm.web.jsx new file mode 100644 index 0000000000..55ee18ad80 --- /dev/null +++ b/tools/templates/crud/client/components/ModuleForm.web.jsx @@ -0,0 +1,39 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Field, reduxForm } from 'redux-form'; +import { Form, RenderField, Button, Alert } from '../../common/components/web'; + +const required = value => (value ? undefined : 'Required'); + +const validate = values => { + const errors = {}; + + if (values.password !== values.passwordConfirmation) { + errors.passwordConfirmation = 'Passwords do not match'; + } + return errors; +}; + +const $Module$Form = ({ handleSubmit, submitting, onSubmit, error }) => { + return ( +
+ + {error && {error}} + + + ); +}; + +$Module$Form.propTypes = { + handleSubmit: PropTypes.func, + onSubmit: PropTypes.func, + submitting: PropTypes.bool, + error: PropTypes.string +}; + +export default reduxForm({ + form: '$module$', + validate +})($Module$Form); diff --git a/tools/templates/crud/client/components/ModuleListView.web.jsx b/tools/templates/crud/client/components/ModuleListView.web.jsx index 40c0a1042f..ab6952bb9d 100644 --- a/tools/templates/crud/client/components/ModuleListView.web.jsx +++ b/tools/templates/crud/client/components/ModuleListView.web.jsx @@ -1,8 +1,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; +import { Link } from 'react-router-dom'; -import { PageLayout, Table } from '../../common/components/web'; +import { PageLayout, Table, Button } from '../../common/components/web'; import createTableColumns from '../../common/util'; import { $Module$ as $Module$Schema } from '../../../../server/modules/$module$/schema'; @@ -30,9 +31,14 @@ class $Module$ListView extends React.PureComponent { return ( {this.renderMetaData()} +

$Module$s

+ + + +
diff --git a/tools/templates/crud/client/containers/ModuleEdit.jsx b/tools/templates/crud/client/containers/ModuleEdit.jsx new file mode 100644 index 0000000000..654af8ed50 --- /dev/null +++ b/tools/templates/crud/client/containers/ModuleEdit.jsx @@ -0,0 +1,82 @@ +import React from 'react'; +import { graphql, compose } from 'react-apollo'; + +import $Module$EditView from '../components/$Module$EditView'; + +import $MODULE$_QUERY from '../graphql/$Module$Query.graphql'; +import ADD_$MODULE$ from '../graphql/Add$Module$.graphql'; +import EDIT_$MODULE$ from '../graphql/Edit$Module$.graphql'; + +class $Module$Edit extends React.Component { + render() { + return <$Module$EditView {...this.props} />; + } +} + +export default compose( + graphql($MODULE$_QUERY, { + options: props => { + let id = 0; + if (props.match) { + id = props.match.params.id; + } else if (props.navigation) { + id = props.navigation.state.params.id; + } + + return { + variables: { id } + }; + }, + props({ data: { loading, $module$ } }) { + return { loading, $module$ }; + } + }), + graphql(ADD_$MODULE$, { + props: ({ ownProps: { history, navigation }, mutate }) => ({ + add$Module$: async input => { + try { + const { data: { add$Module$ } } = await mutate({ + variables: { input } + }); + + if (add$Module$.errors) { + return { errors: add$Module$.errors }; + } + + if (history) { + return history.push('/$module$'); + } + if (navigation) { + return navigation.goBack(); + } + } catch (e) { + console.log(e.graphQLErrors); + } + } + }) + }), + graphql(EDIT_$MODULE$, { + props: ({ ownProps: { history, navigation }, mutate }) => ({ + edit$Module$: async input => { + try { + const { data: { edit$Module$ } } = await mutate({ + variables: { input } + }); + + if (edit$Module$.errors) { + return { errors: edit$Module$.errors }; + } + + if (history) { + return history.push('/$module$'); + } + if (navigation) { + return navigation.goBack(); + } + } catch (e) { + console.log(e.graphQLErrors); + } + } + }) + }) +)($Module$Edit); diff --git a/tools/templates/crud/client/graphql/AddModule.graphql b/tools/templates/crud/client/graphql/AddModule.graphql new file mode 100644 index 0000000000..b5e66390cb --- /dev/null +++ b/tools/templates/crud/client/graphql/AddModule.graphql @@ -0,0 +1,13 @@ +#import "./$Module$.graphql" + +mutation add$Module$($input: $Module$Input!) { + add$Module$(input: $input) { + $module$ { + ...$Module$Info + } + errors { + field + message + } + } +} diff --git a/tools/templates/crud/client/graphql/EditModule.graphql b/tools/templates/crud/client/graphql/EditModule.graphql new file mode 100644 index 0000000000..aa7d88b404 --- /dev/null +++ b/tools/templates/crud/client/graphql/EditModule.graphql @@ -0,0 +1,13 @@ +#import "./$Module$.graphql" + +mutation edit$Module$($input: $Module$Input!) { + edit$Module$(input: $input) { + $module$ { + ...$Module$Info + } + errors { + field + message + } + } +} diff --git a/tools/templates/crud/client/graphql/ModuleQuery.graphql b/tools/templates/crud/client/graphql/ModuleQuery.graphql new file mode 100644 index 0000000000..895d734f24 --- /dev/null +++ b/tools/templates/crud/client/graphql/ModuleQuery.graphql @@ -0,0 +1,8 @@ +#import "./$Module$.graphql" + +query $module$ { + $module$ { + ...$Module$Info + } +} + diff --git a/tools/templates/crud/client/index.web.jsx b/tools/templates/crud/client/index.web.jsx index 560e9ea9b3..a68d4399e5 100644 --- a/tools/templates/crud/client/index.web.jsx +++ b/tools/templates/crud/client/index.web.jsx @@ -2,12 +2,16 @@ import React from 'react'; import { Route, NavLink } from 'react-router-dom'; import { MenuItem } from '../../modules/common/components/web'; import $Module$List from './containers/$Module$List'; +import $Module$Edit from './containers/$Module$Edit'; import reducers from './reducers'; import Feature from '../connector'; export default new Feature({ - route: , + route: [ + , + + ], navItem: ( diff --git a/tools/templates/crud/server/resolvers.js b/tools/templates/crud/server/resolvers.js index 9002051ec6..4b497ec778 100644 --- a/tools/templates/crud/server/resolvers.js +++ b/tools/templates/crud/server/resolvers.js @@ -8,6 +8,33 @@ export default pubsub => ({ } }, Mutation: { + add$Module$: async (obj, { input }, { $Module$ }) => { + try { + const e = new FieldError(); + e.throwIf(); + + const [id] = await $Module$.add$Module$(input); + const $module$ = await $Module$.get$Module$(id); + + return { $module$ }; + } catch (e) { + return { errors: e }; + } + }, + edit$Module$: async (obj, { input }, { $Module$ }) => { + try { + const e = new FieldError(); + e.throwIf(); + + await $Module$.edit$Module$(input); + + const $module$ = await $Module$.get$Module$(input.id); + + return { $module$ }; + } catch (e) { + return { errors: e }; + } + }, delete$Module$: async (obj, { id }, { $Module$ }) => { try { const e = new FieldError(); diff --git a/tools/templates/crud/server/schema.graphqls b/tools/templates/crud/server/schema.graphqls index 61fadd66cb..3588ff5007 100644 --- a/tools/templates/crud/server/schema.graphqls +++ b/tools/templates/crud/server/schema.graphqls @@ -3,12 +3,19 @@ type $Module$Payload { errors: [FieldError!] } +input $Module$Input { + id: String +} + extend type Query { $module$s: [$Module$] + $module$: $Module$ } extend type Mutation { + add$Module$(input: $Module$Input!): $Module$Payload! + edit$Module$(input: $Module$Input!): $Module$Payload! delete$Module$(id: Int!): $Module$Payload! } -extend type Subscription {} +extend type Subscription {} \ No newline at end of file diff --git a/tools/templates/crud/server/sql.js b/tools/templates/crud/server/sql.js index 4a461d3862..4e893b47c4 100644 --- a/tools/templates/crud/server/sql.js +++ b/tools/templates/crud/server/sql.js @@ -11,6 +11,18 @@ export default class $Module$ { return camelizeKeys(await knex.select('*').from('$module$').first()); } + add$Module$(input) { + return knex('$module$') + .insert(input) + .returning('id'); + } + + edit$Module$({ id, ...input}) { + return knex('$module$') + .update(input) + .where({ id }); + } + delete$Module$(id) { return knex('$module$') .where('id', '=', id) From fd591b967287918b91e276f66f5c6218667f76be Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Thu, 23 Nov 2017 06:43:40 +0100 Subject: [PATCH 016/327] fix getModule by id --- tools/templates/crud/client/graphql/ModuleQuery.graphql | 4 ++-- tools/templates/crud/server/resolvers.js | 3 +++ tools/templates/crud/server/schema.graphqls | 2 +- tools/templates/crud/server/sql.js | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/templates/crud/client/graphql/ModuleQuery.graphql b/tools/templates/crud/client/graphql/ModuleQuery.graphql index 895d734f24..2506aea2a8 100644 --- a/tools/templates/crud/client/graphql/ModuleQuery.graphql +++ b/tools/templates/crud/client/graphql/ModuleQuery.graphql @@ -1,7 +1,7 @@ #import "./$Module$.graphql" -query $module$ { - $module$ { +query $module$($id: Int!) { + $module$(id: $id) { ...$Module$Info } } diff --git a/tools/templates/crud/server/resolvers.js b/tools/templates/crud/server/resolvers.js index 4b497ec778..078e052331 100644 --- a/tools/templates/crud/server/resolvers.js +++ b/tools/templates/crud/server/resolvers.js @@ -5,6 +5,9 @@ export default pubsub => ({ Query: { $module$s: (obj, args, { $Module$ }) => { return $Module$.get$Module$s(); + }, + $module$: (obj, { id }, { $Module$ }) => { + return $Module$.get$Module$(id); } }, Mutation: { diff --git a/tools/templates/crud/server/schema.graphqls b/tools/templates/crud/server/schema.graphqls index 3588ff5007..32f38fa9f4 100644 --- a/tools/templates/crud/server/schema.graphqls +++ b/tools/templates/crud/server/schema.graphqls @@ -9,7 +9,7 @@ input $Module$Input { extend type Query { $module$s: [$Module$] - $module$: $Module$ + $module$(id: Int!): $Module$ } extend type Mutation { diff --git a/tools/templates/crud/server/sql.js b/tools/templates/crud/server/sql.js index 4e893b47c4..3dd3565165 100644 --- a/tools/templates/crud/server/sql.js +++ b/tools/templates/crud/server/sql.js @@ -7,8 +7,8 @@ export default class $Module$ { return camelizeKeys(await knex.select('*').from('$module$')); } - async get$Module$() { - return camelizeKeys(await knex.select('*').from('$module$').first()); + async get$Module$(id) { + return camelizeKeys(await knex.select('*').from('$module$').where({ id }).first()); } add$Module$(input) { From 94c3cadb837d193eac2c6278c9d433a15f49dc10 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Thu, 23 Nov 2017 07:02:18 +0100 Subject: [PATCH 017/327] hardcode first field for now --- .../crud/client/components/ModuleEditView.web.jsx | 7 +++++-- tools/templates/crud/client/components/ModuleForm.web.jsx | 2 +- tools/templates/crud/database/seeds/_Module.js | 2 +- tools/templates/crud/server/schema.graphqls | 3 ++- tools/templates/crud/server/schema.js | 3 +++ 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/templates/crud/client/components/ModuleEditView.web.jsx b/tools/templates/crud/client/components/ModuleEditView.web.jsx index 80d97d804d..d41369706c 100644 --- a/tools/templates/crud/client/components/ModuleEditView.web.jsx +++ b/tools/templates/crud/client/components/ModuleEditView.web.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; import { Link } from 'react-router-dom'; import { SubmissionError } from 'redux-form'; +import { pick } from 'lodash'; import { PageLayout } from '../../common/components/web'; import $Module$Form from './$Module$Form'; @@ -13,10 +14,12 @@ class $Module$EditView extends React.PureComponent { const { $module$, add$Module$, edit$Module$ } = this.props; let result = null; + let insertValues = pick(values, ['name']); + if ($module$) { - result = await edit$Module$({ id: $module$.id, ...values }); + result = await edit$Module$({ id: $module$.id, ...insertValues }); } else { - result = await add$Module$(values); + result = await add$Module$(insertValues); } if (result.errors) { diff --git a/tools/templates/crud/client/components/ModuleForm.web.jsx b/tools/templates/crud/client/components/ModuleForm.web.jsx index 55ee18ad80..d234639047 100644 --- a/tools/templates/crud/client/components/ModuleForm.web.jsx +++ b/tools/templates/crud/client/components/ModuleForm.web.jsx @@ -17,7 +17,7 @@ const validate = values => { const $Module$Form = ({ handleSubmit, submitting, onSubmit, error }) => { return (
- + {error && {error}} - ) - }); - - return columns; -}; +import { RenderField } from './components/web'; const required = value => (value ? undefined : 'Required'); diff --git a/tools/templates/crud/client/components/ModuleListView.web.jsx b/tools/templates/crud/client/components/ModuleListView.web.jsx index 31bd8549b5..d1f8c53cee 100644 --- a/tools/templates/crud/client/components/ModuleListView.web.jsx +++ b/tools/templates/crud/client/components/ModuleListView.web.jsx @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; import { Link } from 'react-router-dom'; +import { capitalize } from 'lodash'; import { PageLayout, Table, Button } from '../../common/components/web'; import { createTableColumns } from '../../common/util'; @@ -20,14 +21,86 @@ class $Module$ListView extends React.PureComponent { /> ); + renderOrderByArrow = name => { + const { orderBy } = this.props; + + if (orderBy && orderBy.column === name) { + if (orderBy.order === 'desc') { + return ; + } else { + return ; + } + } else { + return ; + } + }; + hendleDelete$Module$ = id => { const { delete$Module$ } = this.props; delete$Module$(id); }; + orderBy = (e, name) => { + const { onOrderBy, orderBy } = this.props; + + e.preventDefault(); + + let order = 'asc'; + if (orderBy && orderBy.column === name) { + if (orderBy.order === 'asc') { + order = 'desc'; + } else if (orderBy.order === 'desc') { + return onOrderBy({}); + } + } + + return onOrderBy({ column: name, order }); + }; + render() { const { loading, $module$s } = this.props; + let columns = []; + + for (const key of CrudSchema.keys()) { + if (key === 'id') { + columns.push({ + title: ( + this.orderBy(e, key)} href="#"> + {capitalize(key)} {this.renderOrderByArrow(key)} + + ), + dataIndex: 'id', + key: 'id', + render: (text, record) => ( + + {text} + + ) + }); + } else { + columns.push({ + title: ( + this.orderBy(e, key)} href="#"> + {capitalize(key)} {this.renderOrderByArrow(key)} + + ), + dataIndex: key, + key: key + }); + } + } + + columns.push({ + title: 'Actions', + key: 'actions', + render: (text, record) => ( + + ) + }); + return ( {this.renderMetaData()} @@ -38,7 +111,7 @@ class $Module$ListView extends React.PureComponent {
@@ -50,6 +123,8 @@ class $Module$ListView extends React.PureComponent { $Module$ListView.propTypes = { loading: PropTypes.bool.isRequired, $module$s: PropTypes.array, + orderBy: PropTypes.object, + onOrderBy: PropTypes.func.isRequired, delete$Module$: PropTypes.func.isRequired }; diff --git a/tools/templates/crud/client/containers/ModuleList.jsx b/tools/templates/crud/client/containers/ModuleList.jsx index 0bf57d2e17..60b988c7d4 100644 --- a/tools/templates/crud/client/containers/ModuleList.jsx +++ b/tools/templates/crud/client/containers/ModuleList.jsx @@ -1,5 +1,6 @@ import React from 'react'; import { graphql, compose } from 'react-apollo'; +import { connect } from 'react-redux'; import $Module$ListView from '../components/$Module$ListView'; import $MODULE$S_QUERY from '../graphql/$Module$sQuery.graphql'; @@ -13,9 +14,13 @@ class $Module$ extends React.Component { const $Module$WithApollo = compose( graphql($MODULE$S_QUERY, { - options: () => { + options: ({ orderBy, searchText }) => { return { - fetchPolicy: 'cache-and-network' + fetchPolicy: 'cache-and-network', + variables: { + orderBy: orderBy, + filter: { searchText } + } }; }, props({ data: { loading, $module$s, refetch, error } }) { @@ -43,4 +48,17 @@ const $Module$WithApollo = compose( }) )($Module$); -export default $Module$WithApollo; +export default connect( + state => ({ + searchText: state.$module$.searchText, + orderBy: state.$module$.orderBy + }), + dispatch => ({ + onOrderBy(orderBy) { + dispatch({ + type: '$MODULE$_ORDER_BY', + value: orderBy + }); + } + }) +)($Module$WithApollo); diff --git a/tools/templates/crud/client/graphql/ModulesQuery.graphql b/tools/templates/crud/client/graphql/ModulesQuery.graphql index b818cb8fbc..90e1c1c3fd 100644 --- a/tools/templates/crud/client/graphql/ModulesQuery.graphql +++ b/tools/templates/crud/client/graphql/ModulesQuery.graphql @@ -1,7 +1,7 @@ #import "./$Module$.graphql" -query $module$s { - $module$s { +query $module$s($orderBy: OrderBy$Module$Input, $filter: Filter$Module$Input) { + $module$s(orderBy: $orderBy, filter: $filter) { ...$Module$Info } } diff --git a/tools/templates/crud/client/reducers/index.js b/tools/templates/crud/client/reducers/index.js index 6c6ee75a42..0015f6e39a 100644 --- a/tools/templates/crud/client/reducers/index.js +++ b/tools/templates/crud/client/reducers/index.js @@ -1,7 +1,22 @@ -const defaultState = {}; +const defaultState = { + searchText: '', + orderBy: {} +}; export default function(state = defaultState, action) { switch (action.type) { + case '$MODULE$_FILTER_SEARCH_TEXT': + return { + ...state, + searchText: action.value + }; + + case '$MODULE$_ORDER_BY': + return { + ...state, + orderBy: action.value + }; + default: return state; } diff --git a/tools/templates/crud/server/resolvers.js b/tools/templates/crud/server/resolvers.js index 078e052331..3a75b11d7c 100644 --- a/tools/templates/crud/server/resolvers.js +++ b/tools/templates/crud/server/resolvers.js @@ -4,10 +4,10 @@ import FieldError from '../../../common/FieldError'; export default pubsub => ({ Query: { $module$s: (obj, args, { $Module$ }) => { - return $Module$.get$Module$s(); + return $Module$.get$Module$s(args); }, - $module$: (obj, { id }, { $Module$ }) => { - return $Module$.get$Module$(id); + $module$: (obj, args, { $Module$ }) => { + return $Module$.get$Module$(args); } }, Mutation: { diff --git a/tools/templates/crud/server/schema.graphqls b/tools/templates/crud/server/schema.graphqls index 8db675f72f..6b7c8a540c 100644 --- a/tools/templates/crud/server/schema.graphqls +++ b/tools/templates/crud/server/schema.graphqls @@ -3,6 +3,15 @@ type $Module$Payload { errors: [FieldError!] } +input OrderBy$Module$Input { + column: String + order: String +} + +input Filter$Module$Input { + searchText: String +} + input Add$Module$Input { name: String! } @@ -13,7 +22,7 @@ input Edit$Module$Input { } extend type Query { - $module$s: [$Module$] + $module$s(orderBy: OrderBy$Module$Input, filter: Filter$Module$Input): [$Module$] $module$(id: Int!): $Module$ } diff --git a/tools/templates/crud/server/sql.js b/tools/templates/crud/server/sql.js index 3dd3565165..96631d4a4a 100644 --- a/tools/templates/crud/server/sql.js +++ b/tools/templates/crud/server/sql.js @@ -1,13 +1,34 @@ -import { camelizeKeys } from 'humps'; +import { camelizeKeys, decamelize } from 'humps'; +import { has } from 'lodash'; import knex from '../../../server/sql/connector'; export default class $Module$ { - async get$Module$s() { - return camelizeKeys(await knex.select('*').from('$module$')); + async get$Module$s({ orderBy, filter }) { + const queryBuilder = knex.select('*').from('$module$'); + + if (orderBy && orderBy.column) { + let column = orderBy.column; + let order = 'asc'; + if (orderBy.order) { + order = orderBy.order; + } + + queryBuilder.orderBy(decamelize(column), order); + } + + if (filter) { + if (has(filter, 'searchText') && filter.searchText !== '') { + queryBuilder.where(function() { + this.where('name', 'like', `%${filter.searchText}%`); + }); + } + } + + return camelizeKeys(await queryBuilder); } - async get$Module$(id) { + async get$Module$({ id }) { return camelizeKeys(await knex.select('*').from('$module$').where({ id }).first()); } From 2c82992f782ea65df2efbf80e4d73f0eaf1f279f Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Fri, 24 Nov 2017 09:37:34 +0100 Subject: [PATCH 027/327] fix delete handle --- tools/templates/crud/client/components/ModuleListView.web.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/templates/crud/client/components/ModuleListView.web.jsx b/tools/templates/crud/client/components/ModuleListView.web.jsx index d1f8c53cee..b1a09bab49 100644 --- a/tools/templates/crud/client/components/ModuleListView.web.jsx +++ b/tools/templates/crud/client/components/ModuleListView.web.jsx @@ -35,7 +35,7 @@ class $Module$ListView extends React.PureComponent { } }; - hendleDelete$Module$ = id => { + hendleDelete = id => { const { delete$Module$ } = this.props; delete$Module$(id); }; @@ -95,7 +95,7 @@ class $Module$ListView extends React.PureComponent { title: 'Actions', key: 'actions', render: (text, record) => ( - ) From 9ec8f69391a3dcb0b53c66929929f5938ed4d789 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Fri, 24 Nov 2017 10:15:52 +0100 Subject: [PATCH 028/327] working filter --- .../modules/user/containers/UsersFilter.jsx | 4 -- .../crud/client/components/Module.jsx | 31 +++++++++++++++ .../crud/client/components/Module.web.jsx | 38 +++++++++++++++++++ .../components/ModuleFilterView.web.jsx | 34 +++++++++++++++++ .../client/components/ModuleListView.web.jsx | 20 +++------- .../crud/client/containers/ModuleFilter.jsx | 24 ++++++++++++ tools/templates/crud/client/index.web.jsx | 4 +- 7 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 tools/templates/crud/client/components/Module.jsx create mode 100644 tools/templates/crud/client/components/Module.web.jsx create mode 100644 tools/templates/crud/client/components/ModuleFilterView.web.jsx create mode 100644 tools/templates/crud/client/containers/ModuleFilter.jsx diff --git a/src/client/modules/user/containers/UsersFilter.jsx b/src/client/modules/user/containers/UsersFilter.jsx index 4ab72b1fdb..f7441a1e82 100644 --- a/src/client/modules/user/containers/UsersFilter.jsx +++ b/src/client/modules/user/containers/UsersFilter.jsx @@ -1,9 +1,5 @@ -/*eslint-disable no-unused-vars*/ -// React import React from 'react'; import { connect } from 'react-redux'; - -// Components import UsersFilterView from '../components/UsersFilterView'; class UsersFilter extends React.Component { diff --git a/tools/templates/crud/client/components/Module.jsx b/tools/templates/crud/client/components/Module.jsx new file mode 100644 index 0000000000..ebef044528 --- /dev/null +++ b/tools/templates/crud/client/components/Module.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +const $Module$ = () => { + return ( + + + Hello $Module$! + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + alignItems: 'center', + justifyContent: 'center' + }, + element: { + paddingTop: 30 + }, + box: { + textAlign: 'center', + marginLeft: 15, + marginRight: 15 + } +}); + +export default $Module$; diff --git a/tools/templates/crud/client/components/Module.web.jsx b/tools/templates/crud/client/components/Module.web.jsx new file mode 100644 index 0000000000..1c36c646ae --- /dev/null +++ b/tools/templates/crud/client/components/Module.web.jsx @@ -0,0 +1,38 @@ +import React from 'react'; +import Helmet from 'react-helmet'; +import { Link } from 'react-router-dom'; +import { PageLayout, Button } from '../../common/components/web'; + +import $Module$Filter from '../containers/$Module$Filter'; +import $Module$List from '../containers/$Module$List'; +import settings from '../../../../../settings'; + +const $Module$ = () => { + const renderMetaData = () => ( + + ); + + return ( + + {renderMetaData()} +

$Module$

+ + + +
+ <$Module$Filter /> +
+ <$Module$List /> +
+ ); +}; + +export default $Module$; diff --git a/tools/templates/crud/client/components/ModuleFilterView.web.jsx b/tools/templates/crud/client/components/ModuleFilterView.web.jsx new file mode 100644 index 0000000000..1315fb63d4 --- /dev/null +++ b/tools/templates/crud/client/components/ModuleFilterView.web.jsx @@ -0,0 +1,34 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { DebounceInput } from 'react-debounce-input'; +import { Form, FormItem, Input } from '../../common/components/web'; + +class $Module$FilterView extends React.PureComponent { + handleSearch = e => { + const { onSearchTextChange } = this.props; + onSearchTextChange(e.target.value); + }; + + render() { + return ( + + + + + + ); + } +} + +$Module$FilterView.propTypes = { + searchText: PropTypes.string, + onSearchTextChange: PropTypes.func.isRequired +}; + +export default $Module$FilterView; diff --git a/tools/templates/crud/client/components/ModuleListView.web.jsx b/tools/templates/crud/client/components/ModuleListView.web.jsx index b1a09bab49..aa50628aec 100644 --- a/tools/templates/crud/client/components/ModuleListView.web.jsx +++ b/tools/templates/crud/client/components/ModuleListView.web.jsx @@ -102,20 +102,12 @@ class $Module$ListView extends React.PureComponent { }); return ( - - {this.renderMetaData()} -

$Module$s

- - - -
-
- +
); } } diff --git a/tools/templates/crud/client/containers/ModuleFilter.jsx b/tools/templates/crud/client/containers/ModuleFilter.jsx new file mode 100644 index 0000000000..9c9175bba5 --- /dev/null +++ b/tools/templates/crud/client/containers/ModuleFilter.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { connect } from 'react-redux'; + +import $Module$FilterView from '../components/$Module$FilterView'; + +class $Module$Filter extends React.PureComponent { + render() { + return <$Module$FilterView {...this.props} />; + } +} + +export default connect( + state => ({ + searchText: state.$module$.searchText + }), + dispatch => ({ + onSearchTextChange(searchText) { + dispatch({ + type: '$MODULE$_FILTER_SEARCH_TEXT', + value: searchText + }); + } + }) +)($Module$Filter); diff --git a/tools/templates/crud/client/index.web.jsx b/tools/templates/crud/client/index.web.jsx index a68d4399e5..b0cea12b0a 100644 --- a/tools/templates/crud/client/index.web.jsx +++ b/tools/templates/crud/client/index.web.jsx @@ -1,7 +1,7 @@ import React from 'react'; import { Route, NavLink } from 'react-router-dom'; import { MenuItem } from '../../modules/common/components/web'; -import $Module$List from './containers/$Module$List'; +import $Module$ from './components/$Module$'; import $Module$Edit from './containers/$Module$Edit'; import reducers from './reducers'; @@ -9,7 +9,7 @@ import Feature from '../connector'; export default new Feature({ route: [ - , + , ], navItem: ( From 6d1b5528aab106aae91f46ed4941a74aeacb5df9 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Fri, 24 Nov 2017 10:34:06 +0100 Subject: [PATCH 029/327] add searchText property to the domain schema --- src/client/modules/common/util.js | 1 - .../crud/client/components/ModuleListView.web.jsx | 1 + tools/templates/crud/server/schema.js | 3 ++- tools/templates/crud/server/sql.js | 8 +++++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/client/modules/common/util.js b/src/client/modules/common/util.js index 4987175d07..610e79059f 100644 --- a/src/client/modules/common/util.js +++ b/src/client/modules/common/util.js @@ -1,4 +1,3 @@ -/* eslint-disable react/display-name */ import React from 'react'; import { pick, capitalize } from 'lodash'; import { Field } from 'redux-form'; diff --git a/tools/templates/crud/client/components/ModuleListView.web.jsx b/tools/templates/crud/client/components/ModuleListView.web.jsx index aa50628aec..67b50e002e 100644 --- a/tools/templates/crud/client/components/ModuleListView.web.jsx +++ b/tools/templates/crud/client/components/ModuleListView.web.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/display-name */ import React from 'react'; import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; diff --git a/tools/templates/crud/server/schema.js b/tools/templates/crud/server/schema.js index 34bcc3bd6d..77c98ef03f 100644 --- a/tools/templates/crud/server/schema.js +++ b/tools/templates/crud/server/schema.js @@ -6,7 +6,8 @@ export const $Module$ = new DomainSchema( class $Module$ extends Schema { id = DomainSchema.Integer; name = { - type: String + type: String, + searchText: true }; } ); diff --git a/tools/templates/crud/server/sql.js b/tools/templates/crud/server/sql.js index 96631d4a4a..abd9d644d8 100644 --- a/tools/templates/crud/server/sql.js +++ b/tools/templates/crud/server/sql.js @@ -1,6 +1,7 @@ import { camelizeKeys, decamelize } from 'humps'; import { has } from 'lodash'; +import { $Module$ as $Module$Schema } from './schema'; import knex from '../../../server/sql/connector'; export default class $Module$ { @@ -20,7 +21,12 @@ export default class $Module$ { if (filter) { if (has(filter, 'searchText') && filter.searchText !== '') { queryBuilder.where(function() { - this.where('name', 'like', `%${filter.searchText}%`); + for (const key of CrudSchema.keys()) { + const value = CrudSchema.values[key]; + if (value.searchText) { + this.orWhere(key, 'like', `%${filter.searchText}%`); + } + } }); } } From f10b2855ff175fbd1d2f95c5d4199adf4fe442e1 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Fri, 24 Nov 2017 10:46:23 +0100 Subject: [PATCH 030/327] fix getModule args --- tools/templates/crud/server/resolvers.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/templates/crud/server/resolvers.js b/tools/templates/crud/server/resolvers.js index 3a75b11d7c..895b05bc2b 100644 --- a/tools/templates/crud/server/resolvers.js +++ b/tools/templates/crud/server/resolvers.js @@ -17,7 +17,7 @@ export default pubsub => ({ e.throwIf(); const [id] = await $Module$.add$Module$(input); - const $module$ = await $Module$.get$Module$(id); + const $module$ = await $Module$.get$Module$({ id }); return { $module$ }; } catch (e) { @@ -31,7 +31,7 @@ export default pubsub => ({ await $Module$.edit$Module$(input); - const $module$ = await $Module$.get$Module$(input.id); + const $module$ = await $Module$.get$Module$({ id: input.id}); return { $module$ }; } catch (e) { @@ -41,7 +41,7 @@ export default pubsub => ({ delete$Module$: async (obj, { id }, { $Module$ }) => { try { const e = new FieldError(); - const $module$ = await $Module$.get$Module$(id); + const $module$ = await $Module$.get$Module$({ id }); if (!$module$) { e.setError('delete', '$Module$ does not exist.'); e.throwIf(); From d7f3aa358d6a9a015596fd96d659d48e5b88fb0f Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Tue, 28 Nov 2017 11:41:19 +0100 Subject: [PATCH 031/327] refactor post list to use FlatList --- .../modules/post/components/PostList.jsx | 85 +++++++------------ 1 file changed, 30 insertions(+), 55 deletions(-) diff --git a/src/client/modules/post/components/PostList.jsx b/src/client/modules/post/components/PostList.jsx index c6a70d8476..479c168d64 100644 --- a/src/client/modules/post/components/PostList.jsx +++ b/src/client/modules/post/components/PostList.jsx @@ -1,71 +1,46 @@ /*eslint-disable react/display-name*/ import React from 'react'; import PropTypes from 'prop-types'; -import { StyleSheet, Text, View, ListView, ScrollView, Button } from 'react-native'; +import { StyleSheet, FlatList, Text, View, Button } from 'react-native'; -// Row comparison function -const rowHasChanged = (r1, r2) => r1.id !== r2.id; +class PostList extends React.PureComponent { + keyExtractor = item => item.node.id; -// DataSource template object -const ds = new ListView.DataSource({ rowHasChanged }); - -const renderRow = (deletePost, navigation) => rowData => { - return ( - - + } + /> + ); +}; + +SwipeAction.propTypes = { + children: PropTypes.node, + right: PropTypes.object, + onPress: PropTypes.func +}; + +export default SwipeAction; diff --git a/src/client/modules/common/components/native/ui-native-base/components/index.jsx b/src/client/modules/common/components/native/ui-native-base/components/index.jsx new file mode 100644 index 0000000000..b139dd561f --- /dev/null +++ b/src/client/modules/common/components/native/ui-native-base/components/index.jsx @@ -0,0 +1,5 @@ +// eslint-disable-next-line import/prefer-default-export +export { default as Button } from './Button'; +export { default as Input } from './Input'; +export { default as SwipeAction } from './SwipeAction'; +export { default as ListItem } from './ListItem'; diff --git a/src/client/modules/post/components/PostList.jsx b/src/client/modules/post/components/PostList.jsx index 6f3730de78..c81f574f21 100644 --- a/src/client/modules/post/components/PostList.jsx +++ b/src/client/modules/post/components/PostList.jsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, FlatList, Text, View } from 'react-native'; -import { SwipeAction, ListItem } from '../../common/components/native'; +import { SwipeAction } from '../../common/components/native'; class PostList extends React.PureComponent { onEndReachedCalledDuringMomentum = false; @@ -13,19 +13,13 @@ class PostList extends React.PureComponent { const { deletePost, navigation } = this.props; return ( deletePost(id), - style: { backgroundColor: '#F4333C', color: 'white' } - } - ]} + onPress={() => navigation.navigate('PostEdit', { id })} + right={{ + text: 'Delete', + onPress: () => deletePost(id) + }} > - navigation.navigate('PostEdit', { id })}> - {title} - + {title} ); }; diff --git a/tools/webpackAppConfig.js b/tools/webpackAppConfig.js index 97eb4a0c3c..41b42fd691 100644 --- a/tools/webpackAppConfig.js +++ b/tools/webpackAppConfig.js @@ -40,6 +40,7 @@ const ios = { const dependencyPlatforms = { antd: 'web', + 'antd-mobile': ['ios', 'android'], 'apollo-engine': 'server', bcryptjs: 'server', 'body-parser': 'server', @@ -62,6 +63,7 @@ const dependencyPlatforms = { 'jwt-decode': 'web', knex: 'server', mysql2: 'server', + 'native-base': ['ios', 'android'], nodemailer: 'server', opencollective: 'server', passport: 'server', From 0e3595c832ed45e3ef89d0082ba88e8da915af71 Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 29 Nov 2017 11:36:27 +0100 Subject: [PATCH 036/327] Form components --- .../common/components/native/RenderField.jsx | 59 ++++++------------- .../modules/common/components/native/index.js | 4 +- .../ui-antd-mobile/components/FormButton.jsx | 21 +++++++ .../ui-antd-mobile/components/FormView.jsx | 24 ++++++++ .../ui-antd-mobile/components/Input.jsx | 17 ------ .../ui-antd-mobile/components/InputItem.jsx | 13 ++++ .../ui-antd-mobile/components/index.jsx | 4 +- .../ui-native-base/components/Button.jsx | 2 +- .../ui-native-base/components/FormButton.jsx | 31 ++++++++++ .../ui-native-base/components/FormView.jsx | 24 ++++++++ .../ui-native-base/components/Input.jsx | 17 ------ .../ui-native-base/components/InputItem.jsx | 27 +++++++++ .../ui-native-base/components/index.jsx | 4 +- .../modules/post/components/PostEditView.jsx | 11 +--- .../modules/post/components/PostForm.jsx | 18 ++---- 15 files changed, 172 insertions(+), 104 deletions(-) create mode 100644 src/client/modules/common/components/native/ui-antd-mobile/components/FormButton.jsx create mode 100644 src/client/modules/common/components/native/ui-antd-mobile/components/FormView.jsx delete mode 100644 src/client/modules/common/components/native/ui-antd-mobile/components/Input.jsx create mode 100644 src/client/modules/common/components/native/ui-antd-mobile/components/InputItem.jsx create mode 100644 src/client/modules/common/components/native/ui-native-base/components/FormButton.jsx create mode 100644 src/client/modules/common/components/native/ui-native-base/components/FormView.jsx delete mode 100644 src/client/modules/common/components/native/ui-native-base/components/Input.jsx create mode 100644 src/client/modules/common/components/native/ui-native-base/components/InputItem.jsx diff --git a/src/client/modules/common/components/native/RenderField.jsx b/src/client/modules/common/components/native/RenderField.jsx index 1504ff3b10..d0cf80551c 100644 --- a/src/client/modules/common/components/native/RenderField.jsx +++ b/src/client/modules/common/components/native/RenderField.jsx @@ -1,53 +1,28 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { StyleSheet, View, Text, TextInput } from 'react-native'; +import { InputItem } from './'; -const RenderField = ({ input, label, meta: { touched, error }, ...inputProps }) => { - const { container, inputText, text, errorField } = styles; +const RenderField = ({ input, label, meta: { active, error }, ...inputProps }) => { + let hasError = false; + if (active && error) { + hasError = true; + } return ( - - {label} - - + + {label} + ); }; -const styles = StyleSheet.create({ - inputText: { - backgroundColor: '#FFF', - color: '#000', - borderRadius: 5, - paddingLeft: 5, - paddingRight: 5, - lineHeight: 20, - flex: 3, - marginBottom: 5 - }, - text: { - alignSelf: 'center', - fontSize: 16, - paddingTop: 10, - paddingBottom: 10, - flex: 1 - }, - errorField: { - borderColor: 'red', - borderWidth: StyleSheet.hairlineWidth - }, - container: { - height: 40, - flex: 1, - flexDirection: 'row', - alignItems: 'center' - } -}); - RenderField.propTypes = { input: PropTypes.object, label: PropTypes.string, diff --git a/src/client/modules/common/components/native/index.js b/src/client/modules/common/components/native/index.js index cbb4aad651..3fd83eade2 100644 --- a/src/client/modules/common/components/native/index.js +++ b/src/client/modules/common/components/native/index.js @@ -1,5 +1,5 @@ // eslint-disable-next-line import/prefer-default-export -export * from './ui-antd-mobile/components'; -//export * from './ui-native-base/components'; +export * from './ui-native-base/components'; +//export * from './ui-antd-mobile/components'; export { default as RenderField } from './RenderField'; export { default as createTabBarIconWrapper } from './createTabBarIconWrapper'; diff --git a/src/client/modules/common/components/native/ui-antd-mobile/components/FormButton.jsx b/src/client/modules/common/components/native/ui-antd-mobile/components/FormButton.jsx new file mode 100644 index 0000000000..4f533e68a2 --- /dev/null +++ b/src/client/modules/common/components/native/ui-antd-mobile/components/FormButton.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import List from 'antd-mobile/lib/list'; +import Button from 'antd-mobile/lib/button'; + +const FormButton = ({ children, onPress, ...props }) => { + return ( + + + + ); +}; + +FormButton.propTypes = { + children: PropTypes.node, + onPress: PropTypes.func +}; + +export default FormButton; diff --git a/src/client/modules/common/components/native/ui-antd-mobile/components/FormView.jsx b/src/client/modules/common/components/native/ui-antd-mobile/components/FormView.jsx new file mode 100644 index 0000000000..96e6e31381 --- /dev/null +++ b/src/client/modules/common/components/native/ui-antd-mobile/components/FormView.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { StyleSheet, ScrollView } from 'react-native'; +import List from 'antd-mobile/lib/list'; + +const FormView = ({ children }) => { + return ( + + {children} + + ); +}; + +FormView.propTypes = { + children: PropTypes.node +}; + +const styles = StyleSheet.create({ + scroll: { + marginBottom: 5 + } +}); + +export default FormView; diff --git a/src/client/modules/common/components/native/ui-antd-mobile/components/Input.jsx b/src/client/modules/common/components/native/ui-antd-mobile/components/Input.jsx deleted file mode 100644 index a5519f10c5..0000000000 --- a/src/client/modules/common/components/native/ui-antd-mobile/components/Input.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import InputItem from 'antd-mobile/lib/input-item'; - -const Input = ({ children, ...props }) => { - return ( - - {children} - - ); -}; - -Input.propTypes = { - children: PropTypes.node -}; - -export default Input; diff --git a/src/client/modules/common/components/native/ui-antd-mobile/components/InputItem.jsx b/src/client/modules/common/components/native/ui-antd-mobile/components/InputItem.jsx new file mode 100644 index 0000000000..cab60729a8 --- /dev/null +++ b/src/client/modules/common/components/native/ui-antd-mobile/components/InputItem.jsx @@ -0,0 +1,13 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ADInputItem from 'antd-mobile/lib/input-item'; + +const InputItem = ({ children, ...props }) => { + return {children}; +}; + +InputItem.propTypes = { + children: PropTypes.node +}; + +export default InputItem; diff --git a/src/client/modules/common/components/native/ui-antd-mobile/components/index.jsx b/src/client/modules/common/components/native/ui-antd-mobile/components/index.jsx index b139dd561f..75ba84e5ff 100644 --- a/src/client/modules/common/components/native/ui-antd-mobile/components/index.jsx +++ b/src/client/modules/common/components/native/ui-antd-mobile/components/index.jsx @@ -1,5 +1,7 @@ // eslint-disable-next-line import/prefer-default-export export { default as Button } from './Button'; -export { default as Input } from './Input'; +export { default as FormView } from './FormView'; +export { default as FormButton } from './FormButton'; +export { default as InputItem } from './InputItem'; export { default as SwipeAction } from './SwipeAction'; export { default as ListItem } from './ListItem'; diff --git a/src/client/modules/common/components/native/ui-native-base/components/Button.jsx b/src/client/modules/common/components/native/ui-native-base/components/Button.jsx index 8fb3eb3774..aabf1c28bd 100644 --- a/src/client/modules/common/components/native/ui-native-base/components/Button.jsx +++ b/src/client/modules/common/components/native/ui-native-base/components/Button.jsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Text } from 'react-native'; -import { Button as NBButton } from 'native-base'; +import { NBButton } from 'native-base'; const Button = ({ children, ...props }) => { return ( diff --git a/src/client/modules/common/components/native/ui-native-base/components/FormButton.jsx b/src/client/modules/common/components/native/ui-native-base/components/FormButton.jsx new file mode 100644 index 0000000000..69d78ac9b1 --- /dev/null +++ b/src/client/modules/common/components/native/ui-native-base/components/FormButton.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { StyleSheet, Text } from 'react-native'; +import { Button } from 'native-base'; + +const FormButton = ({ children, ...props }) => { + return ( + + ); +}; + +FormButton.propTypes = { + children: PropTypes.node +}; + +const styles = StyleSheet.create({ + button: { + marginTop: 10, + marginLeft: 15, + marginRight: 15 + }, + textStyle: { + color: '#FFF', + fontSize: 16, + fontWeight: '500' + } +}); + +export default FormButton; diff --git a/src/client/modules/common/components/native/ui-native-base/components/FormView.jsx b/src/client/modules/common/components/native/ui-native-base/components/FormView.jsx new file mode 100644 index 0000000000..bf1eff6d3e --- /dev/null +++ b/src/client/modules/common/components/native/ui-native-base/components/FormView.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { StyleSheet, ScrollView } from 'react-native'; + +const FormView = ({ children }) => { + return ( + + {children} + + ); +}; + +FormView.propTypes = { + children: PropTypes.node +}; + +const styles = StyleSheet.create({ + scroll: { + paddingBottom: 10, + backgroundColor: '#fff' + } +}); + +export default FormView; diff --git a/src/client/modules/common/components/native/ui-native-base/components/Input.jsx b/src/client/modules/common/components/native/ui-native-base/components/Input.jsx deleted file mode 100644 index a5519f10c5..0000000000 --- a/src/client/modules/common/components/native/ui-native-base/components/Input.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import InputItem from 'antd-mobile/lib/input-item'; - -const Input = ({ children, ...props }) => { - return ( - - {children} - - ); -}; - -Input.propTypes = { - children: PropTypes.node -}; - -export default Input; diff --git a/src/client/modules/common/components/native/ui-native-base/components/InputItem.jsx b/src/client/modules/common/components/native/ui-native-base/components/InputItem.jsx new file mode 100644 index 0000000000..cfc7340893 --- /dev/null +++ b/src/client/modules/common/components/native/ui-native-base/components/InputItem.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { StyleSheet } from 'react-native'; +import { Item, Label, Input, Icon } from 'native-base'; + +const InputItem = ({ children, error, ...props }) => { + return ( + + + + {error && } + + ); +}; + +InputItem.propTypes = { + children: PropTypes.node, + error: PropTypes.bool +}; + +const styles = StyleSheet.create({ + item: { + paddingLeft: 10 + } +}); + +export default InputItem; diff --git a/src/client/modules/common/components/native/ui-native-base/components/index.jsx b/src/client/modules/common/components/native/ui-native-base/components/index.jsx index b139dd561f..75ba84e5ff 100644 --- a/src/client/modules/common/components/native/ui-native-base/components/index.jsx +++ b/src/client/modules/common/components/native/ui-native-base/components/index.jsx @@ -1,5 +1,7 @@ // eslint-disable-next-line import/prefer-default-export export { default as Button } from './Button'; -export { default as Input } from './Input'; +export { default as FormView } from './FormView'; +export { default as FormButton } from './FormButton'; +export { default as InputItem } from './InputItem'; export { default as SwipeAction } from './SwipeAction'; export { default as ListItem } from './ListItem'; diff --git a/src/client/modules/post/components/PostEditView.jsx b/src/client/modules/post/components/PostEditView.jsx index 20d2e4d5c9..682ddc6683 100644 --- a/src/client/modules/post/components/PostEditView.jsx +++ b/src/client/modules/post/components/PostEditView.jsx @@ -54,16 +54,7 @@ PostEditView.propTypes = { const styles = StyleSheet.create({ container: { - margin: 5, - flexDirection: 'column' - }, - element: { - paddingTop: 30 - }, - box: { - textAlign: 'center', - marginLeft: 15, - marginRight: 15 + //flex: 1 } }); diff --git a/src/client/modules/post/components/PostForm.jsx b/src/client/modules/post/components/PostForm.jsx index d32bed209c..e0db7e6eda 100644 --- a/src/client/modules/post/components/PostForm.jsx +++ b/src/client/modules/post/components/PostForm.jsx @@ -1,21 +1,19 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Field, reduxForm } from 'redux-form'; -import { StyleSheet, ScrollView } from 'react-native'; -import { Button } from '../../common/components'; -import { RenderField } from '../../common/components/native'; +import { FormView, RenderField, FormButton } from '../../common/components/native'; const required = value => (value ? undefined : 'Required'); const PostForm = ({ handleSubmit, valid, onSubmit }) => { return ( - + - - + + ); }; @@ -25,12 +23,6 @@ PostForm.propTypes = { valid: PropTypes.bool }; -const styles = StyleSheet.create({ - scroll: { - marginBottom: 5 - } -}); - export default reduxForm({ form: 'post', enableReinitialize: true From 1d36d03aac91a63b38b8cd368d5da5203f7fc88f Mon Sep 17 00:00:00 2001 From: Mitja Debeljak Date: Wed, 29 Nov 2017 11:59:50 +0100 Subject: [PATCH 037/327] finish styling post edit --- .../common/components/native/RenderField.jsx | 4 +- .../post/components/PostCommentForm.jsx | 18 +-- .../post/components/PostCommentsView.jsx | 138 +++++++----------- .../modules/post/components/PostList.jsx | 18 --- 4 files changed, 62 insertions(+), 116 deletions(-) diff --git a/src/client/modules/common/components/native/RenderField.jsx b/src/client/modules/common/components/native/RenderField.jsx index d0cf80551c..dfd5e567fb 100644 --- a/src/client/modules/common/components/native/RenderField.jsx +++ b/src/client/modules/common/components/native/RenderField.jsx @@ -2,9 +2,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import { InputItem } from './'; -const RenderField = ({ input, label, meta: { active, error }, ...inputProps }) => { +const RenderField = ({ input, label, meta: { touched, error }, ...inputProps }) => { let hasError = false; - if (active && error) { + if (touched && error) { hasError = true; } diff --git a/src/client/modules/post/components/PostCommentForm.jsx b/src/client/modules/post/components/PostCommentForm.jsx index 2d65ba9934..fa89e2655e 100644 --- a/src/client/modules/post/components/PostCommentForm.jsx +++ b/src/client/modules/post/components/PostCommentForm.jsx @@ -1,9 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Field, reduxForm } from 'redux-form'; -import { StyleSheet, ScrollView } from 'react-native'; -import { Button } from '../../common/components'; -import { RenderField } from '../../common/components/native'; +import { FormView, RenderField, FormButton } from '../../common/components/native'; const required = value => (value ? undefined : 'Required'); @@ -14,12 +12,12 @@ const PostCommentForm = ({ handleSubmit, valid, initialValues, onSubmit }) => { } return ( - + - - + + ); }; @@ -30,12 +28,6 @@ PostCommentForm.propTypes = { valid: PropTypes.bool }; -const styles = StyleSheet.create({ - scroll: { - marginBottom: 5 - } -}); - export default reduxForm({ form: 'comment', enableReinitialize: true diff --git a/src/client/modules/post/components/PostCommentsView.jsx b/src/client/modules/post/components/PostCommentsView.jsx index 80db02b607..ea89f4414d 100644 --- a/src/client/modules/post/components/PostCommentsView.jsx +++ b/src/client/modules/post/components/PostCommentsView.jsx @@ -1,78 +1,68 @@ -/*eslint-disable react/display-name*/ - import React from 'react'; import PropTypes from 'prop-types'; -import { StyleSheet, Text, View, ListView, ScrollView, Button, Keyboard } from 'react-native'; +import { StyleSheet, FlatList, Text, View, ScrollView, Keyboard } from 'react-native'; +import { SwipeAction } from '../../common/components/native'; import PostCommentForm from './PostCommentForm'; -function onCommentDelete(comment, deleteComment, onCommentSelect, id) { - if (comment.id === id) { - onCommentSelect({ id: null, content: '' }); - } +class PostCommentsView extends React.PureComponent { + keyExtractor = item => item.id; - deleteComment(id); -} + renderItem = ({ item: { id, content } }) => { + const { comment, deleteComment, onCommentSelect } = this.props; + return ( + onCommentSelect({ id: id, content: content })} + right={{ + text: 'Delete', + onPress: () => this.onCommentDelete(comment, deleteComment, onCommentSelect, id) + }} + > + {content} + + ); + }; -// Row comparison function -const rowHasChanged = (r1, r2) => r1.id !== r2.id; + onCommentDelete = (comment, deleteComment, onCommentSelect, id) => { + if (comment.id === id) { + onCommentSelect({ id: null, content: '' }); + } -// DataSource template object -const ds = new ListView.DataSource({ rowHasChanged }); + deleteComment(id); + }; -const renderRow = (onCommentSelect, comment, deleteComment) => rowData => { - return ( - -