diff --git a/client/.babelrc b/client/.babelrc deleted file mode 100644 index e0d613c0..00000000 --- a/client/.babelrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "presets": ["env", "stage-0", "react"], - "plugins": [ - "transform-runtime", - [ - "module-resolver", - { - "root": ["./src/app"], - "alias": { - "test": "./test" - } - } - ] - ], - "env": { - "production": { - "plugins": ["transform-react-remove-prop-types"] - } - } -} diff --git a/client/.dockerignore b/client/.dockerignore index 3c3629e6..0e75fe55 100644 --- a/client/.dockerignore +++ b/client/.dockerignore @@ -1 +1,3 @@ node_modules +dist +coverage diff --git a/client/.gitignore b/client/.gitignore index 5be1bca4..01290528 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -11,3 +11,4 @@ build deploy/keys selenium-debug.log +chromedriver.log diff --git a/client/README.md b/client/README.md index 38fb4bf5..80d69d91 100644 --- a/client/README.md +++ b/client/README.md @@ -1,10 +1,10 @@ # StarHackIt React Frontend -A functional Preact/React based frontend starter kit: +A functional React based frontend starter kit: -* `preact` or `react` for pure view layer, 100% stateless compoment. +* `react` for pure view layer, 100% stateless compoment. * `mobx` for state management. -* `glamorous` for real-time styling. +* `emotion` for real-time styling. * `universal-router` for the routing solution: code split, data fetching. * Internationalization with `i18next` * Find bugs, enforce coding standards with `eslint` and its plugins: `react`, `promise`, `mocha`. @@ -38,7 +38,6 @@ These are the main *npm* commands for a normal developer workflow: | `npm start` | Start a development web server | | `npm test` | Run the unit tests with Karma | | `npm run test:watch` | Watch the code and run the unit test | -| `npm run selenium-install` | Intall the Selenium driver for end to end testing | | `npm run e2e` | Run the end to end tests with Nigthwatch/Selenium | | `npm run build`| Create a production build | | `npm run start:prod`| start a web server to serve the production build | @@ -78,7 +77,6 @@ Unit tests are written as `mocha` test and executed thanks to `karma`: To execute the end to end testing, a.k.a _e2e testing_, first make sure the frontend and backend are running, then run: - $ npm run selenium-install $ npm run e2e The end to end tests are executed by [nightwatch](http://nightwatchjs.org/) which uses the *Selenium* driver API. @@ -120,42 +118,59 @@ To build the production version: *webpack* will produce a report with all the assets and their respective size. ``` -Hash: fcc48ad427c813ae63bd -Version: webpack 4.4.1 -Time: 4593ms -Built at: 2018-4-2 18:33:11 - Asset Size Chunks Chunk Names - 14.fcc48ad427c813ae63bd.js 283 KiB 14 [emitted] [big] - 0.fcc48ad427c813ae63bd.js 9.38 KiB 0 [emitted] - 2.css 608 bytes 2 [emitted] - 2.fcc48ad427c813ae63bd.js 24.9 KiB 2 [emitted] - 3.fcc48ad427c813ae63bd.js 68 KiB 3 [emitted] - 4.fcc48ad427c813ae63bd.js 88.6 KiB 4 [emitted] - 5.fcc48ad427c813ae63bd.js 2 KiB 5 [emitted] - 6.fcc48ad427c813ae63bd.js 4.87 KiB 6 [emitted] - 7.fcc48ad427c813ae63bd.js 4.47 KiB 7 [emitted] - 8.fcc48ad427c813ae63bd.js 4.69 KiB 8 [emitted] - 9.fcc48ad427c813ae63bd.js 23.5 KiB 9 [emitted] - 10.fcc48ad427c813ae63bd.js 81 bytes 10 [emitted] - 11.fcc48ad427c813ae63bd.js 2.95 KiB 11 [emitted] - 12.fcc48ad427c813ae63bd.js 8.11 KiB 12 [emitted] - 13.fcc48ad427c813ae63bd.js 6 KiB 13 [emitted] - 1.fcc48ad427c813ae63bd.js 39.4 KiB 1 [emitted] - 15.fcc48ad427c813ae63bd.js 662 bytes 15 [emitted] - app.css 39 bytes 16 [emitted] app - app.fcc48ad427c813ae63bd.js 313 KiB 16 [emitted] [big] app - index.html 3.05 KiB [emitted] - favicon.ico 1.12 KiB [emitted] - locales/en/common.json 410 bytes [emitted] - locales/fr/common.json 314 bytes [emitted] - locales/it/common.json 175 bytes [emitted] - 2.fcc48ad427c813ae63bd.js.gz 5.89 KiB [emitted] - 9.fcc48ad427c813ae63bd.js.gz 3.99 KiB [emitted] - 1.fcc48ad427c813ae63bd.js.gz 13.3 KiB [emitted] - 3.fcc48ad427c813ae63bd.js.gz 16.9 KiB [emitted] - 4.fcc48ad427c813ae63bd.js.gz 28.4 KiB [emitted] - 14.fcc48ad427c813ae63bd.js.gz 172 KiB [emitted] -app.fcc48ad427c813ae63bd.js.gz 92.2 KiB [emitted] +Version: webpack 4.28.4 +Time: 16929ms +Built at: 06/19/2019 6:26:27 PM + Asset Size Chunks Chunk Names + 10.39137f272569846297d4.js 23.5 KiB 10 [emitted] + 10.39137f272569846297d4.js.gz 3.99 KiB [emitted] + 11.39137f272569846297d4.js 428 bytes 11 [emitted] + 11.39137f272569846297d4.js.gz 280 bytes [emitted] + 12.39137f272569846297d4.js 1.71 KiB 12 [emitted] + 12.39137f272569846297d4.js.gz 771 bytes [emitted] + 13.39137f272569846297d4.js 81 bytes 13 [emitted] + 3.39137f272569846297d4.js 11.8 KiB 3 [emitted] + 3.39137f272569846297d4.js.gz 3.76 KiB [emitted] + 4.39137f272569846297d4.js 276 KiB 4 [emitted] [big] + 4.39137f272569846297d4.js.gz 168 KiB [emitted] + 5.39137f272569846297d4.js 4.99 KiB 5 [emitted] + 5.39137f272569846297d4.js.gz 2.38 KiB [emitted] + 6.39137f272569846297d4.js 5.47 KiB 6 [emitted] + 6.39137f272569846297d4.js.gz 2.54 KiB [emitted] + 7.39137f272569846297d4.js 1.73 KiB 7 [emitted] + 7.39137f272569846297d4.js.gz 767 bytes [emitted] + 8.39137f272569846297d4.js 39.5 KiB 8 [emitted] + 8.39137f272569846297d4.js.gz 13.3 KiB [emitted] + 9.39137f272569846297d4.js 3.77 KiB 9 [emitted] + 9.39137f272569846297d4.js.gz 1.1 KiB [emitted] + admin.39137f272569846297d4.js 372 KiB 0 [emitted] [big] admin + admin.39137f272569846297d4.js.gz 115 KiB [emitted] + admin.css 647 bytes 0 [emitted] admin + admin.css.gz 262 bytes [emitted] + admin/index.html 2.21 KiB [emitted] + admin/index.html.gz 870 bytes [emitted] + favicon.ico 1.12 KiB [emitted] + favicon.ico.gz 220 bytes [emitted] + index.html 2.32 KiB [emitted] + index.html.gz 937 bytes [emitted] + locales/en/common.json 410 bytes [emitted] + locales/en/common.json.gz 200 bytes [emitted] + locales/fr/common.json 314 bytes [emitted] + locales/fr/common.json.gz 207 bytes [emitted] + locales/it/common.json 175 bytes [emitted] + locales/it/common.json.gz 138 bytes [emitted] + public.39137f272569846297d4.js 334 KiB 1 [emitted] [big] public +public.39137f272569846297d4.js.gz 106 KiB [emitted] + public.css 39 bytes 1 [emitted] public + user.39137f272569846297d4.js 334 KiB 2 [emitted] [big] user + user.39137f272569846297d4.js.gz 106 KiB [emitted] + user.css 39 bytes 2 [emitted] user + user/index.html 2.31 KiB [emitted] + user/index.html.gz 935 bytes [emitted] +Entrypoint public [big] = public.css public.39137f272569846297d4.js +Entrypoint user [big] = user.css user.39137f272569846297d4.js +Entrypoint admin [big] = admin.css admin.39137f272569846297d4.js + ``` diff --git a/client/karma.conf.js b/client/karma.conf.js index d8b357df..605cf0b2 100644 --- a/client/karma.conf.js +++ b/client/karma.conf.js @@ -1,28 +1,51 @@ /*eslint-env node */ +process.env.CHROME_BIN = require("puppeteer").executablePath(); + const _ = require("lodash"); const path = require("path"); const webpackConfig = require("./webpack.dev"); -const webpackConfigProd = require("./webpack.prod"); webpackConfig.devtool = "cheap-module-source-map"; module.exports = function(config) { - const configuration = { - browsers: ["Chrome"], // ['Chrome'] run in Chrome, 'PhantomJS' + browsers: ["Chrome_without_security"], + customLaunchers: { + Chrome_without_security: { + base: "ChromeHeadless", + flags: [ + "--headless", + "--ignore-certificate-errors", + "--no-sandbox", + "--disable-setuid-sandbox", + "--window-size=1920,1080", + "--disable-accelerated-2d-canvas", + "--disable-dev-shm-usage", + "--disable-gpu" + ] + }, + Chrome_travis_ci: { + base: "Chrome", + flags: ["--no-sandbox"] + } + }, singleRun: true, // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ["mocha", "sinon"], - files: ["src/**/*.spec.js"], + files: ["src/**/*.spec.{js,jsx,ts,tsx}"], preprocessors: { "src/**/*.js": ["webpack", "sourcemap"] }, - reporters: ["mocha", "coverage"], + reporters: ["mocha", "coverage", "junit"], + junitReporter: { + outputDir: "coverage", + outputFile: "test-results.xml" + }, webpack: { mode: "development", module: { rules: [ { - test: /.(gif|png|woff(2)?|eot|ttf|svg)(\?[a-z0-9=\.]+)?$/, + test: /.(gif|png|woff(2)?|eot|ttf|svg)(\?[a-z0-9=.]+)?$/, use: ["url-loader"] }, { @@ -58,12 +81,6 @@ module.exports = function(config) { dir: "coverage/" } ] - }, - customLaunchers: { - Chrome_travis_ci: { - base: "Chrome", - flags: ["--no-sandbox"] - } } }; diff --git a/client/package.json b/client/package.json index a3c0c39a..896dd45c 100644 --- a/client/package.json +++ b/client/package.json @@ -1,7 +1,7 @@ { "name": "starhackit-ui", "title": "StarHack.It", - "version": "6.0.0", + "version": "7.0.0", "description": "React + node starter kit. A fullstack boilerplate written in ES6/7 with authentication and authorisation", "homepage": "https://github.com/FredericHeem/starhackit", "license": "NLPL", @@ -16,7 +16,6 @@ "clean": "rimraf dist coverage", "test": "karma start --single-run --no-auto-watch karma.conf.js", "test:watch": "karma start --auto-watch --no-single-run karma.conf.js", - "selenium-install": "webdriver-manager update", "e2e": "npm run nightwatch", "nightwatch": "cd test/nightwatch/ && nightwatch", "docker:build": "npm run build && docker build -t starhackit/ui .", @@ -33,29 +32,24 @@ }, "browserslist": "last 2 versions, ie 11", "dependencies": { - "@types/jest": "24.0.15", + "@emotion/core": "10.0.10", + "@emotion/styled": "10.0.12", "@types/react": "16.8.20", - "@types/styled-jsx": "2.2.8", "axios": "0.19.0", "debug": "4.1.1", - "glamor": "2.20.40", - "glamorous": "5.0.0", "history": "4.9.0", "i18next": "17.0.3", "i18next-browser-languagedetector": "3.0.1", - "i18next-localstorage-cache": "1.1.1", "i18next-xhr-backend": "3.0.0", "intl": "1.2.5", "lodash": "4.17.11", - "mdlean": "0.15.0", + "mdlean": "0.20.0", "mobx": "5.10.1", - "mobx-preact": "3.0.0", - "preact": "8.4.2", - "preact-compat": "3.19.0", - "preact-deep-force-update": "0.1.0", + "mobx-react": "6.1.1", "prop-types": "15.7.2", "qs": "6.7.0", - "react-color": "2.17.3", + "react": "16.8.6", + "react-dom": "16.8.6", "react-leanimate": "0.16.0", "react-pagify": "2.4.0", "reactabular-table": "8.14.0", @@ -64,20 +58,11 @@ "validate.js": "0.13.1" }, "devDependencies": { - "babel-core": "6.26.3", - "babel-plugin-module-resolver": "3.2.0", - "babel-plugin-transform-react-remove-prop-types": "0.4.24", - "babel-plugin-transform-runtime": "6.23.0", - "babel-polyfill": "6.26.0", - "babel-preset-env": "1.7.0", - "babel-preset-react": "6.24.1", - "babel-preset-stage-0": "6.24.1", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", "bluebird": "3.5.5", "chai": "4.2.0", "chai-as-promised": "7.1.1", "chance": "1.0.18", + "chromedriver": "75.0.0", "clean-webpack-plugin": "3.0.0", "compression-webpack-plugin": "3.0.0", "copy-webpack-plugin": "5.0.3", @@ -89,25 +74,23 @@ "istanbul-instrumenter-loader": "3.0.1", "jscpd": "2.0.15", "json-loader": "0.5.7", - "karma": "4.1.0", + "karma": "3.1.1", "karma-chai": "0.1.0", "karma-chrome-launcher": "2.2.0", "karma-coverage": "1.1.2", + "karma-junit-reporter": "1.2.0", "karma-mocha": "1.3.0", "karma-mocha-reporter": "2.2.5", - "karma-phantomjs-launcher": "1.0.4", "karma-sinon": "1.0.5", "karma-sourcemap-loader": "0.3.7", - "karma-webpack": "4.0.2", + "karma-webpack": "3.0.5", "lodash-webpack-plugin": "0.11.5", "mini-css-extract-plugin": "0.7.0", "mocha": "6.1.4", "nightwatch": "1.1.12", - "phantomjs-prebuilt": "2.1.16", - "protractor": "5.4.2", + "puppeteer": "1.11.0", "sinon": "7.3.2", "style-loader": "0.23.1", - "ts-jest": "24.0.2", "ts-loader": "6.0.3", "ts-node": "8.3.0", "tslint": "5.17.0", @@ -124,14 +107,7 @@ "webpack-hud": "0.1.2" }, "engines": { - "node": ">4.x", - "npm": ">3.x" - }, - "false": {}, - "alias": { - "react": "preact-compat", - "react-dom": "preact-compat", - "mobx-react": "mobx-preact", - "create-react-class": "preact-compat/lib/create-react-class" + "node": ">8.x", + "npm": ">5.x" } } diff --git a/client/src/app/app.css b/client/src/app.css similarity index 100% rename from client/src/app/app.css rename to client/src/app.css diff --git a/client/src/app.js b/client/src/app.js new file mode 100644 index 00000000..70f19182 --- /dev/null +++ b/client/src/app.js @@ -0,0 +1,26 @@ +import "./app.css"; +import Router from "./router"; +import Log from "utils/log"; +import config from "./config"; + +Log({ enable: config.debug.log }); + +const initialScreenFadeOut = () => { + const loading = document.getElementById("loading"); + if (loading) { + loading.classList.add("m-fadeOut"); + } +} + +export default async function({ context, routes, layout }) { + const router = Router({ context, routes, layout }); + + initialScreenFadeOut(); + + router.start(); + + return { + context, + router + } +} diff --git a/client/src/app/app.js b/client/src/app/app.js deleted file mode 100644 index 4a304869..00000000 --- a/client/src/app/app.js +++ /dev/null @@ -1,61 +0,0 @@ -import "./app.css"; -import Debug from "debug"; -import intl from "utils/intl"; -import Context from "./context"; - -import AuthModule from "./parts/auth/authModule"; -import CoreModule from "./parts/core/coreModule"; -import DbModule from "./parts/db/dbModule"; -import ThemeModule from "./parts/theme/themeModule"; -import HelloModule from "./parts/hello/HelloModule"; -import ProfileModule from "./parts/profile/profileModule"; - - -import Router from "./router"; - -const debug = new Debug("app"); - -export default function({ language = "en" }) { - debug("App begins"); - - const context = Context({ language }); - const { rest } = context; - - const parts = { - theme: ThemeModule(context), - auth: AuthModule(context), - core: CoreModule(context), - db: DbModule(context), - hello: HelloModule(context), - profile: ProfileModule(context) - }; - context.parts = parts; - - rest.setJwtSelector(parts.auth.stores().auth.getToken); - - async function i18nInit() { - context.formatter.setLocale(language); - await intl(language); - } - - async function preAuth() { - const token = localStorage.getItem("JWT"); - if (token) { - parts.auth.stores().auth.setToken(token); - } - await parts.auth.stores().me.fetch(); - } - - const router = Router(context); - - return { - context, - render() { - router.start(); - }, - async start() { - debug("start"); - return Promise.all([i18nInit(), preAuth()]); - } - }; -} diff --git a/client/src/app/components/FormGroup.js b/client/src/app/components/FormGroup.js deleted file mode 100644 index 0fdfb342..00000000 --- a/client/src/app/components/FormGroup.js +++ /dev/null @@ -1,6 +0,0 @@ -import glamorous from "glamorous"; - -export default () => glamorous("div")({ - marginTop: 20, - marginBottom: 20 - }); diff --git a/client/src/app/components/Page.js b/client/src/app/components/Page.js deleted file mode 100644 index bb2582a2..00000000 --- a/client/src/app/components/Page.js +++ /dev/null @@ -1,7 +0,0 @@ -import glamorous from "glamorous"; - -export default () => glamorous("section")({ - maxWidth: 600, - minWidth: 400, - width: "100%" - }); diff --git a/client/src/app/components/Paper.js b/client/src/app/components/Paper.js deleted file mode 100644 index 33384c4f..00000000 --- a/client/src/app/components/Paper.js +++ /dev/null @@ -1,13 +0,0 @@ -import glamorous from "glamorous"; - -export default context => { - const { theme } = context; - return glamorous("div")(() => ({ - boxShadow: `2px 2px 2px 2px ${theme.palette.borderColor}`, - padding: 20, - margin: 10, - "@media(max-width: 600px)": { - margin: 0 - } - })); -}; diff --git a/client/src/app/components/Strike.js b/client/src/app/components/Strike.js deleted file mode 100644 index 219d93ea..00000000 --- a/client/src/app/components/Strike.js +++ /dev/null @@ -1,9 +0,0 @@ -import glamorous from "glamorous"; -export default context => { - const { theme } = context; - return glamorous("div")(() => ({ - position: "relative", - borderBottom: `1px solid ${theme.palette.borderColor}`, - marginBottom: 20 - })); -}; diff --git a/client/src/app/components/applicationView.js b/client/src/app/components/applicationView.js deleted file mode 100644 index 76f8bfcc..00000000 --- a/client/src/app/components/applicationView.js +++ /dev/null @@ -1,62 +0,0 @@ -import React, { createElement as h } from "react"; -import { observer } from "mobx-react"; -import glamorous from "glamorous"; -import asyncView from "components/AsyncView"; -import navBar from "./navbar"; -import footer from "./footer"; -// eslint-disable-next-line no-undef -const version = __VERSION__; - -export default context => { - const { theme, parts } = context; - const { palette } = theme; - const NavBar = navBar(context); - const Footer = footer(context); - const AsyncView = asyncView(context); - const AlertStack = context.alertStack.View; - - const AppRoot = glamorous("div")({ - display: "flex", - minHeight: "100vh" - }); - - const AppView = glamorous("div")(() => ({ - flex: "1 1 auto", - display: "flex", - flexDirection: "column", - color: palette.textPrimary - })); - - const MainView = glamorous("main")({ - display: "flex", - flexGrow: "1", - justifyContent: "center", - alignItems: "flex-start", - marginTop: 50, - "@media(max-width: 600px)": { - margin: 10 - } - }); - - function ApplicationView({ authStore, themeStore, children }) { - return ( - - - - {children} -