=

first commit

Showing 145 changed files with 4694 additions and 0 deletions
1 +node_modules
2 +tmp
3 +lib
1 +{
2 + // Use IntelliSense to learn about possible attributes.
3 + // Hover to view descriptions of existing attributes.
4 + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 + "version": "0.2.0",
6 + "configurations": [
7 + {
8 + "type": "node",
9 + "request": "launch",
10 + "name": "Launch Program",
11 + "program": "${workspaceFolder}/server/src/routers/graphql/Mutation/createPost.ts",
12 + "outFiles": [
13 + "${workspaceFolder}/**/*.js"
14 + ]
15 + }
16 + ]
17 +}
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 +}
...\ No newline at end of file ...\ No newline at end of file
1 +# See https://help.github.com/ignore-files/ for more about ignoring files.
2 +
3 +# dependencies
4 +/node_modules
5 +
6 +# testing
7 +/coverage
8 +
9 +# production
10 +/build
11 +
12 +# misc
13 +.DS_Store
14 +.env.local
15 +.env.development.local
16 +.env.test.local
17 +.env.production.local
18 +
19 +npm-debug.log*
20 +yarn-debug.log*
21 +yarn-error.log*
This diff could not be displayed because it is too large.
1 +'use strict';
2 +
3 +const fs = require('fs');
4 +const path = require('path');
5 +const paths = require('./paths');
6 +
7 +// Make sure that including paths.js after env.js will read .env variables.
8 +delete require.cache[require.resolve('./paths')];
9 +
10 +const NODE_ENV = process.env.NODE_ENV;
11 +if (!NODE_ENV) {
12 + throw new Error(
13 + 'The NODE_ENV environment variable is required but was not specified.'
14 + );
15 +}
16 +
17 +// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
18 +var dotenvFiles = [
19 + `${paths.dotenv}.${NODE_ENV}.local`,
20 + `${paths.dotenv}.${NODE_ENV}`,
21 + // Don't include `.env.local` for `test` environment
22 + // since normally you expect tests to produce the same
23 + // results for everyone
24 + NODE_ENV !== 'test' && `${paths.dotenv}.local`,
25 + paths.dotenv,
26 +].filter(Boolean);
27 +
28 +// Load environment variables from .env* files. Suppress warnings using silent
29 +// if this file is missing. dotenv will never modify any environment variables
30 +// that have already been set. Variable expansion is supported in .env files.
31 +// https://github.com/motdotla/dotenv
32 +// https://github.com/motdotla/dotenv-expand
33 +dotenvFiles.forEach(dotenvFile => {
34 + if (fs.existsSync(dotenvFile)) {
35 + require('dotenv-expand')(
36 + require('dotenv').config({
37 + path: dotenvFile,
38 + })
39 + );
40 + }
41 +});
42 +
43 +// We support resolving modules according to `NODE_PATH`.
44 +// This lets you use absolute paths in imports inside large monorepos:
45 +// https://github.com/facebookincubator/create-react-app/issues/253.
46 +// It works similar to `NODE_PATH` in Node itself:
47 +// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
48 +// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
49 +// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
50 +// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
51 +// We also resolve them to make sure all tools using them work consistently.
52 +const appDirectory = fs.realpathSync(process.cwd());
53 +process.env.NODE_PATH = (process.env.NODE_PATH || '')
54 + .split(path.delimiter)
55 + .filter(folder => folder && !path.isAbsolute(folder))
56 + .map(folder => path.resolve(appDirectory, folder))
57 + .join(path.delimiter);
58 +
59 +// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
60 +// injected into the application via DefinePlugin in Webpack configuration.
61 +const REACT_APP = /^REACT_APP_/i;
62 +
63 +function getClientEnvironment(publicUrl) {
64 + const raw = Object.keys(process.env)
65 + .filter(key => REACT_APP.test(key))
66 + .reduce(
67 + (env, key) => {
68 + env[key] = process.env[key];
69 + return env;
70 + },
71 + {
72 + // Useful for determining whether we’re running in production mode.
73 + // Most importantly, it switches React into the correct mode.
74 + NODE_ENV: process.env.NODE_ENV || 'development',
75 + // Useful for resolving the correct path to static assets in `public`.
76 + // For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
77 + // This should only be used as an escape hatch. Normally you would put
78 + // images into the `src` and `import` them in code to get their paths.
79 + PUBLIC_URL: publicUrl,
80 + }
81 + );
82 + // Stringify all values so we can feed into Webpack DefinePlugin
83 + const stringified = {
84 + 'process.env': Object.keys(raw).reduce(
85 + (env, key) => {
86 + env[key] = JSON.stringify(raw[key]);
87 + return env;
88 + },
89 + {}
90 + ),
91 + };
92 +
93 + return { raw, stringified };
94 +}
95 +
96 +module.exports = getClientEnvironment;
1 +'use strict';
2 +
3 +// This is a custom Jest transformer turning style imports into empty objects.
4 +// http://facebook.github.io/jest/docs/en/webpack.html
5 +
6 +module.exports = {
7 + process() {
8 + return 'module.exports = {};';
9 + },
10 + getCacheKey() {
11 + // The output is always the same.
12 + return 'cssTransform';
13 + },
14 +};
1 +'use strict';
2 +
3 +const path = require('path');
4 +
5 +// This is a custom Jest transformer turning file imports into filenames.
6 +// http://facebook.github.io/jest/docs/en/webpack.html
7 +
8 +module.exports = {
9 + process(src, filename) {
10 + return `module.exports = ${JSON.stringify(path.basename(filename))};`;
11 + },
12 +};
1 +// Copyright 2004-present Facebook. All Rights Reserved.
2 +
3 +'use strict';
4 +
5 +const tsJestPreprocessor = require('ts-jest/preprocessor');
6 +
7 +module.exports = tsJestPreprocessor;
1 +'use strict';
2 +
3 +const path = require('path');
4 +const fs = require('fs');
5 +const url = require('url');
6 +
7 +// Make sure any symlinks in the project folder are resolved:
8 +// https://github.com/facebookincubator/create-react-app/issues/637
9 +const appDirectory = fs.realpathSync(process.cwd());
10 +const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
11 +
12 +const envPublicUrl = process.env.PUBLIC_URL;
13 +
14 +function ensureSlash(path, needsSlash) {
15 + const hasSlash = path.endsWith('/');
16 + if (hasSlash && !needsSlash) {
17 + return path.substr(path, path.length - 1);
18 + } else if (!hasSlash && needsSlash) {
19 + return `${path}/`;
20 + } else {
21 + return path;
22 + }
23 +}
24 +
25 +const getPublicUrl = appPackageJson =>
26 + envPublicUrl || require(appPackageJson).homepage;
27 +
28 +// We use `PUBLIC_URL` environment variable or "homepage" field to infer
29 +// "public path" at which the app is served.
30 +// Webpack needs to know it to put the right <script> hrefs into HTML even in
31 +// single-page apps that may serve index.html for nested URLs like /todos/42.
32 +// We can't use a relative path in HTML because we don't want to load something
33 +// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
34 +function getServedPath(appPackageJson) {
35 + const publicUrl = getPublicUrl(appPackageJson);
36 + const servedUrl = envPublicUrl ||
37 + (publicUrl ? url.parse(publicUrl).pathname : '/');
38 + return ensureSlash(servedUrl, true);
39 +}
40 +
41 +// config after eject: we're in ./config/
42 +module.exports = {
43 + dotenv: resolveApp('.env'),
44 + appBuild: resolveApp('build'),
45 + appPublic: resolveApp('public'),
46 + appHtml: resolveApp('public/index.html'),
47 + appIndexJs: resolveApp('src/index.tsx'),
48 + appPackageJson: resolveApp('package.json'),
49 + appSrc: resolveApp('src'),
50 + yarnLockFile: resolveApp('yarn.lock'),
51 + testsSetup: resolveApp('src/setupTests.ts'),
52 + appNodeModules: resolveApp('node_modules'),
53 + appTsConfig: resolveApp('tsconfig.json'),
54 + appTsLint: resolveApp('tslint.json'),
55 + publicUrl: getPublicUrl(resolveApp('package.json')),
56 + servedPath: getServedPath(resolveApp('package.json')),
57 +};
1 +'use strict';
2 +
3 +if (typeof Promise === 'undefined') {
4 + // Rejection tracking prevents a common issue where React gets into an
5 + // inconsistent state due to an error, but it gets swallowed by a Promise,
6 + // and the user has no idea what causes React's erratic future behavior.
7 + require('promise/lib/rejection-tracking').enable();
8 + window.Promise = require('promise/lib/es6-extensions.js');
9 +}
10 +
11 +// fetch() polyfill for making API calls.
12 +require('whatwg-fetch');
13 +
14 +// Object.assign() is commonly used with React.
15 +// It will use the native implementation if it's present and isn't buggy.
16 +Object.assign = require('object-assign');
17 +
18 +// In tests, polyfill requestAnimationFrame since jsdom doesn't provide it yet.
19 +// We don't polyfill it in the browser--this is user's responsibility.
20 +if (process.env.NODE_ENV === 'test') {
21 + require('raf').polyfill(global);
22 +}
1 +'use strict';
2 +
3 +const autoprefixer = require('autoprefixer');
4 +const path = require('path');
5 +const webpack = require('webpack');
6 +const HtmlWebpackPlugin = require('html-webpack-plugin');
7 +const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
8 +const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
9 +const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
10 +const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
11 +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
12 +const getClientEnvironment = require('./env');
13 +const paths = require('./paths');
14 +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
15 +
16 +const publicPath = '/';
17 +const publicUrl = '';
18 +const env = getClientEnvironment(publicUrl);
19 +
20 +module.exports = {
21 + devtool: 'cheap-module-source-map',
22 + entry: [
23 + require.resolve('./polyfills'),
24 + require.resolve('react-dev-utils/webpackHotDevClient'),
25 + paths.appIndexJs,
26 + ],
27 + output: {
28 + pathinfo: true,
29 + filename: 'static/js/bundle.js',
30 + chunkFilename: 'static/js/[name].chunk.js',
31 + publicPath: publicPath,
32 + devtoolModuleFilenameTemplate: info =>
33 + path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
34 + },
35 + resolve: {
36 + modules: ['src', 'node_modules', paths.appNodeModules].concat(
37 + process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
38 + ),
39 + extensions: [
40 + '.mjs',
41 + '.web.ts',
42 + '.ts',
43 + '.web.tsx',
44 + '.tsx',
45 + '.web.js',
46 + '.js',
47 + '.json',
48 + '.web.jsx',
49 + '.jsx',
50 + ],
51 + plugins: [
52 + new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
53 + new TsconfigPathsPlugin({ configFile: paths.appTsConfig }),
54 + ],
55 + },
56 + module: {
57 + strictExportPresence: true,
58 + rules: [
59 + {
60 + test: /\.(js|jsx|mjs)$/,
61 + loader: require.resolve('source-map-loader'),
62 + enforce: 'pre',
63 + include: paths.appSrc,
64 + },
65 + {
66 + oneOf: [
67 + {
68 + test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
69 + loader: require.resolve('url-loader'),
70 + options: {
71 + limit: 10000,
72 + name: 'static/media/[name].[hash:8].[ext]',
73 + },
74 + },
75 + {
76 + test: /\.(js|jsx|mjs)$/,
77 + include: paths.appSrc,
78 + loader: require.resolve('babel-loader'),
79 + options: {
80 +
81 + compact: true,
82 + },
83 + },
84 + {
85 + test: /\.(ts|tsx)$/,
86 + include: paths.appSrc,
87 + use: [
88 + {
89 + loader: require.resolve('ts-loader'),
90 + options: {
91 + transpileOnly: true,
92 + },
93 + },
94 + ],
95 + },
96 + {
97 + test: /\.css$/,
98 + use: [
99 + require.resolve('style-loader'),
100 + {
101 + loader: require.resolve('css-loader'),
102 + options: {
103 + importLoaders: 1,
104 + },
105 + },
106 + {
107 + loader: require.resolve('postcss-loader'),
108 + options: {
109 + ident: 'postcss',
110 + plugins: () => [
111 + require('postcss-flexbugs-fixes'),
112 + autoprefixer({
113 + browsers: [
114 + '>1%',
115 + 'last 4 versions',
116 + 'Firefox ESR',
117 + 'not ie < 9', // React doesn't support IE8 anyway
118 + ],
119 + flexbox: 'no-2009',
120 + }),
121 + ],
122 + },
123 + },
124 + ],
125 + },
126 + {
127 + test: /\.scss$/,
128 + use: [
129 + require.resolve('style-loader'),
130 + {
131 + loader: require.resolve('css-loader'),
132 + options: {
133 + importLoaders: 1,
134 + },
135 + },
136 + {
137 + loader: require.resolve('postcss-loader'),
138 + options: {
139 + ident: 'postcss',
140 + plugins: () => [
141 + require('postcss-flexbugs-fixes'),
142 + autoprefixer({
143 + browsers: [
144 + '>1%',
145 + 'last 4 versions',
146 + 'Firefox ESR',
147 + 'not ie < 9', // React doesn't support IE8 anyway
148 + ],
149 + flexbox: 'no-2009',
150 + }),
151 + ],
152 + },
153 + },
154 + {
155 + loader: require.resolve('sass-loader'),
156 + options: {
157 + // includePaths: ["absolute/path/a", "absolute/path/b"]
158 + }
159 + }
160 + ],
161 + },
162 + {
163 + test: /\.(gql|graphql)$/,
164 + loader: require.resolve('graphql-tag/loader'),
165 + },
166 + {
167 + exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
168 + loader: require.resolve('file-loader'),
169 + options: {
170 + name: 'static/media/[name].[hash:8].[ext]',
171 + },
172 + },
173 + ],
174 + },
175 + ],
176 + },
177 + plugins: [
178 + new InterpolateHtmlPlugin(env.raw),
179 + new HtmlWebpackPlugin({
180 + inject: true,
181 + template: paths.appHtml,
182 + }),
183 + new webpack.NamedModulesPlugin(),
184 + new webpack.DefinePlugin(env.stringified),
185 + new webpack.HotModuleReplacementPlugin(),
186 + new CaseSensitivePathsPlugin(),
187 + new WatchMissingNodeModulesPlugin(paths.appNodeModules),
188 + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
189 + new ForkTsCheckerWebpackPlugin({
190 + async: false,
191 + watch: paths.appSrc,
192 + tsconfig: paths.appTsConfig,
193 + tslint: paths.appTsLint,
194 + }),
195 + ],
196 + node: {
197 + dgram: 'empty',
198 + fs: 'empty',
199 + net: 'empty',
200 + tls: 'empty',
201 + child_process: 'empty',
202 + },
203 + performance: {
204 + hints: false,
205 + },
206 +};
1 +'use strict';
2 +
3 +const autoprefixer = require('autoprefixer');
4 +const path = require('path');
5 +const webpack = require('webpack');
6 +const HtmlWebpackPlugin = require('html-webpack-plugin');
7 +const ExtractTextPlugin = require('extract-text-webpack-plugin');
8 +const ManifestPlugin = require('webpack-manifest-plugin');
9 +const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
10 +const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
11 +const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
12 +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
13 +const paths = require('./paths');
14 +const getClientEnvironment = require('./env');
15 +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
16 +const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
17 +
18 +// Webpack uses `publicPath` to determine where the app is being served from.
19 +// It requires a trailing slash, or the file assets will get an incorrect path.
20 +const publicPath = paths.servedPath;
21 +// Some apps do not use client-side routing with pushState.
22 +// For these, "homepage" can be set to "." to enable relative asset paths.
23 +const shouldUseRelativeAssetPaths = publicPath === './';
24 +// Source maps are resource heavy and can cause out of memory issue for large source files.
25 +const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
26 +// `publicUrl` is just like `publicPath`, but we will provide it to our app
27 +// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
28 +// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
29 +const publicUrl = publicPath.slice(0, -1);
30 +// Get environment variables to inject into our app.
31 +const env = getClientEnvironment(publicUrl);
32 +
33 +// Assert this just to be safe.
34 +// Development builds of React are slow and not intended for production.
35 +if (env.stringified['process.env'].NODE_ENV !== '"production"') {
36 + throw new Error('Production builds must have NODE_ENV=production.');
37 +}
38 +
39 +// Note: defined here because it will be used more than once.
40 +const cssFilename = 'static/css/[name].[contenthash:8].css';
41 +
42 +// ExtractTextPlugin expects the build output to be flat.
43 +// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
44 +// However, our output is structured with css, js and media folders.
45 +// To have this structure working with relative paths, we have to use custom options.
46 +const extractTextPluginOptions = shouldUseRelativeAssetPaths
47 + ? // Making sure that the publicPath goes back to to build folder.
48 + { publicPath: Array(cssFilename.split('/').length).join('../') }
49 + : {};
50 +
51 +// This is the production configuration.
52 +// It compiles slowly and is focused on producing a fast and minimal bundle.
53 +// The development configuration is different and lives in a separate file.
54 +module.exports = {
55 + // Don't attempt to continue if there are any errors.
56 + bail: true,
57 + // We generate sourcemaps in production. This is slow but gives good results.
58 + // You can exclude the *.map files from the build during deployment.
59 + devtool: shouldUseSourceMap ? 'source-map' : false,
60 + // In production, we only want to load the polyfills and the app code.
61 + entry: [require.resolve('./polyfills'), paths.appIndexJs],
62 + output: {
63 + // The build folder.
64 + path: paths.appBuild,
65 + // Generated JS file names (with nested folders).
66 + // There will be one main bundle, and one file per asynchronous chunk.
67 + // We don't currently advertise code splitting but Webpack supports it.
68 + filename: 'static/js/[name].[chunkhash:8].js',
69 + chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
70 + // We inferred the "public path" (such as / or /my-project) from homepage.
71 + publicPath: publicPath,
72 + // Point sourcemap entries to original disk location (format as URL on Windows)
73 + devtoolModuleFilenameTemplate: info =>
74 + path
75 + .relative(paths.appSrc, info.absoluteResourcePath)
76 + .replace(/\\/g, '/'),
77 + },
78 + resolve: {
79 + // This allows you to set a fallback for where Webpack should look for modules.
80 + // We placed these paths second because we want `node_modules` to "win"
81 + // if there are any conflicts. This matches Node resolution mechanism.
82 + // https://github.com/facebookincubator/create-react-app/issues/253
83 + modules: ['src', 'node_modules', paths.appNodeModules].concat(
84 + // It is guaranteed to exist because we tweak it in `env.js`
85 + process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
86 + ),
87 + // These are the reasonable defaults supported by the Node ecosystem.
88 + // We also include JSX as a common component filename extension to support
89 + // some tools, although we do not recommend using it, see:
90 + // https://github.com/facebookincubator/create-react-app/issues/290
91 + // `web` extension prefixes have been added for better support
92 + // for React Native Web.
93 + extensions: [
94 + '.mjs',
95 + '.web.ts',
96 + '.ts',
97 + '.web.tsx',
98 + '.tsx',
99 + '.web.js',
100 + '.js',
101 + '.json',
102 + '.web.jsx',
103 + '.jsx',
104 + ],
105 + alias: {
106 +
107 + // Support React Native Web
108 + // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
109 + 'react-native': 'react-native-web',
110 + },
111 + plugins: [
112 + // Prevents users from importing files from outside of src/ (or node_modules/).
113 + // This often causes confusion because we only process files within src/ with babel.
114 + // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
115 + // please link the files into your node_modules/ and let module-resolution kick in.
116 + // Make sure your source files are compiled, as they will not be processed in any way.
117 + new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
118 + new TsconfigPathsPlugin({ configFile: paths.appTsConfig }),
119 + ],
120 + },
121 + module: {
122 + strictExportPresence: true,
123 + rules: [
124 + // TODO: Disable require.ensure as it's not a standard language feature.
125 + // We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176.
126 + // { parser: { requireEnsure: false } },
127 + {
128 + test: /\.(js|jsx|mjs)$/,
129 + loader: require.resolve('source-map-loader'),
130 + enforce: 'pre',
131 + include: paths.appSrc,
132 + },
133 + {
134 + // "oneOf" will traverse all following loaders until one will
135 + // match the requirements. When no loader matches it will fall
136 + // back to the "file" loader at the end of the loader list.
137 + oneOf: [
138 + // "url" loader works just like "file" loader but it also embeds
139 + // assets smaller than specified size as data URLs to avoid requests.
140 + {
141 + test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
142 + loader: require.resolve('url-loader'),
143 + options: {
144 + limit: 10000,
145 + name: 'static/media/[name].[hash:8].[ext]',
146 + },
147 + },
148 + {
149 + test: /\.(js|jsx|mjs)$/,
150 + include: paths.appSrc,
151 + loader: require.resolve('babel-loader'),
152 + options: {
153 +
154 + compact: true,
155 + },
156 + },
157 + // Compile .tsx?
158 + {
159 + test: /\.(ts|tsx)$/,
160 + include: paths.appSrc,
161 + use: [
162 + {
163 + loader: require.resolve('ts-loader'),
164 + options: {
165 + // disable type checker - we will use it in fork plugin
166 + transpileOnly: true,
167 + },
168 + },
169 + ],
170 + },
171 + // The notation here is somewhat confusing.
172 + // "postcss" loader applies autoprefixer to our CSS.
173 + // "css" loader resolves paths in CSS and adds assets as dependencies.
174 + // "style" loader normally turns CSS into JS modules injecting <style>,
175 + // but unlike in development configuration, we do something different.
176 + // `ExtractTextPlugin` first applies the "postcss" and "css" loaders
177 + // (second argument), then grabs the result CSS and puts it into a
178 + // separate file in our build process. This way we actually ship
179 + // a single CSS file in production instead of JS code injecting <style>
180 + // tags. If you use code splitting, however, any async bundles will still
181 + // use the "style" loader inside the async code so CSS from them won't be
182 + // in the main CSS file.
183 + {
184 + test: /\.css$/,
185 + loader: ExtractTextPlugin.extract(
186 + Object.assign(
187 + {
188 + fallback: {
189 + loader: require.resolve('style-loader'),
190 + options: {
191 + hmr: false,
192 + },
193 + },
194 + use: [
195 + {
196 + loader: require.resolve('css-loader'),
197 + options: {
198 + importLoaders: 1,
199 + minimize: true,
200 + sourceMap: shouldUseSourceMap,
201 + },
202 + },
203 + {
204 + loader: require.resolve('postcss-loader'),
205 + options: {
206 + // Necessary for external CSS imports to work
207 + // https://github.com/facebookincubator/create-react-app/issues/2677
208 + ident: 'postcss',
209 + plugins: () => [
210 + require('postcss-flexbugs-fixes'),
211 + autoprefixer({
212 + browsers: [
213 + '>1%',
214 + 'last 4 versions',
215 + 'Firefox ESR',
216 + 'not ie < 9', // React doesn't support IE8 anyway
217 + ],
218 + flexbox: 'no-2009',
219 + }),
220 + ],
221 + },
222 + },
223 + ],
224 + },
225 + extractTextPluginOptions
226 + )
227 + ),
228 + // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
229 + },
230 + // "file" loader makes sure assets end up in the `build` folder.
231 + // When you `import` an asset, you get its filename.
232 + // This loader doesn't use a "test" so it will catch all modules
233 + // that fall through the other loaders.
234 + {
235 + loader: require.resolve('file-loader'),
236 + // Exclude `js` files to keep "css" loader working as it injects
237 + // it's runtime that would otherwise processed through "file" loader.
238 + // Also exclude `html` and `json` extensions so they get processed
239 + // by webpacks internal loaders.
240 + exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
241 + options: {
242 + name: 'static/media/[name].[hash:8].[ext]',
243 + },
244 + },
245 + // ** STOP ** Are you adding a new loader?
246 + // Make sure to add the new loader(s) before the "file" loader.
247 + ],
248 + },
249 + ],
250 + },
251 + plugins: [
252 + // Makes some environment variables available in index.html.
253 + // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
254 + // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
255 + // In production, it will be an empty string unless you specify "homepage"
256 + // in `package.json`, in which case it will be the pathname of that URL.
257 + new InterpolateHtmlPlugin(env.raw),
258 + // Generates an `index.html` file with the <script> injected.
259 + new HtmlWebpackPlugin({
260 + inject: true,
261 + template: paths.appHtml,
262 + minify: {
263 + removeComments: true,
264 + collapseWhitespace: true,
265 + removeRedundantAttributes: true,
266 + useShortDoctype: true,
267 + removeEmptyAttributes: true,
268 + removeStyleLinkTypeAttributes: true,
269 + keepClosingSlash: true,
270 + minifyJS: true,
271 + minifyCSS: true,
272 + minifyURLs: true,
273 + },
274 + }),
275 + // Makes some environment variables available to the JS code, for example:
276 + // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
277 + // It is absolutely essential that NODE_ENV was set to production here.
278 + // Otherwise React will be compiled in the very slow development mode.
279 + new webpack.DefinePlugin(env.stringified),
280 + // Minify the code.
281 + new UglifyJsPlugin({
282 + uglifyOptions: {
283 + parse: {
284 + // we want uglify-js to parse ecma 8 code. However we want it to output
285 + // ecma 5 compliant code, to avoid issues with older browsers, this is
286 + // whey we put `ecma: 5` to the compress and output section
287 + // https://github.com/facebook/create-react-app/pull/4234
288 + ecma: 8,
289 + },
290 + compress: {
291 + ecma: 5,
292 + warnings: false,
293 + // Disabled because of an issue with Uglify breaking seemingly valid code:
294 + // https://github.com/facebook/create-react-app/issues/2376
295 + // Pending further investigation:
296 + // https://github.com/mishoo/UglifyJS2/issues/2011
297 + comparisons: false,
298 + },
299 + mangle: {
300 + safari10: true,
301 + },
302 + output: {
303 + ecma: 5,
304 + comments: false,
305 + // Turned on because emoji and regex is not minified properly using default
306 + // https://github.com/facebook/create-react-app/issues/2488
307 + ascii_only: true,
308 + },
309 + },
310 + // Use multi-process parallel running to improve the build speed
311 + // Default number of concurrent runs: os.cpus().length - 1
312 + parallel: true,
313 + // Enable file caching
314 + cache: true,
315 + sourceMap: shouldUseSourceMap,
316 + }), // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
317 + new ExtractTextPlugin({
318 + filename: cssFilename,
319 + }),
320 + // Generate a manifest file which contains a mapping of all asset filenames
321 + // to their corresponding output file so that tools can pick it up without
322 + // having to parse `index.html`.
323 + new ManifestPlugin({
324 + fileName: 'asset-manifest.json',
325 + }),
326 + // Generate a service worker script that will precache, and keep up to date,
327 + // the HTML & assets that are part of the Webpack build.
328 + new SWPrecacheWebpackPlugin({
329 + // By default, a cache-busting query parameter is appended to requests
330 + // used to populate the caches, to ensure the responses are fresh.
331 + // If a URL is already hashed by Webpack, then there is no concern
332 + // about it being stale, and the cache-busting can be skipped.
333 + dontCacheBustUrlsMatching: /\.\w{8}\./,
334 + filename: 'service-worker.js',
335 + logger(message) {
336 + if (message.indexOf('Total precache size is') === 0) {
337 + // This message occurs for every build and is a bit too noisy.
338 + return;
339 + }
340 + if (message.indexOf('Skipping static resource') === 0) {
341 + // This message obscures real errors so we ignore it.
342 + // https://github.com/facebookincubator/create-react-app/issues/2612
343 + return;
344 + }
345 + console.log(message);
346 + },
347 + minify: true,
348 + // For unknown URLs, fallback to the index page
349 + navigateFallback: publicUrl + '/index.html',
350 + // Ignores URLs starting from /__ (useful for Firebase):
351 + // https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
352 + navigateFallbackWhitelist: [/^(?!\/__).*/],
353 + // Don't precache sourcemaps (they're large) and build asset manifest:
354 + staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
355 + }),
356 + // Moment.js is an extremely popular library that bundles large locale files
357 + // by default due to how Webpack interprets its code. This is a practical
358 + // solution that requires the user to opt into importing specific locales.
359 + // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
360 + // You can remove this if you don't use Moment.js:
361 + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
362 + // Perform type checking and linting in a separate process to speed up compilation
363 + new ForkTsCheckerWebpackPlugin({
364 + async: false,
365 + tsconfig: paths.appTsConfig,
366 + tslint: paths.appTsLint,
367 + }),
368 + ],
369 + // Some libraries import Node modules but don't use them in the browser.
370 + // Tell Webpack to provide empty mocks for them so importing them works.
371 + node: {
372 + dgram: 'empty',
373 + fs: 'empty',
374 + net: 'empty',
375 + tls: 'empty',
376 + child_process: 'empty',
377 + },
378 +};
1 +'use strict';
2 +
3 +const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
4 +const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
5 +const ignoredFiles = require('react-dev-utils/ignoredFiles');
6 +const config = require('./webpack.config.dev');
7 +const paths = require('./paths');
8 +
9 +const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
10 +const host = process.env.HOST || '0.0.0.0';
11 +
12 +module.exports = function(proxy, allowedHost) {
13 + return {
14 + // WebpackDevServer 2.4.3 introduced a security fix that prevents remote
15 + // websites from potentially accessing local content through DNS rebinding:
16 + // https://github.com/webpack/webpack-dev-server/issues/887
17 + // https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
18 + // However, it made several existing use cases such as development in cloud
19 + // environment or subdomains in development significantly more complicated:
20 + // https://github.com/facebookincubator/create-react-app/issues/2271
21 + // https://github.com/facebookincubator/create-react-app/issues/2233
22 + // While we're investigating better solutions, for now we will take a
23 + // compromise. Since our WDS configuration only serves files in the `public`
24 + // folder we won't consider accessing them a vulnerability. However, if you
25 + // use the `proxy` feature, it gets more dangerous because it can expose
26 + // remote code execution vulnerabilities in backends like Django and Rails.
27 + // So we will disable the host check normally, but enable it if you have
28 + // specified the `proxy` setting. Finally, we let you override it if you
29 + // really know what you're doing with a special environment variable.
30 + disableHostCheck: !proxy ||
31 + process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
32 + // Enable gzip compression of generated files.
33 + compress: true,
34 + // Silence WebpackDevServer's own logs since they're generally not useful.
35 + // It will still show compile warnings and errors with this setting.
36 + clientLogLevel: 'none',
37 + // By default WebpackDevServer serves physical files from current directory
38 + // in addition to all the virtual build products that it serves from memory.
39 + // This is confusing because those files won’t automatically be available in
40 + // production build folder unless we copy them. However, copying the whole
41 + // project directory is dangerous because we may expose sensitive files.
42 + // Instead, we establish a convention that only files in `public` directory
43 + // get served. Our build script will copy `public` into the `build` folder.
44 + // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
45 + // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
46 + // In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
47 + // Note that we only recommend to use `public` folder as an escape hatch
48 + // for files like `favicon.ico`, `manifest.json`, and libraries that are
49 + // for some reason broken when imported through Webpack. If you just want to
50 + // use an image, put it in `src` and `import` it from JavaScript instead.
51 + contentBase: paths.appPublic,
52 + // By default files from `contentBase` will not trigger a page reload.
53 + watchContentBase: true,
54 + // Enable hot reloading server. It will provide /sockjs-node/ endpoint
55 + // for the WebpackDevServer client so it can learn when the files were
56 + // updated. The WebpackDevServer client is included as an entry point
57 + // in the Webpack development configuration. Note that only changes
58 + // to CSS are currently hot reloaded. JS changes will refresh the browser.
59 + hot: true,
60 + // It is important to tell WebpackDevServer to use the same "root" path
61 + // as we specified in the config. In development, we always serve from /.
62 + publicPath: config.output.publicPath,
63 + // WebpackDevServer is noisy by default so we emit custom message instead
64 + // by listening to the compiler events with `compiler.plugin` calls above.
65 + quiet: true,
66 + // Reportedly, this avoids CPU overload on some systems.
67 + // https://github.com/facebookincubator/create-react-app/issues/293
68 + // src/node_modules is not ignored to support absolute imports
69 + // https://github.com/facebookincubator/create-react-app/issues/1065
70 + watchOptions: {
71 + ignored: ignoredFiles(paths.appSrc),
72 + },
73 + // Enable HTTPS if the HTTPS environment variable is set to 'true'
74 + https: protocol === 'https',
75 + host: host,
76 + overlay: false,
77 + historyApiFallback: {
78 + // Paths with dots should still use the history fallback.
79 + // See https://github.com/facebookincubator/create-react-app/issues/387.
80 + disableDotRule: true,
81 + },
82 + public: allowedHost,
83 + proxy,
84 + before(app) {
85 + // This lets us open files from the runtime error overlay.
86 + app.use(errorOverlayMiddleware());
87 + // This service worker file is effectively a 'no-op' that will reset any
88 + // previous service worker registered for the same host:port combination.
89 + // We do this in development to avoid hitting the production cache if
90 + // it used the same host and port.
91 + // https://github.com/facebookincubator/create-react-app/issues/2272#issuecomment-302832432
92 + app.use(noopServiceWorkerMiddleware());
93 + },
94 + };
95 +};
1 +declare module '*.svg'
2 +declare module '*.png'
3 +declare module '*.jpg'
1 +{
2 + "name": "front",
3 + "version": "0.1.0",
4 + "private": true,
5 + "proxy": "http://0.0.0.0:7777",
6 + "dependencies": {
7 + "apollo-boost": "^0.1.4",
8 + "apollo-cache-inmemory": "^1.2.1",
9 + "apollo-link-context": "^1.0.8",
10 + "apollo-link-http": "^1.5.4",
11 + "apollo-upload-client": "^8.0.0",
12 + "axios": "^0.18.0",
13 + "graphql": "^0.13.2",
14 + "material-ui": "^0.20.0",
15 + "ramda": "^0.25.0",
16 + "react": "^16.3.1",
17 + "react-apollo": "^2.1.3",
18 + "react-dom": "^16.3.1",
19 + "react-redux": "^5.0.7",
20 + "react-router-dom": "^4.2.2",
21 + "redux": "^4.0.0",
22 + "redux-actions": "^2.3.0",
23 + "redux-logger": "^3.0.6",
24 + "redux-observable": "^1.0.0-alpha.2",
25 + "rxjs": "^6.1.0"
26 + },
27 + "scripts": {
28 + "start": "node scripts/start.js",
29 + "build": "node scripts/build.js",
30 + "test": "node scripts/test.js --env=jsdom"
31 + },
32 + "devDependencies": {
33 + "@types/graphql": "^0.13.0",
34 + "@types/jest": "^22.2.3",
35 + "@types/material-ui": "^0.21.2",
36 + "@types/node": "^9.6.5",
37 + "@types/ramda": "^0.25.21",
38 + "@types/react": "^16.3.10",
39 + "@types/react-dom": "^16.0.5",
40 + "@types/react-redux": "^5.0.19",
41 + "@types/react-router-dom": "^4.2.6",
42 + "@types/redux-actions": "^2.2.4",
43 + "@types/redux-logger": "^3.0.6",
44 + "async-each": "^1.0.1",
45 + "autoprefixer": "7.1.6",
46 + "babel-jest": "^22.1.0",
47 + "babel-loader": "^7.1.2",
48 + "babel-preset-react-app": "^3.1.1",
49 + "case-sensitive-paths-webpack-plugin": "2.1.1",
50 + "chalk": "1.1.3",
51 + "css-loader": "0.28.7",
52 + "dotenv": "4.0.0",
53 + "dotenv-expand": "4.2.0",
54 + "extract-text-webpack-plugin": "3.0.2",
55 + "file-loader": "0.11.2",
56 + "fork-ts-checker-webpack-plugin": "^0.2.8",
57 + "fs-extra": "3.0.1",
58 + "html-webpack-plugin": "2.29.0",
59 + "jest": "22.1.4",
60 + "node-sass": "^4.9.0",
61 + "object-assign": "4.1.1",
62 + "postcss-flexbugs-fixes": "3.2.0",
63 + "postcss-loader": "2.0.8",
64 + "promise": "8.0.1",
65 + "raf": "3.4.0",
66 + "react-dev-utils": "^5.0.1",
67 + "resolve": "1.6.0",
68 + "sass-loader": "^7.0.1",
69 + "source-map-loader": "^0.2.1",
70 + "style-loader": "0.19.0",
71 + "styled-components": "^3.2.5",
72 + "sw-precache-webpack-plugin": "0.11.4",
73 + "ts-jest": "22.0.1",
74 + "ts-loader": "^2.3.7",
75 + "tsconfig-paths-webpack-plugin": "^2.0.0",
76 + "tslint": "^5.7.0",
77 + "tslint-config-prettier": "^1.10.0",
78 + "tslint-react": "^3.2.0",
79 + "typescript": "^2.8.1",
80 + "uglifyjs-webpack-plugin": "^1.1.8",
81 + "url-loader": "0.6.2",
82 + "webpack": "3.8.1",
83 + "webpack-dev-server": "2.9.4",
84 + "webpack-manifest-plugin": "1.3.2",
85 + "whatwg-fetch": "2.0.3"
86 + },
87 + "jest": {
88 + "collectCoverageFrom": [
89 + "src/**/*.{js,jsx,ts,tsx}"
90 + ],
91 + "setupFiles": [
92 + "<rootDir>/config/polyfills.js"
93 + ],
94 + "testMatch": [
95 + "<rootDir>/src/**/__tests__/**/*.(j|t)s?(x)",
96 + "<rootDir>/src/**/?(*.)(spec|test).(j|t)s?(x)"
97 + ],
98 + "testEnvironment": "node",
99 + "testURL": "http://localhost",
100 + "transform": {
101 + "^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
102 + "^.+\\.tsx?$": "<rootDir>/config/jest/typescriptTransform.js",
103 + "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
104 + "^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
105 + },
106 + "transformIgnorePatterns": [
107 + "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|ts|tsx)$"
108 + ],
109 + "moduleNameMapper": {
110 + "^react-native$": "react-native-web"
111 + },
112 + "moduleFileExtensions": [
113 + "web.ts",
114 + "ts",
115 + "web.tsx",
116 + "tsx",
117 + "web.js",
118 + "js",
119 + "web.jsx",
120 + "jsx",
121 + "json",
122 + "node",
123 + "mjs"
124 + ],
125 + "globals": {
126 + "ts-jest": {
127 + "tsConfigFile": "/home/merong/Project/money/front/tsconfig.test.json"
128 + }
129 + }
130 + },
131 + "babel": {
132 + "presets": [
133 + "react-app"
134 + ]
135 + },
136 + "eslintConfig": {
137 + "extends": "react-app"
138 + }
139 +}
No preview for this file type
1 +<!DOCTYPE html>
2 +<html lang="en">
3 + <head>
4 + <meta charset="utf-8">
5 + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6 + <meta name="theme-color" content="#000000">
7 + <!--
8 + manifest.json provides metadata used when your web app is added to the
9 + homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
10 + -->
11 + <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
12 + <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
13 + <!--
14 + Notice the use of %PUBLIC_URL% in the tags above.
15 + It will be replaced with the URL of the `public` folder during the build.
16 + Only files inside the `public` folder can be referenced from the HTML.
17 +
18 + Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
19 + work correctly both with client-side routing and a non-root public URL.
20 + Learn how to configure a non-root public URL by running `npm run build`.
21 + -->
22 + <title>React App</title>
23 + </head>
24 + <body>
25 + <noscript>
26 + You need to enable JavaScript to run this app.
27 + </noscript>
28 + <div id="root"></div>
29 + <!--
30 + This HTML file is a template.
31 + If you open it directly in the browser, you will see an empty page.
32 +
33 + You can add webfonts, meta tags, or analytics to this file.
34 + The build step will place the bundled scripts into the <body> tag.
35 +
36 + To begin the development, run `npm start` or `yarn start`.
37 + To create a production bundle, use `npm run build` or `yarn build`.
38 + -->
39 + </body>
40 +</html>
1 +{
2 + "short_name": "React App",
3 + "name": "Create React App Sample",
4 + "icons": [
5 + {
6 + "src": "favicon.ico",
7 + "sizes": "64x64 32x32 24x24 16x16",
8 + "type": "image/x-icon"
9 + }
10 + ],
11 + "start_url": "./index.html",
12 + "display": "standalone",
13 + "theme_color": "#000000",
14 + "background_color": "#ffffff"
15 +}
1 +'use strict';
2 +
3 +// Do this as the first thing so that any code reading it knows the right env.
4 +process.env.BABEL_ENV = 'production';
5 +process.env.NODE_ENV = 'production';
6 +
7 +// Makes the script crash on unhandled rejections instead of silently
8 +// ignoring them. In the future, promise rejections that are not handled will
9 +// terminate the Node.js process with a non-zero exit code.
10 +process.on('unhandledRejection', err => {
11 + throw err;
12 +});
13 +
14 +// Ensure environment variables are read.
15 +require('../config/env');
16 +
17 +const path = require('path');
18 +const chalk = require('chalk');
19 +const fs = require('fs-extra');
20 +const webpack = require('webpack');
21 +const config = require('../config/webpack.config.prod');
22 +const paths = require('../config/paths');
23 +const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
24 +const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
25 +const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
26 +const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
27 +const printBuildError = require('react-dev-utils/printBuildError');
28 +
29 +const measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild;
30 +const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
31 +const useYarn = fs.existsSync(paths.yarnLockFile);
32 +
33 +// These sizes are pretty large. We'll warn for bundles exceeding them.
34 +const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
35 +const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
36 +
37 +// Warn and crash if required files are missing
38 +if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
39 + process.exit(1);
40 +}
41 +
42 +// First, read the current file sizes in build directory.
43 +// This lets us display how much they changed later.
44 +measureFileSizesBeforeBuild(paths.appBuild)
45 + .then(previousFileSizes => {
46 + // Remove all content but keep the directory so that
47 + // if you're in it, you don't end up in Trash
48 + fs.emptyDirSync(paths.appBuild);
49 + // Merge with the public folder
50 + copyPublicFolder();
51 + // Start the webpack build
52 + return build(previousFileSizes);
53 + })
54 + .then(
55 + ({ stats, previousFileSizes, warnings }) => {
56 + if (warnings.length) {
57 + console.log(chalk.yellow('Compiled with warnings.\n'));
58 + console.log(warnings.join('\n\n'));
59 + console.log(
60 + '\nSearch for the ' +
61 + chalk.underline(chalk.yellow('keywords')) +
62 + ' to learn more about each warning.'
63 + );
64 + console.log(
65 + 'To ignore, add ' +
66 + chalk.cyan('// eslint-disable-next-line') +
67 + ' to the line before.\n'
68 + );
69 + } else {
70 + console.log(chalk.green('Compiled successfully.\n'));
71 + }
72 +
73 + console.log('File sizes after gzip:\n');
74 + printFileSizesAfterBuild(
75 + stats,
76 + previousFileSizes,
77 + paths.appBuild,
78 + WARN_AFTER_BUNDLE_GZIP_SIZE,
79 + WARN_AFTER_CHUNK_GZIP_SIZE
80 + );
81 + console.log();
82 +
83 + const appPackage = require(paths.appPackageJson);
84 + const publicUrl = paths.publicUrl;
85 + const publicPath = config.output.publicPath;
86 + const buildFolder = path.relative(process.cwd(), paths.appBuild);
87 + printHostingInstructions(
88 + appPackage,
89 + publicUrl,
90 + publicPath,
91 + buildFolder,
92 + useYarn
93 + );
94 + },
95 + err => {
96 + console.log(chalk.red('Failed to compile.\n'));
97 + printBuildError(err);
98 + process.exit(1);
99 + }
100 + );
101 +
102 +// Create the production build and print the deployment instructions.
103 +function build(previousFileSizes) {
104 + console.log('Creating an optimized production build...');
105 +
106 + let compiler = webpack(config);
107 + return new Promise((resolve, reject) => {
108 + compiler.run((err, stats) => {
109 + if (err) {
110 + return reject(err);
111 + }
112 + const messages = formatWebpackMessages(stats.toJson({}, true));
113 + if (messages.errors.length) {
114 + // Only keep the first error. Others are often indicative
115 + // of the same problem, but confuse the reader with noise.
116 + if (messages.errors.length > 1) {
117 + messages.errors.length = 1;
118 + }
119 + return reject(new Error(messages.errors.join('\n\n')));
120 + }
121 + if (
122 + process.env.CI &&
123 + (typeof process.env.CI !== 'string' ||
124 + process.env.CI.toLowerCase() !== 'false') &&
125 + messages.warnings.length
126 + ) {
127 + console.log(
128 + chalk.yellow(
129 + '\nTreating warnings as errors because process.env.CI = true.\n' +
130 + 'Most CI servers set it automatically.\n'
131 + )
132 + );
133 + return reject(new Error(messages.warnings.join('\n\n')));
134 + }
135 + return resolve({
136 + stats,
137 + previousFileSizes,
138 + warnings: messages.warnings,
139 + });
140 + });
141 + });
142 +}
143 +
144 +function copyPublicFolder() {
145 + fs.copySync(paths.appPublic, paths.appBuild, {
146 + dereference: true,
147 + filter: file => file !== paths.appHtml,
148 + });
149 +}
1 +'use strict';
2 +
3 +// Do this as the first thing so that any code reading it knows the right env.
4 +process.env.BABEL_ENV = 'development';
5 +process.env.NODE_ENV = 'development';
6 +
7 +// Makes the script crash on unhandled rejections instead of silently
8 +// ignoring them. In the future, promise rejections that are not handled will
9 +// terminate the Node.js process with a non-zero exit code.
10 +process.on('unhandledRejection', err => {
11 + throw err;
12 +});
13 +
14 +// Ensure environment variables are read.
15 +require('../config/env');
16 +
17 +const fs = require('fs');
18 +const chalk = require('chalk');
19 +const webpack = require('webpack');
20 +const WebpackDevServer = require('webpack-dev-server');
21 +const clearConsole = require('react-dev-utils/clearConsole');
22 +const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
23 +const {
24 + choosePort,
25 + createCompiler,
26 + prepareProxy,
27 + prepareUrls,
28 +} = require('react-dev-utils/WebpackDevServerUtils');
29 +const openBrowser = require('react-dev-utils/openBrowser');
30 +const paths = require('../config/paths');
31 +const config = require('../config/webpack.config.dev');
32 +const createDevServerConfig = require('../config/webpackDevServer.config');
33 +
34 +const useYarn = fs.existsSync(paths.yarnLockFile);
35 +const isInteractive = process.stdout.isTTY;
36 +
37 +// Warn and crash if required files are missing
38 +if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
39 + process.exit(1);
40 +}
41 +
42 +// Tools like Cloud9 rely on this.
43 +const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
44 +const HOST = process.env.HOST || '0.0.0.0';
45 +
46 +if (process.env.HOST) {
47 + console.log(
48 + chalk.cyan(
49 + `Attempting to bind to HOST environment variable: ${chalk.yellow(
50 + chalk.bold(process.env.HOST)
51 + )}`
52 + )
53 + );
54 + console.log(
55 + `If this was unintentional, check that you haven't mistakenly set it in your shell.`
56 + );
57 + console.log(`Learn more here: ${chalk.yellow('http://bit.ly/2mwWSwH')}`);
58 + console.log();
59 +}
60 +
61 +// We attempt to use the default port but if it is busy, we offer the user to
62 +// run on a different port. `choosePort()` Promise resolves to the next free port.
63 +choosePort(HOST, DEFAULT_PORT)
64 + .then(port => {
65 + if (port == null) {
66 + // We have not found a port.
67 + return;
68 + }
69 + const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
70 + const appName = require(paths.appPackageJson).name;
71 + const urls = prepareUrls(protocol, HOST, port);
72 + // Create a webpack compiler that is configured with custom messages.
73 + const compiler = createCompiler(webpack, config, appName, urls, useYarn);
74 + // Load proxy config
75 + const proxySetting = require(paths.appPackageJson).proxy;
76 + const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
77 + // Serve webpack assets generated by the compiler over a web sever.
78 + const serverConfig = createDevServerConfig(
79 + proxyConfig,
80 + urls.lanUrlForConfig
81 + );
82 + const devServer = new WebpackDevServer(compiler, serverConfig);
83 + // Launch WebpackDevServer.
84 + devServer.listen(port, HOST, err => {
85 + if (err) {
86 + return console.log(err);
87 + }
88 + if (isInteractive) {
89 + clearConsole();
90 + }
91 + console.log(chalk.cyan('Starting the development server...\n'));
92 + });
93 +
94 + ['SIGINT', 'SIGTERM'].forEach(function(sig) {
95 + process.on(sig, function() {
96 + devServer.close();
97 + process.exit();
98 + });
99 + });
100 + })
101 + .catch(err => {
102 + if (err && err.message) {
103 + console.log(err.message);
104 + }
105 + process.exit(1);
106 + });
1 +'use strict';
2 +
3 +// Do this as the first thing so that any code reading it knows the right env.
4 +process.env.BABEL_ENV = 'test';
5 +process.env.NODE_ENV = 'test';
6 +process.env.PUBLIC_URL = '';
7 +
8 +// Makes the script crash on unhandled rejections instead of silently
9 +// ignoring them. In the future, promise rejections that are not handled will
10 +// terminate the Node.js process with a non-zero exit code.
11 +process.on('unhandledRejection', err => {
12 + throw err;
13 +});
14 +
15 +// Ensure environment variables are read.
16 +require('../config/env');
17 +
18 +const jest = require('jest');
19 +let argv = process.argv.slice(2);
20 +
21 +// Watch unless on CI, in coverage mode, or explicitly running all tests
22 +if (
23 + !process.env.CI &&
24 + argv.indexOf('--coverage') === -1 &&
25 + argv.indexOf('--watchAll') === -1
26 +) {
27 + argv.push('--watch');
28 +}
29 +
30 +
31 +jest.run(argv);
1 +import * as React from "react";
2 +import { Switch, Route, Link } from "react-router-dom";
3 +import Main from "components/gadgets/Main";
4 +import Nav from "components/gadgets/Nav";
5 +
6 +class App extends React.Component {
7 + public render() {
8 + return (
9 + <div>
10 + <Nav />
11 + <Main />
12 + </div>
13 + );
14 + }
15 +}
16 +
17 +export default App;
1 +import Component from './Component'
2 +
3 +export default Component
...\ No newline at end of file ...\ No newline at end of file
1 +import * as React from "react";
2 +import { Switch, Route } from "react-router-dom";
3 +import RequestPage from "components/pages/RequestPage";
4 +import DronePage from "components/pages/DronePage";
5 +import HomePage from "components/pages/HomePage";
6 +import RegisterPage from "components/pages/RegisterPage";
7 +import MyPage from "components/pages/MyPage";
8 +import ContractPage from "components/pages/ContractPage";
9 +import LoginPage from "components/pages/LoginPage";
10 +import OrgPage from "components/pages/OrgPage";
11 +import BuyPage from "components/pages/BuyPage";
12 +import DatasetPage from "components/pages/DatasetPage";
13 +import SearchPage from "components/pages/SearchPage";
14 +import JudgePage from "components/pages/JudgePage";
15 +import { withRouter, RouteComponentProps } from "react-router-dom";
16 +
17 +
18 +require("./styles.scss");
19 +
20 +interface MyProps extends RouteComponentProps<{}> {}
21 +
22 +class Main extends React.Component<MyProps> {
23 + componentDidUpdate(prevProps) {
24 + if (this.props.location !== prevProps.location) window.scrollTo(0, 0);
25 + }
26 +
27 + public render() {
28 + return (
29 + <main className="Main">
30 + <Switch>
31 + <Route exact path="/" component={HomePage} />
32 + <Route exact path="/request" component={RequestPage} />
33 + <Route exact path="/drone" component={DronePage} />
34 + <Route exact path="/register" component={RegisterPage} />
35 + <Route exact path="/my-page" component={MyPage} />
36 + <Route exact path="/contract/:id" component={ContractPage} />
37 + <Route exact path="/org" component={OrgPage} />
38 + <Route exact path="/buy" component={BuyPage} />
39 + <Route exact path="/judge/:id" component={JudgePage} />
40 + <Route exact path="/search/:id" component={SearchPage} />
41 + <Route exact path="/dataset" component={DatasetPage} />
42 + <Route exact path="/login" component={LoginPage} />
43 + </Switch>
44 + </main>
45 + );
46 + }
47 +}
48 +
49 +export default withRouter(Main);
1 +.Main {
2 + padding: 30px;
3 + margin: 200px auto 0 auto;
4 + width: 1280px;
5 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import * as React from "react";
2 +import { NavLink, Link } from "react-router-dom";
3 +require("./styles.scss");
4 +
5 +const activeStyle = {
6 + textDecoration: "underline"
7 +};
8 +
9 +const Nav: React.SFC<{}> = () => (
10 + <div className="nav">
11 + <ul>
12 + <li>
13 + <NavLink exact to="/" activeStyle={activeStyle}>
14 + <p>홈</p>
15 + </NavLink>
16 + </li>
17 + <li>
18 + <NavLink exact to="/my-page" activeStyle={activeStyle}>
19 + <p>내페이지</p>
20 + </NavLink>
21 + </li>
22 + </ul>
23 + <ul>
24 + <li>
25 + <NavLink exact to="/drone" activeStyle={activeStyle}>
26 + <p>드론등록</p>
27 + </NavLink>
28 + </li>
29 + <li>
30 + <NavLink exact to="/request" activeStyle={activeStyle}>
31 + <p>허가신청</p>
32 + </NavLink>
33 + </li>
34 + </ul>
35 + <ul>
36 + <li>
37 + <NavLink exact to="/dataset" activeStyle={activeStyle}>
38 + <p>데이터등록</p>
39 + </NavLink>
40 + </li>
41 + <li>
42 + <NavLink exact to="/buy" activeStyle={activeStyle}>
43 + <p>데이터구매</p>
44 + </NavLink>
45 + </li>
46 + </ul>
47 + <ul>
48 + <li>
49 + <NavLink exact to="/login" activeStyle={activeStyle}>
50 + <p>로그인</p>
51 + </NavLink>
52 + </li>
53 + <li>
54 + <NavLink exact to="/register" activeStyle={activeStyle}>
55 + <p>가입</p>
56 + </NavLink>
57 + </li>
58 + <li>
59 + <button onClick={() => localStorage.clear()}>로그아웃</button>
60 + </li>
61 + </ul>
62 + </div>
63 +);
64 +
65 +export default Nav;
1 +.nav {
2 + padding: 1rem;
3 + z-index: 2;
4 + position: fixed;
5 + height: 3rem;
6 + background-color: white;
7 + top: 0;
8 + left: 0;
9 + right: 0;
10 + ul {
11 + margin: 0;
12 + display: flex;
13 + li {
14 + margin-left: 10px;
15 + }
16 + }
17 +}
1 +import * as React from "react";
2 +import { Link } from "react-router-dom";
3 +import TextField from "material-ui/TextField";
4 +import RaisedButton from "material-ui/RaisedButton";
5 +import DatePicker from "material-ui/DatePicker";
6 +import Toggle from "material-ui/Toggle";
7 +import MenuItem from "material-ui/MenuItem";
8 +import DropDownMenu from "material-ui/DropDownMenu";
9 +
10 +require("./styles.scss");
11 +
12 +const style = {
13 + width: "100%"
14 +};
15 +
16 +interface Props {
17 + datasets: Array<any>;
18 + buyDataset: Function;
19 +}
20 +
21 +class BuyPage extends React.Component<Props> {
22 + public render() {
23 + const { props } = this;
24 + const { datasets, buyDataset } = props;
25 + return (
26 + <div className="buy-page">
27 + <h2>데이터셋 구매</h2>
28 + <ul>
29 + {datasets.map(dataset => (
30 + <li key={dataset.id}>
31 + <h3>데이터</h3>
32 + <p>{dataset.comment}</p>
33 + <h3>촬영 기종</h3>
34 + <p>{dataset.producer.model.name}</p>
35 + <h3>소유자</h3>
36 + <p>{dataset.producer.owner.email}</p>
37 + <hr />
38 + <RaisedButton
39 + label="구매"
40 + onClick={() => buyDataset(dataset.id)}
41 + />
42 + </li>
43 + ))}
44 + </ul>
45 + </div>
46 + );
47 + }
48 +}
49 +
50 +export default BuyPage;
1 +mutation buyDataset($id: ID!) {
2 + dataset: buyDataset(id: $id) {
3 + id
4 + }
5 +}
1 +query FetchAllDatasets {
2 + datasets: fetchAllDatasets {
3 + id
4 + comment
5 + producer {
6 + id
7 + name
8 + model {
9 + id
10 + name
11 + }
12 + owner {
13 + id
14 + email
15 + }
16 + }
17 + }
18 +}
1 +import Component from "./Component";
2 +import * as React from "react";
3 +import { Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +
6 +const FETCH_ALL_DATASETS = require("./fetchAllDatasets.gql");
7 +const BUY_DATASET = require("./buyDataset.gql");
8 +
9 +class FetchAllDatasetsQuery extends Query<{
10 + datasets: any;
11 +}> {}
12 +
13 +class CreateContractMutation extends Mutation<{}> {}
14 +
15 +const update = (history: any) => (cache, result) => history.push("/buy");
16 +
17 +const QueryComponent: React.SFC<RouteComponentProps<{}>> = ({ history }) => (
18 + <FetchAllDatasetsQuery query={FETCH_ALL_DATASETS} fetchPolicy="network-only">
19 + {({ loading, error, data }) => {
20 + if (loading) return <p>Loading...</p>;
21 + else if (error) return <p>Error :(</p>;
22 + else
23 + return (
24 + <CreateContractMutation
25 + mutation={BUY_DATASET}
26 + update={update(history)}
27 + >
28 + {mutate => {
29 + const buyDataset = id => mutate({ variables: { id } });
30 + return (
31 + <Component datasets={data!.datasets} buyDataset={buyDataset} />
32 + );
33 + }}
34 + </CreateContractMutation>
35 + );
36 + }}
37 + </FetchAllDatasetsQuery>
38 +);
39 +
40 +export default QueryComponent;
1 +.request-page {
2 + width: 300px;
3 +}
1 +import * as React from "react";
2 +import { Link } from "react-router-dom";
3 +import styled from "styled-components";
4 +import TextField from "material-ui/TextField";
5 +import RaisedButton from "material-ui/RaisedButton";
6 +
7 +require("./styles.scss");
8 +
9 +const style = {
10 + width: "100%"
11 +};
12 +
13 +interface Props {
14 + contract: any;
15 +}
16 +
17 +const statusLog = (status, review) => {
18 + if (status === "wait") return "심사중";
19 + else if (status === "ok") return "승인";
20 + else return `반려사유: ${review}`;
21 +};
22 +
23 +class ContractPage extends React.Component<Props> {
24 + public render() {
25 + const { props } = this;
26 + const { contract } = props;
27 + return (
28 + <div className="contract-page">
29 + <h2>허가서</h2>
30 + <h3>날짜</h3>
31 + <p>{contract.date}</p>
32 + <h3>지역</h3>
33 + <p>{contract.area}</p>
34 + <h3>상세주소</h3>
35 + <p>{contract.address}</p>
36 + <h3>사유</h3>
37 + <p>{contract.reason}</p>
38 + <h3>신청 상태</h3>
39 + <p>{statusLog(contract.status, contract.review)}</p>
40 + </div>
41 + );
42 + }
43 +}
44 +
45 +export default ContractPage;
1 +query FetchContract($id: ID!) {
2 + contract: fetchContract(id: $id) {
3 + id
4 + reason
5 + date
6 + area
7 + address
8 + status
9 + review
10 + }
11 +}
1 +import Component from "./Component";
2 +import * as React from "react";
3 +import { graphql, Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +
6 +const FETCH_CONTRACT = require("./fetchContract.gql");
7 +
8 +interface Props {
9 + contract: any;
10 +}
11 +
12 +class FetchContractQuery extends Query<Props> {}
13 +
14 +const QueryComponent: React.SFC<RouteComponentProps<{}>> = props => (
15 + <FetchContractQuery
16 + query={FETCH_CONTRACT}
17 + fetchPolicy="network-only"
18 + variables={{ id: props.match.params["id"] }}
19 + >
20 + {({ loading, error, data }) => {
21 + if (loading) return <p>Loading...</p>;
22 + else if (error || !data!.contract) return <p>Error :(</p>;
23 + else return <Component contract={data!.contract} />;
24 + }}
25 + </FetchContractQuery>
26 +);
27 +
28 +export default withRouter(QueryComponent);
1 +.register-page {
2 + width: 300px;
3 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import * as React from "react";
2 +import { Link } from "react-router-dom";
3 +import TextField from "material-ui/TextField";
4 +import RaisedButton from "material-ui/RaisedButton";
5 +import DatePicker from "material-ui/DatePicker";
6 +import Toggle from "material-ui/Toggle";
7 +import MenuItem from "material-ui/MenuItem";
8 +import DropDownMenu from "material-ui/DropDownMenu";
9 +
10 +require("./styles.scss");
11 +
12 +const style = {
13 + width: "100%"
14 +};
15 +
16 +interface Props {
17 + user: any;
18 + createDataset(input: any): void;
19 +}
20 +
21 +interface State {
22 + comment: string;
23 + droneId: string;
24 +}
25 +
26 +class RequestPage extends React.Component<Props, State> {
27 + state = {
28 + comment: "",
29 + droneId: ""
30 + };
31 +
32 + handleChangeComment = event => this.setState({ comment: event.target.value });
33 + handleChangeDrone = (event, index, droneId) => this.setState({ droneId });
34 +
35 + public render() {
36 + const { props, state } = this;
37 + const minDate = new Date();
38 + const maxDate = new Date();
39 + maxDate.setDate(maxDate.getDate() + 90);
40 + const { createDataset } = props;
41 +
42 + return (
43 + <div className="dataset-page">
44 + <h2>데이터셋 등록</h2>
45 + <TextField
46 + hintText="설명"
47 + type="text"
48 + value={state.comment}
49 + onChange={this.handleChangeComment}
50 + style={style}
51 + />
52 + <h3>파일</h3>
53 + <input type="file" />
54 + <h3>촬영한 드론</h3>
55 + <DropDownMenu
56 + maxHeight={300}
57 + value={state.droneId}
58 + onChange={this.handleChangeDrone}
59 + >
60 + {props.user.drones.map(drone => (
61 + <MenuItem
62 + key={drone.id}
63 + value={drone.id}
64 + primaryText={`${drone.name} (${drone.model.name})`}
65 + />
66 + ))}
67 + </DropDownMenu>
68 + <RaisedButton
69 + label="확인"
70 + primary={true}
71 + onClick={() => createDataset(state)}
72 + />
73 + </div>
74 + );
75 + }
76 +}
77 +
78 +export default RequestPage;
1 +mutation CreateDatase($input: DatasetInput!) {
2 + dataset: createDataset(input: $input) {
3 + id
4 + }
5 +}
1 +query FetchCurrentUser {
2 + user: fetchCurrentUser {
3 + id
4 + drones {
5 + id
6 + date
7 + name
8 + model {
9 + id
10 + name
11 + }
12 + owner {
13 + id
14 + email
15 + }
16 + }
17 + }
18 +}
1 +import Component from "./Component";
2 +import * as React from "react";
3 +import { Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +
6 +const FETCH_CURRENT_USER = require("./fetchCurrentUser.gql");
7 +const CREATE_DATASET = require("./createDataset.gql");
8 +
9 +class FetchCurrentUserQuery extends Query<{
10 + user: any;
11 + orgs: any;
12 +}> {}
13 +
14 +class CreateContractMutation extends Mutation<{}> {}
15 +
16 +const update = (history: any) => (cache, result) => history.push("/my-page");
17 +
18 +const QueryComponent: React.SFC<RouteComponentProps<{}>> = ({ history }) => (
19 + <FetchCurrentUserQuery query={FETCH_CURRENT_USER} fetchPolicy="network-only">
20 + {({ loading, error, data }) => {
21 + if (loading) return <p>Loading...</p>;
22 + else if (error) return <p>Error :(</p>;
23 + else
24 + return (
25 + <CreateContractMutation
26 + mutation={CREATE_DATASET}
27 + update={update(history)}
28 + >
29 + {mutate => {
30 + const createDataset = input => mutate({ variables: { input } });
31 + return (
32 + <Component user={data!.user} createDataset={createDataset} />
33 + );
34 + }}
35 + </CreateContractMutation>
36 + );
37 + }}
38 + </FetchCurrentUserQuery>
39 +);
40 +
41 +export default withRouter(QueryComponent);
1 +.request-page {
2 + width: 300px;
3 +}
1 +import * as R from "ramda";
2 +import * as React from "react";
3 +import { Link } from "react-router-dom";
4 +import DropDownMenu from "material-ui/DropDownMenu";
5 +import MenuItem from "material-ui/MenuItem";
6 +import TextField from "material-ui/TextField";
7 +import RaisedButton from "material-ui/RaisedButton";
8 +
9 +require("./styles.scss");
10 +
11 +interface State {
12 + modelId: string;
13 + name: string;
14 +}
15 +
16 +interface Props {
17 + models: Array<any>;
18 + registerDrone(input: any): void;
19 +}
20 +
21 +const style = {
22 + width: "100%"
23 +};
24 +
25 +class DronePage extends React.Component<Props, State> {
26 + state = {
27 + modelId: "",
28 + name: ""
29 + };
30 +
31 + handleChangeModel = (event, index, modelId) => this.setState({ modelId });
32 + handleChangeName = event => this.setState({ name: event.target.value });
33 +
34 + public render() {
35 + const { props, state } = this;
36 + return (
37 + <div className="drone-page">
38 + <h2>드론등록</h2>
39 + <TextField
40 + hintText="이름"
41 + type="text"
42 + value={state.name}
43 + onChange={this.handleChangeName}
44 + style={style}
45 + />
46 + <h3>모델</h3>
47 + <DropDownMenu
48 + maxHeight={300}
49 + value={state.modelId}
50 + onChange={this.handleChangeModel}
51 + >
52 + {props.models.map(model => (
53 + <MenuItem
54 + key={model.id}
55 + value={model.id}
56 + primaryText={`${model.name}`}
57 + />
58 + ))}
59 + </DropDownMenu>
60 + <RaisedButton
61 + label="등록하기"
62 + primary={true}
63 + style={style}
64 + onClick={() => props.registerDrone(state)}
65 + />
66 + </div>
67 + );
68 + }
69 +}
70 +
71 +export default DronePage;
1 +query FetchAllModels {
2 + models: fetchAllModels {
3 + id
4 + name
5 + }
6 +}
1 +import Component from "./Component";
2 +import * as React from "react";
3 +import { Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +
6 +const FETCH_ALL_MODELS = require("./fetchAllModels.gql");
7 +const REGISTER_DRONE = require("./registerDrone.gql");
8 +
9 +class FetchAllModelsQuery extends Query<{
10 + models: Array<any>;
11 +}> {}
12 +
13 +class RegisterDroneMutation extends Mutation<{}> {}
14 +
15 +const update = (history: any) => (cache, result) => history.push("/my-page");
16 +
17 +const QueryComponent: React.SFC<RouteComponentProps<{}>> = ({ history }) => (
18 + <FetchAllModelsQuery query={FETCH_ALL_MODELS}>
19 + {({ loading, error, data }) => {
20 + if (loading) return <p>Loading...</p>;
21 + else if (error) return <p>Error :(</p>;
22 + else
23 + return (
24 + <RegisterDroneMutation
25 + mutation={REGISTER_DRONE}
26 + update={update(history)}
27 + >
28 + {mutate => {
29 + const registerDrone = input => mutate({ variables: { input } });
30 + return (
31 + <Component
32 + models={data!.models}
33 + registerDrone={registerDrone}
34 + />
35 + );
36 + }}
37 + </RegisterDroneMutation>
38 + );
39 + }}
40 + </FetchAllModelsQuery>
41 +);
42 +
43 +export default withRouter(QueryComponent);
1 +mutation RegisterDrone($input: DroneInput!) {
2 + drone: registerDrone(input: $input) {
3 + id
4 + name
5 + date
6 + model {
7 + id
8 + name
9 + }
10 + }
11 +}
...\ No newline at end of file ...\ No newline at end of file
1 +.drone-page {
2 + width: 300px;
3 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import * as R from "ramda";
2 +import * as React from "react";
3 +
4 +require("./styles.scss");
5 +
6 +class HomePage extends React.Component<{}> {
7 + public render() {
8 + const { props, state } = this;
9 + return (
10 + <div className="home-page">
11 + <h1>1조 과제 시연</h1>
12 + </div>
13 + );
14 + }
15 +}
16 +
17 +export default HomePage;
1 +.home-page {
2 + width: 300px;
3 +}
1 +import * as React from "react";
2 +import { Link } from "react-router-dom";
3 +import styled from "styled-components";
4 +import TextField from "material-ui/TextField";
5 +import RaisedButton from "material-ui/RaisedButton";
6 +
7 +require("./styles.scss");
8 +
9 +const style = {
10 + // width: "100%"
11 +};
12 +
13 +interface Props {
14 + org: any;
15 + confirm: Function;
16 + reject: Function;
17 +}
18 +
19 +class Tester extends React.Component<any> {
20 + state = { review: "" };
21 + handleChangeReview = event => this.setState({ review: event.target.value });
22 + public render() {
23 + const { props, state } = this;
24 + const { id, confirm, reject } = props;
25 + return (
26 + <div>
27 + <RaisedButton
28 + label="승인"
29 + primary={true}
30 + style={style}
31 + onClick={() => confirm(id, state.review)}
32 + />
33 + <hr />
34 + <TextField
35 + hintText="사유"
36 + type="text"
37 + value={state.review}
38 + onChange={this.handleChangeReview}
39 + style={style}
40 + />
41 + <RaisedButton
42 + label="반려"
43 + primary={true}
44 + style={style}
45 + onClick={() => reject(id, state.review)}
46 + />
47 + </div>
48 + );
49 + }
50 +}
51 +
52 +class JudgePage extends React.Component<Props> {
53 + public render() {
54 + const { props, state } = this;
55 + const { org } = props;
56 + return (
57 + <div className="judge-page">
58 + <h2>신청서</h2>
59 + <ul>
60 + {org.contracts
61 + .filter(contract => contract.status === "wait")
62 + .map(contract => (
63 + <li key={contract.id}>
64 + <h3>사유</h3>
65 + <p>{contract.reason}</p>
66 + <h3>주소</h3>
67 + <p>{contract.address}</p>
68 + <h3>드론</h3>
69 + <p>
70 + {contract.drone.name}({contract.drone.model.name})
71 + </p>
72 + <Tester
73 + id={contract.id}
74 + confirm={props.confirm}
75 + reject={props.reject}
76 + />
77 + <br />
78 + </li>
79 + ))}
80 + </ul>
81 + </div>
82 + );
83 + }
84 +}
85 +
86 +export default JudgePage;
1 +query FetchOrg($id: ID!) {
2 + org: fetchOrg(id: $id) {
3 + id
4 + name
5 + contracts {
6 + id
7 + reason
8 + address
9 + status
10 + drone {
11 + id
12 + name
13 + model {
14 + id
15 + name
16 + }
17 + }
18 + }
19 + }
20 +}
1 +import Component from "./Component";
2 +import * as React from "react";
3 +import { graphql, Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +
6 +const FETCH_ORG = require("./fetchOrg.gql");
7 +const JUDGE_CONTRACT = require("./judgeContract.gql");
8 +
9 +interface Props {
10 + org: any;
11 +}
12 +
13 +class FetchContractQuery extends Query<Props> {}
14 +class JudgeContractMutation extends Mutation<{}> {}
15 +
16 +const update = (history: any) => (cache, result) => history.push('/org');
17 +
18 +const QueryComponent: React.SFC<RouteComponentProps<{}> & Props> = props => (
19 + <FetchContractQuery
20 + query={FETCH_ORG}
21 + fetchPolicy="network-only"
22 + variables={{ id: props.match.params["id"] }}
23 + >
24 + {({ loading, error, data }) => {
25 + if (loading) return <p>Loading...</p>;
26 + else if (error || !data!.org) return <p>Error :(</p>;
27 + else
28 + return (
29 + <JudgeContractMutation
30 + mutation={JUDGE_CONTRACT}
31 + update={update(history)}
32 + >
33 + {mutate => {
34 + const confirm = (id, review) => {
35 + mutate({ variables: { id, ok: true, review } });
36 + props.history.push('/org');
37 + }
38 + const reject = (id, review) => {
39 + mutate({ variables: { id, ok: false, review } });
40 + props.history.push('/org');
41 + }
42 + return (
43 + <Component org={data!.org} confirm={confirm} reject={reject} />
44 + );
45 + }}
46 + </JudgeContractMutation>
47 + );
48 + }}
49 + </FetchContractQuery>
50 +);
51 +
52 +export default withRouter(QueryComponent);
1 +mutation JudgeContract($id: ID!, $ok: Boolean!, $review: String!) {
2 + contract: judgeContract(id: $id, ok: $ok, review: $review) {
3 + id
4 + }
5 +}
1 +.register-page {
2 + width: 300px;
3 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import * as R from "ramda";
2 +import * as React from "react";
3 +import TextField from "material-ui/TextField";
4 +import RaisedButton from "material-ui/RaisedButton";
5 +import { History } from "history";
6 +
7 +require("./styles.scss");
8 +
9 +interface Props {
10 + login: (input) => void;
11 + history: History;
12 +}
13 +
14 +const style = {
15 + width: "100%"
16 +};
17 +
18 +class LoginPage extends React.Component<Props> {
19 + state = {
20 + // email: "",
21 + // password: ""
22 + email: "db@khu.ac.kr",
23 + password: "db"
24 + };
25 +
26 + handleChangeEmail = event => this.setState({ email: event.target.value });
27 + handleChangePassword = event =>
28 + this.setState({ password: event.target.value });
29 +
30 + public render() {
31 + const { props, state } = this;
32 + return (
33 + <div className="login-page">
34 + <form>
35 + <h2>로그인</h2>
36 + <TextField
37 + hintText="email"
38 + type="email"
39 + value={state.email}
40 + onChange={this.handleChangeEmail}
41 + style={style}
42 + />
43 + <TextField
44 + hintText="password"
45 + type="password"
46 + value={state.password}
47 + onChange={this.handleChangePassword}
48 + style={style}
49 + />
50 + <RaisedButton
51 + label="로그인"
52 + style={style}
53 + onClick={() => props.login(state)}
54 + />
55 + {/*
56 + <RaisedButton
57 + label="회원가입"
58 + primary={true}
59 + style={style}
60 + onClick={() => props.history.push("register")}
61 + /> */}
62 + </form>
63 + </div>
64 + );
65 + }
66 +}
67 +
68 +export default LoginPage;
1 +import * as React from "react";
2 +import Component from "./Component";
3 +import { Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +import * as R from "ramda";
6 +import { History } from "history";
7 +
8 +const LOGIN = require("./login.gql");
9 +
10 +class LoginMutation extends Mutation<{}> {}
11 +
12 +interface Variables {
13 + input: {
14 + email: string;
15 + password: string;
16 + };
17 +}
18 +
19 +const update = (history: History) => (cache, { data }) => {
20 + const { login } = data;
21 + if (R.isNil(login)) {
22 + alert("로그인 실패");
23 + } else {
24 + localStorage.setItem("token", login.token);
25 + history.push("/");
26 + }
27 +};
28 +
29 +const MutationComponent: React.SFC<RouteComponentProps<Variables>> = ({
30 + match,
31 + history
32 +}) => (
33 + <LoginMutation mutation={LOGIN} update={update(history)}>
34 + {mutate => {
35 + const login = input => mutate({ variables: { input } });
36 + return <Component login={login} history={history} />;
37 + }}
38 + </LoginMutation>
39 +);
40 +
41 +export default withRouter(MutationComponent);
1 +mutation Login($input: UserInput!) {
2 + login: login(input: $input) {
3 + user {
4 + id
5 + }
6 + token
7 + }
8 +}
1 +.login-page {
2 + width: 300px;
3 +}
1 +import * as React from "react";
2 +import { Link } from "react-router-dom";
3 +import { List, ListItem } from "material-ui/List";
4 +import Avatar from "material-ui/Avatar";
5 +
6 +require("./styles.scss");
7 +
8 +interface Props {
9 + user: any;
10 + history: any;
11 +}
12 +
13 +class UserPage extends React.Component<Props> {
14 + public render() {
15 + const { user, history } = this.props;
16 + console.log(this.props);
17 + return (
18 + <div className="my-page">
19 + <h2>내 페이지</h2>
20 + <h3>드론 목록</h3>
21 + <List>
22 + {user.drones.map(drone => (
23 + <ListItem
24 + key={drone.id}
25 + primaryText={`${drone.name} (${drone.model.name})`}
26 + leftAvatar={
27 + <Avatar src={`/assets/img/${drone.model.name}.jpg`} />
28 + }
29 + />
30 + ))}
31 + </List>
32 + <h3>허가서 목록</h3>
33 + <List>
34 + {user.contracts.map(contract => (
35 + <ListItem
36 + key={contract.id}
37 + primaryText={`${contract.reason} (${contract.drone.name})`}
38 + leftAvatar={
39 + <Avatar src={`/assets/img/${contract.drone.model.name}.jpg`} />
40 + }
41 + onClick={() => history.push(`/contract/${contract.id}`)}
42 + />
43 + ))}
44 + </List>
45 + <h3>구매한 데이터셋</h3>
46 + <ul>
47 + {user.datasets.map(dataset => (
48 + <li key={dataset.id}>
49 + <h4>데이터</h4>
50 + <p>{dataset.comment}</p>
51 + <h4>촬영한 드론</h4>
52 + <p>{dataset.producer.name}({dataset.producer.model.name})</p>
53 + </li>
54 + ))}
55 + </ul>
56 + </div>
57 + );
58 + }
59 +}
60 +
61 +export default UserPage;
1 +query FetchCurrentUser {
2 + user: fetchCurrentUser {
3 + id
4 + drones {
5 + id
6 + name
7 + date
8 + model {
9 + id
10 + name
11 + }
12 + }
13 + contracts {
14 + id
15 + reason
16 + date
17 + drone {
18 + id
19 + date
20 + name
21 + model {
22 + id
23 + name
24 + }
25 + }
26 + }
27 + datasets {
28 + id
29 + comment
30 + producer {
31 + id
32 + name
33 + model {
34 + id
35 + name
36 + }
37 + }
38 + }
39 + }
40 +}
1 +import * as React from "react";
2 +import Component from "./Component";
3 +import { graphql, Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +const FETCH_CURRENT_USER = require("./fetchCurrentUser.gql");
6 +
7 +interface Props {
8 + user: any;
9 +}
10 +
11 +class FetchUserPageQuery extends Query<Props> {}
12 +
13 +const QueryComponent: React.SFC<RouteComponentProps<{}>> = props => (
14 + <FetchUserPageQuery
15 + query={FETCH_CURRENT_USER} fetchPolicy="network-only">
16 + {({ loading, error, data }) => {
17 + if (loading) return <p>Loading...</p>;
18 + else if (error || !data!.user) return <p>Error :(</p>;
19 + else return <Component user={data!.user} history={props.history} />;
20 + }}
21 + </FetchUserPageQuery>
22 +);
23 +
24 +export default withRouter(QueryComponent);
1 +.my-page {
2 + width: 300px;
3 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import * as React from "react";
2 +import { Link } from "react-router-dom";
3 +import styled from "styled-components";
4 +import TextField from "material-ui/TextField";
5 +import RaisedButton from "material-ui/RaisedButton";
6 +
7 +require("./styles.scss");
8 +
9 +const style = {
10 + width: "100%"
11 +};
12 +
13 +interface Props {
14 + orgs: Array<any>;
15 +}
16 +
17 +class OrgPage extends React.Component<Props> {
18 + public render() {
19 + const { props } = this;
20 + const { orgs } = props;
21 + console.log(orgs, orgs.length);
22 + return (
23 + <div className="org-page">
24 + <h2>신청서 심사</h2>
25 + <ul>
26 + {orgs.map(org => (
27 + <li key={org.id}>
28 + <h3>{org.name}</h3>
29 + <p><Link to={`/judge/${org.id}`}>심사</Link></p>
30 + <p><Link to={`/search/${org.id}`}>질의</Link></p>
31 + </li>
32 + ))}
33 + </ul>
34 + </div>
35 + );
36 + }
37 +}
38 +
39 +export default OrgPage;
1 +query FetchAllOrgs {
2 + orgs: fetchAllOrgs {
3 + id
4 + name
5 + }
6 +}
1 +import Component from "./Component";
2 +import * as React from "react";
3 +import { graphql, Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +
6 +const FETCH_ALL_ORGS = require("./fetchAllOrgs.gql");
7 +
8 +interface Props {
9 + orgs: Array<any>;
10 +}
11 +
12 +class FetchContractQuery extends Query<Props> {}
13 +
14 +const QueryComponent: React.SFC<RouteComponentProps<{}>> = props => (
15 + <FetchContractQuery
16 + query={FETCH_ALL_ORGS}
17 + fetchPolicy="network-only"
18 + >
19 + {({ loading, error, data }) => {
20 + if (loading) return <p>Loading...</p>;
21 + else if (error || !data!.orgs) return <p>Error :(</p>;
22 + else return <Component orgs={data!.orgs} />;
23 + }}
24 + </FetchContractQuery>
25 +);
26 +
27 +export default withRouter(QueryComponent);
1 +.register-page {
2 + width: 300px;
3 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import * as React from "react";
2 +import { Link } from "react-router-dom";
3 +import styled from "styled-components";
4 +import TextField from "material-ui/TextField";
5 +import RaisedButton from "material-ui/RaisedButton";
6 +
7 +require("./styles.scss");
8 +
9 +interface UserInput {
10 + email: string;
11 + password: string;
12 +}
13 +
14 +const style = {
15 + width: "100%"
16 +};
17 +
18 +interface Props {
19 + createUser: (input: UserInput) => void;
20 +}
21 +
22 +class RegisterPage extends React.Component<Props> {
23 + state = {
24 + password: "",
25 + email: ""
26 + };
27 +
28 + handleChangeEmail = event => this.setState({ email: event.target.value });
29 + handleChangePassword = event =>
30 + this.setState({ password: event.target.value });
31 +
32 + public render() {
33 + const createUser = this.props.createUser;
34 + const { props, state } = this;
35 + return (
36 + <div className="register-page">
37 + <h2>가입하기</h2>
38 + <TextField
39 + hintText="email"
40 + type="email"
41 + value={state.email}
42 + onChange={this.handleChangeEmail}
43 + style={style}
44 + />
45 + <TextField
46 + hintText="password"
47 + type="password"
48 + value={state.password}
49 + onChange={this.handleChangePassword}
50 + style={style}
51 + />
52 + <RaisedButton
53 + label="확인"
54 + primary={true}
55 + style={style}
56 + onClick={() => createUser(state)}
57 + />
58 + </div>
59 + );
60 + }
61 +}
62 +
63 +export default RegisterPage;
1 +mutation createUser($input: UserInput!) {
2 + user: createUser(input: $input) {
3 + id
4 + email
5 + }
6 +}
1 +import Component from "./Component";
2 +import * as React from "react";
3 +import { graphql, Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +
6 +const CREATE_USER = require("./createUser.gql");
7 +
8 +class CreateUserMutation extends Mutation<{}> {}
9 +
10 +interface Variables {
11 + id: string;
12 +}
13 +
14 +const update = (history: any) => (cache, result) => history.push('/');
15 +
16 +const QueryComponent: React.SFC<RouteComponentProps<Variables>> = ({
17 + match,
18 + history
19 +}) => (
20 + <CreateUserMutation mutation={CREATE_USER} update={update(history)}>
21 + {mutate => {
22 + const createUser = input => mutate({ variables: { input } });
23 + return <Component createUser={createUser} />;
24 + }}
25 + </CreateUserMutation>
26 +);
27 +
28 +export default withRouter(QueryComponent);
1 +.register-page {
2 + width: 300px;
3 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import * as React from "react";
2 +import { Link } from "react-router-dom";
3 +import TextField from "material-ui/TextField";
4 +import RaisedButton from "material-ui/RaisedButton";
5 +import DatePicker from "material-ui/DatePicker";
6 +import Toggle from "material-ui/Toggle";
7 +import MenuItem from "material-ui/MenuItem";
8 +import DropDownMenu from "material-ui/DropDownMenu";
9 +
10 +require("./styles.scss");
11 +
12 +const style = {
13 + width: "100%"
14 +};
15 +
16 +interface Props {
17 + user: any;
18 + orgs: any;
19 + createContract(input: any): void;
20 +}
21 +
22 +interface State {
23 + reason: string;
24 + date: Date;
25 + droneId: string;
26 + area: string;
27 + address: string;
28 +}
29 +
30 +class RequestPage extends React.Component<Props, State> {
31 + state = {
32 + reason: "",
33 + date: new Date(),
34 + droneId: "",
35 + area: "지역",
36 + address: ""
37 + };
38 +
39 + handleChangeReason = event => this.setState({ reason: event.target.value });
40 + handleChangeDate = (event, date) => this.setState({ date });
41 + handleChangeDrone = (event, index, droneId) => this.setState({ droneId });
42 + handleChangeArea = (event, index, area) => this.setState({ area });
43 + handleChangeAddress = event => this.setState({ address: event.target.value });
44 +
45 + public render() {
46 + const { props, state } = this;
47 + const minDate = new Date();
48 + const maxDate = new Date();
49 + maxDate.setDate(maxDate.getDate() + 90);
50 +
51 + return (
52 + <div className="request-page">
53 + <h2>허가 신청서 작성</h2>
54 + <TextField
55 + hintText="사유"
56 + type="text"
57 + value={state.reason}
58 + onChange={this.handleChangeReason}
59 + style={style}
60 + />
61 + <DropDownMenu
62 + maxHeight={300}
63 + value={state.droneId}
64 + onChange={this.handleChangeDrone}
65 + >
66 + {props.user.drones.map(drone => (
67 + <MenuItem
68 + key={drone.id}
69 + value={drone.id}
70 + primaryText={`${drone.name} (${drone.model.name})`}
71 + />
72 + ))}
73 + </DropDownMenu>
74 + <DatePicker
75 + floatingLabelText="날짜"
76 + onChange={this.handleChangeDate}
77 + defaultDate={state.date}
78 + minDate={minDate}
79 + maxDate={maxDate}
80 + />
81 + <DropDownMenu
82 + maxHeight={300}
83 + value={state.area}
84 + onChange={this.handleChangeArea}
85 + >
86 + {props.orgs.map(org => (
87 + <MenuItem key={org.id} value={org.name} primaryText={org.name} />
88 + ))}
89 + </DropDownMenu>
90 + <TextField
91 + hintText="상세주소"
92 + type="text"
93 + value={state.address}
94 + onChange={this.handleChangeAddress}
95 + style={style}
96 + />
97 + <RaisedButton
98 + label="확인"
99 + primary={true}
100 + style={style}
101 + onClick={() => props.createContract(state)}
102 + />
103 + </div>
104 + );
105 + }
106 +}
107 +
108 +export default RequestPage;
1 +mutation CreateContract($input: ContractInput!) {
2 + contract: createContract(input: $input) {
3 + id
4 + }
5 +}
1 +query FetchCurrentUser {
2 + user: fetchCurrentUser {
3 + id
4 + drones {
5 + id
6 + date
7 + name
8 + model {
9 + id
10 + name
11 + }
12 + }
13 + }
14 +
15 + orgs: fetchAllOrgs {
16 + id
17 + name
18 + }
19 +}
1 +import Component from "./Component";
2 +import * as React from "react";
3 +import { Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +
6 +const FETCH_CURRENT_USER = require("./fetchCurrentUser.gql");
7 +const CREATE_CONTRACT = require("./createContract.gql");
8 +
9 +class FetchCurrentUserQuery extends Query<{
10 + user: any;
11 + orgs: any;
12 +}> {}
13 +
14 +class CreateContractMutation extends Mutation<{}> {}
15 +
16 +const update = (history: any) => (cache, result) => history.push("/my-page");
17 +
18 +const QueryComponent: React.SFC<RouteComponentProps<{}>> = ({ history }) => (
19 + <FetchCurrentUserQuery query={FETCH_CURRENT_USER} fetchPolicy="network-only">
20 + {({ loading, error, data }) => {
21 + if (loading) return <p>Loading...</p>;
22 + else if (error) return <p>Error :(</p>;
23 + else
24 + return (
25 + <CreateContractMutation
26 + mutation={CREATE_CONTRACT}
27 + update={update(history)}
28 + >
29 + {mutate => {
30 + const createContract = input => mutate({ variables: { input } });
31 + return (
32 + <Component user={data!.user} orgs={data!.orgs} createContract={createContract} />
33 + );
34 + }}
35 + </CreateContractMutation>
36 + );
37 + }}
38 + </FetchCurrentUserQuery>
39 +);
40 +
41 +export default withRouter(QueryComponent);
1 +.request-page {
2 + width: 300px;
3 +}
1 +import * as React from "react";
2 +import { Link } from "react-router-dom";
3 +import styled from "styled-components";
4 +import TextField from "material-ui/TextField";
5 +import RaisedButton from "material-ui/RaisedButton";
6 +
7 +require("./styles.scss");
8 +
9 +const style = {
10 + // width: "100%"
11 +};
12 +
13 +interface Props {
14 + org: any;
15 +}
16 +
17 +class SearchPage extends React.Component<Props> {
18 + public render() {
19 + const { props, state } = this;
20 + const { org } = props;
21 + return (
22 + <div className="judge-page">
23 + <h2>신청서</h2>
24 + <ul>
25 + {org.contracts
26 + .filter(contract => contract.status === "ok")
27 + .map(contract => (
28 + <li key={contract.id}>
29 + <h3>사유</h3>
30 + <p>{contract.reason}</p>
31 + <h3>주소</h3>
32 + <p>{contract.address}</p>
33 + <h3>드론</h3>
34 + <p>
35 + {contract.drone.name}({contract.drone.model.name})
36 + </p>
37 + <br />
38 + </li>
39 + ))}
40 + </ul>
41 + </div>
42 + );
43 + }
44 +}
45 +
46 +export default SearchPage;
1 +query FetchOrg($id: ID!) {
2 + org: fetchOrg(id: $id) {
3 + id
4 + name
5 + contracts {
6 + id
7 + reason
8 + address
9 + status
10 + drone {
11 + id
12 + name
13 + model {
14 + id
15 + name
16 + }
17 + }
18 + }
19 + }
20 +}
1 +import Component from "./Component";
2 +import * as React from "react";
3 +import { graphql, Query, Mutation } from "react-apollo";
4 +import { withRouter, RouteComponentProps } from "react-router";
5 +
6 +const FETCH_ORG = require("./fetchOrg.gql");
7 +
8 +interface Props {
9 + org: any;
10 +}
11 +
12 +class FetchContractQuery extends Query<Props> {}
13 +
14 +const update = (history: any) => (cache, result) => history.goBack();
15 +
16 +const QueryComponent: React.SFC<RouteComponentProps<{}> & Props> = props => (
17 + <FetchContractQuery
18 + query={FETCH_ORG}
19 + fetchPolicy="network-only"
20 + variables={{ id: props.match.params["id"] }}
21 + >
22 + {({ loading, error, data }) => {
23 + if (loading) return <p>Loading...</p>;
24 + else if (error || !data!.org) return <p>Error :(</p>;
25 + else return <Component org={data!.org} />;
26 + }}
27 + </FetchContractQuery>
28 +);
29 +
30 +export default withRouter(QueryComponent);
1 +mutation JudgeContract($id: ID!, $ok: Boolean!, $review: String!) {
2 + contract: judgeContract(id: $id, ok: $ok, review: $review) {
3 + id
4 + }
5 +}
1 +.register-page {
2 + width: 300px;
3 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import * as R from "ramda";
2 +import { ApolloLink } from "apollo-link";
3 +import { setContext } from "apollo-link-context";
4 +import { InMemoryCache } from "apollo-cache-inmemory";
5 +import { ApolloClient } from "apollo-client";
6 +import { createUploadLink } from "apollo-upload-client";
7 +
8 +const authLink = setContext((req, { headers }) => {
9 + const token = localStorage.getItem("token");
10 + const authorization = token ? `Bearer ${token}` : "";
11 + return { headers: R.merge(headers, { authorization }) };
12 +});
13 +const uploadLink = createUploadLink();
14 +
15 +const link = ApolloLink.from([authLink, uploadLink]);
16 +
17 +const cache = new InMemoryCache({
18 + cacheRedirects: {
19 + Query: {}
20 + }
21 +});
22 +
23 +const client = new ApolloClient({ link, cache });
24 +
25 +export default () => client;
1 +body {
2 + margin: 0;
3 + padding: 0;
4 + font-family: sans-serif;
5 +}
6 +
7 +ul {
8 + padding: 0;
9 +}
10 +
11 +li {
12 + list-style-type: none;
13 +}
14 +
15 +a {
16 + color: #258fb8;
17 + text-decoration: none;
18 + &:hover {
19 + text-decoration: underline;
20 + }
21 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import * as R from "ramda";
2 +import * as React from "react";
3 +import * as ReactDOM from "react-dom";
4 +
5 +import { BrowserRouter } from "react-router-dom";
6 +import { ApolloProvider } from "react-apollo";
7 +import { Provider } from "react-redux";
8 +import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";
9 +
10 +import App from "components/App";
11 +// import configureStore from "./configureStore";
12 +import configureClient from "./configureClient";
13 +
14 +import registerServiceWorker from "./registerServiceWorker";
15 +import "./index.scss";
16 +
17 +// const store = configureStore();
18 +const client = configureClient();
19 +
20 +const Root = () => (
21 + <ApolloProvider client={client}>
22 + <BrowserRouter>
23 + <MuiThemeProvider>
24 + <App />
25 + </MuiThemeProvider>
26 + </BrowserRouter>
27 + </ApolloProvider>
28 +);
29 +
30 +ReactDOM.render(<Root />, document.getElementById("root") as HTMLElement);
31 +
32 +registerServiceWorker();
1 +import { combineReducers } from 'redux'
2 +import { combineEpics } from 'redux-observable'
1 +// tslint:disable:no-console
2 +// In production, we register a service worker to serve assets from local cache.
3 +
4 +// This lets the app load faster on subsequent visits in production, and gives
5 +// it offline capabilities. However, it also means that developers (and users)
6 +// will only see deployed updates on the 'N+1' visit to a page, since previously
7 +// cached resources are updated in the background.
8 +
9 +// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
10 +// This link also includes instructions on opting out of this behavior.
11 +
12 +const isLocalhost = Boolean(
13 + window.location.hostname === 'localhost' ||
14 + // [::1] is the IPv6 localhost address.
15 + window.location.hostname === '[::1]' ||
16 + // 127.0.0.1/8 is considered localhost for IPv4.
17 + window.location.hostname.match(
18 + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
19 + )
20 +);
21 +
22 +export default function register() {
23 + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
24 + // The URL constructor is available in all browsers that support SW.
25 + const publicUrl = new URL(
26 + process.env.PUBLIC_URL!,
27 + window.location.toString()
28 + );
29 + if (publicUrl.origin !== window.location.origin) {
30 + // Our service worker won't work if PUBLIC_URL is on a different origin
31 + // from what our page is served on. This might happen if a CDN is used to
32 + // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
33 + return;
34 + }
35 +
36 + window.addEventListener('load', () => {
37 + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
38 +
39 + if (isLocalhost) {
40 + // This is running on localhost. Lets check if a service worker still exists or not.
41 + checkValidServiceWorker(swUrl);
42 +
43 + // Add some additional logging to localhost, pointing developers to the
44 + // service worker/PWA documentation.
45 + navigator.serviceWorker.ready.then(() => {
46 + console.log(
47 + 'This web app is being served cache-first by a service ' +
48 + 'worker. To learn more, visit https://goo.gl/SC7cgQ'
49 + );
50 + });
51 + } else {
52 + // Is not local host. Just register service worker
53 + registerValidSW(swUrl);
54 + }
55 + });
56 + }
57 +}
58 +
59 +function registerValidSW(swUrl: string) {
60 + navigator.serviceWorker
61 + .register(swUrl)
62 + .then(registration => {
63 + registration.onupdatefound = () => {
64 + const installingWorker = registration.installing;
65 + if (installingWorker) {
66 + installingWorker.onstatechange = () => {
67 + if (installingWorker.state === 'installed') {
68 + if (navigator.serviceWorker.controller) {
69 + // At this point, the old content will have been purged and
70 + // the fresh content will have been added to the cache.
71 + // It's the perfect time to display a 'New content is
72 + // available; please refresh.' message in your web app.
73 + console.log('New content is available; please refresh.');
74 + } else {
75 + // At this point, everything has been precached.
76 + // It's the perfect time to display a
77 + // 'Content is cached for offline use.' message.
78 + console.log('Content is cached for offline use.');
79 + }
80 + }
81 + };
82 + }
83 + };
84 + })
85 + .catch(error => {
86 + console.error('Error during service worker registration:', error);
87 + });
88 +}
89 +
90 +function checkValidServiceWorker(swUrl: string) {
91 + // Check if the service worker can be found. If it can't reload the page.
92 + fetch(swUrl)
93 + .then(response => {
94 + // Ensure service worker exists, and that we really are getting a JS file.
95 + if (
96 + response.status === 404 ||
97 + response.headers.get('content-type')!.indexOf('javascript') === -1
98 + ) {
99 + // No service worker found. Probably a different app. Reload the page.
100 + navigator.serviceWorker.ready.then(registration => {
101 + registration.unregister().then(() => {
102 + window.location.reload();
103 + });
104 + });
105 + } else {
106 + // Service worker found. Proceed as normal.
107 + registerValidSW(swUrl);
108 + }
109 + })
110 + .catch(() => {
111 + console.log(
112 + 'No internet connection found. App is running in offline mode.'
113 + );
114 + });
115 +}
116 +
117 +export function unregister() {
118 + if ('serviceWorker' in navigator) {
119 + navigator.serviceWorker.ready.then(registration => {
120 + registration.unregister();
121 + });
122 + }
123 +}
1 +{
2 + "compilerOptions": {
3 + "outDir": "build/dist",
4 + "module": "esnext",
5 + "target": "es5",
6 + "lib": [
7 + "es6",
8 + "dom",
9 + "esnext.asynciterable"
10 + ],
11 + "sourceMap": true,
12 + "allowJs": true,
13 + "jsx": "react",
14 + "moduleResolution": "node",
15 + "rootDir": "src",
16 + "forceConsistentCasingInFileNames": true,
17 + "noImplicitReturns": true,
18 + "noImplicitThis": true,
19 + "noImplicitAny": false,
20 + "strictNullChecks": true,
21 + "suppressImplicitAnyIndexErrors": true,
22 + "noUnusedLocals": false,
23 + "baseUrl": "./src"
24 + },
25 + "exclude": [
26 + "../node_modules",
27 + "build",
28 + "scripts",
29 + "acceptance-tests",
30 + "webpack",
31 + "jest",
32 + "src/setupTests.ts"
33 + ]
34 +}
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "extends": "./tsconfig.json",
3 + "compilerOptions": {
4 + "module": "commonjs"
5 + }
6 +}
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "extends": [],
3 + "linterOptions": {
4 + "exclude": [
5 + "config/**/*.js",
6 + "node_modules/**/*.ts"
7 + ]
8 + }
9 +}
...\ No newline at end of file ...\ No newline at end of file
1 +nodejs 10.4.1
2 +yarn 1.6.0
3 +oracle DB // username: "system", password: "oracle", database: "khu"로 로그인 할 수 있어야 하고 테이블이 없어야함(두 번째 실행시 configureDB.ts synchronize를 false로 주지 않으면 에러발생)
4 +
5 +front와 server에서 각각 yarn install을 입력해서 의존성을 받음
6 +완료시 각각 yarn start로 개발서버를 띄울 수 있음
7 +빌드가 잘 되지 않으면 node-sass, oracledb, typescript, babel, webpack을 yarn global add {패키지 이름}을 입력해서 전역으로 설치
8 +
9 +server를 먼저 띄우고 front를 띄우면 front의 package.json의 proxy를 참조해서 server에 연결됨(이 부분에서 문제가 발생하면 화면은 나오지만 통신을 못함)
10 +위와 같은 문제 발생시 front의 proxy를 localhost, 0.0.0.0, 진짜 IP등으로 바꿔가면서 실행
11 +
12 +모든 과정이 준비되면
13 +localhost:3000으로 접속해서 시연 가능
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const fs = require('fs');
4 +const path = require('path');
5 +const paths = require('./paths');
6 +
7 +delete require.cache[require.resolve('./paths')];
8 +
9 +const NODE_ENV = process.env.NODE_ENV;
10 +if (!NODE_ENV) {
11 + throw new Error(
12 + 'The NODE_ENV environment variable is required but was not specified.'
13 + );
14 +}
15 +
16 +var dotenvFiles = [
17 + `${paths.dotenv}.${NODE_ENV}.local`,
18 + `${paths.dotenv}.${NODE_ENV}`,
19 + NODE_ENV !== 'test' && `${paths.dotenv}.local`,
20 + paths.dotenv,
21 +].filter(Boolean);
22 +
23 +dotenvFiles.forEach(dotenvFile => {
24 + if (fs.existsSync(dotenvFile)) {
25 + require('dotenv-expand')(
26 + require('dotenv').config({
27 + path: dotenvFile,
28 + })
29 + );
30 + }
31 +});
32 +
33 +const appDirectory = fs.realpathSync(process.cwd());
34 +process.env.NODE_PATH = (process.env.NODE_PATH || '')
35 + .split(path.delimiter)
36 + .filter(folder => folder && !path.isAbsolute(folder))
37 + .map(folder => path.resolve(appDirectory, folder))
38 + .join(path.delimiter);
39 +
40 +const REACT_APP = /^REACT_APP_/i;
41 +
42 +function getClientEnvironment(publicUrl) {
43 + const raw = Object.keys(process.env)
44 + .filter(key => REACT_APP.test(key))
45 + .reduce(
46 + (env, key) => {
47 + env[key] = process.env[key];
48 + return env;
49 + },
50 + {
51 + NODE_ENV: process.env.NODE_ENV || 'development',
52 + PUBLIC_URL: publicUrl,
53 + }
54 + );
55 + const stringified = {
56 + 'process.env': Object.keys(raw).reduce((env, key) => {
57 + env[key] = JSON.stringify(raw[key]);
58 + return env;
59 + }, {}),
60 + };
61 +
62 + return { raw, stringified };
63 +}
64 +
65 +module.exports = getClientEnvironment;
1 +'use strict';
2 +
3 +const path = require('path');
4 +const fs = require('fs');
5 +const url = require('url');
6 +
7 +const appDirectory = fs.realpathSync(process.cwd());
8 +const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
9 +
10 +const envPublicUrl = process.env.PUBLIC_URL;
11 +
12 +function ensureSlash(path, needsSlash) {
13 + const hasSlash = path.endsWith('/');
14 + if (hasSlash && !needsSlash) {
15 + return path.substr(path, path.length - 1);
16 + } else if (!hasSlash && needsSlash) {
17 + return `${path}/`;
18 + } else {
19 + return path;
20 + }
21 +}
22 +
23 +const getPublicUrl = appPackageJson =>
24 + envPublicUrl || require(appPackageJson).homepage;
25 +
26 +function getServedPath(appPackageJson) {
27 + const publicUrl = getPublicUrl(appPackageJson);
28 + const servedUrl =
29 + envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');
30 + return ensureSlash(servedUrl, true);
31 +}
32 +
33 +module.exports = {
34 + appPackageJson: resolveApp('package.json'),
35 + appTsConfig: resolveApp('tsconfig.json'),
36 + appTsLint: resolveApp('tslint.json'),
37 +
38 + yarnLockFile: resolveApp('yarn.lock'),
39 + testsSetup: resolveApp('src/setupTests.js'),
40 + appNodeModules: resolveApp('node_modules'),
41 + publicUrl: getPublicUrl(resolveApp('package.json')),
42 + servedPath: getServedPath(resolveApp('package.json')),
43 +
44 + dotenv: resolveApp('.env'),
45 + serverAssets: resolveApp('assets'),
46 + appSrc: resolveApp('src'),
47 + appLib: resolveApp('lib'),
48 + appEntry: resolveApp('src/index.ts'),
49 + appBuild: resolveApp('../build/server'),
50 + temporalOutput: resolveApp('tmp'),
51 +};
1 +'use strict';
2 +
3 +const webpack = require('webpack');
4 +const paths = require('./paths');
5 +const nodeExternals = require('webpack-node-externals');
6 +const CopyWebpackPlugin = require('copy-webpack-plugin');
7 +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
8 +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
9 +
10 +module.exports = {
11 + devtool: 'cheap-module-source-map',
12 + target: 'node',
13 + entry: paths.appEntry,
14 + output: {
15 + path: paths.temporalOutput,
16 + filename: 'index.js'
17 + },
18 + externals: [nodeExternals()],
19 + resolve: {
20 + modules: [paths.appLib, paths.appSrc, paths.appNodeModules],
21 + extensions: [
22 + '.mjs',
23 + '.web.ts',
24 + '.ts',
25 + '.web.tsx',
26 + '.tsx',
27 + '.web.js',
28 + '.js',
29 + '.json',
30 + '.web.jsx',
31 + '.jsx',
32 + ],
33 + plugins: [
34 + new TsconfigPathsPlugin({ configFile: paths.appTsConfig }),
35 + ],
36 + },
37 + module: {
38 + strictExportPresence: true,
39 + rules: [
40 + {
41 + test: /\.(js|jsx|mjs)$/,
42 + loader: require.resolve('source-map-loader'),
43 + enforce: 'pre',
44 + include: paths.appSrc,
45 + },
46 + {
47 + oneOf: [
48 + {
49 + test: /\.(js|jsx|mjs)$/,
50 + loader: require.resolve('babel-loader'),
51 + options: {
52 + cacheDirectory: true,
53 + },
54 + },
55 + {
56 + test: /\.(ts|tsx)$/,
57 + include: paths.appSrc,
58 + use: [
59 + {
60 + loader: require.resolve('ts-loader'),
61 + options: {
62 + transpileOnly: true,
63 + },
64 + },
65 + ],
66 + },
67 + {
68 + test: /\.(graphql|gql)$/,
69 + loader: require.resolve('graphql-tag/loader'),
70 + }
71 + ],
72 + },
73 + ],
74 + },
75 + plugins: [
76 + new webpack.BannerPlugin({ banner: 'require("source-map-support").install();', raw: true, entryOnly: false }),
77 + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
78 + new webpack.DefinePlugin({
79 + 'process.env.NODE_ENV': '"development"',
80 + '__DEV__': true
81 + }),
82 + new ForkTsCheckerWebpackPlugin({
83 + async: false,
84 + watch: paths.appSrc,
85 + tsconfig: paths.appTsConfig,
86 + tslint: paths.appTsLint,
87 + }),
88 + new CopyWebpackPlugin([
89 + { from: paths.serverAssets, to: 'assets' },
90 + ])
91 + ],
92 + devtool: 'sourcemap'
93 +};
...\ No newline at end of file ...\ No newline at end of file
1 +const webpack = require('webpack');
2 +const paths = require('./paths');
3 +const nodeExternals = require('webpack-node-externals');
4 +const CopyWebpackPlugin = require('copy-webpack-plugin')
5 +
6 +module.exports = {
7 + target: 'node',
8 + entry: paths.appEntry,
9 + output: {
10 + path: paths.appBuild,
11 + filename: 'index.js'
12 + },
13 + externals: [nodeExternals()],
14 + resolve: {
15 + modules: [paths.appLib, paths.appSrc, paths.appNodeModules],
16 + extensions: [
17 + '.mjs',
18 + '.web.ts',
19 + '.ts',
20 + '.web.tsx',
21 + '.tsx',
22 + '.web.js',
23 + '.js',
24 + '.json',
25 + '.web.jsx',
26 + '.jsx',
27 + ],
28 + },
29 + module: {
30 + strictExportPresence: true,
31 + rules: [
32 + {
33 + oneOf: [
34 + {
35 + test: /\.(js|jsx|mjs)$/,
36 + loader: require.resolve('babel-loader'),
37 + options: {
38 + cacheDirectory: true,
39 + },
40 + },
41 + {
42 + test: /\.(ts|tsx)$/,
43 + include: paths.appSrc,
44 + use: [
45 + {
46 + loader: require.resolve('ts-loader'),
47 + options: {
48 + transpileOnly: true,
49 + },
50 + },
51 + ],
52 + },
53 + {
54 + test: /\.(graphql|gql)$/,
55 + loader: require.resolve('graphql-tag/loader'),
56 + }
57 + ],
58 + },
59 + ],
60 + },
61 + plugins: [
62 + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
63 + new webpack.DefinePlugin({
64 + 'process.env.NODE_ENV': '"production"',
65 + '__DEV__': false
66 + }),
67 + new webpack.optimize.UglifyJsPlugin({
68 + compress: {
69 + warnings: false,
70 + comparisons: false,
71 + },
72 + mangle: {
73 + safari10: true,
74 + },
75 + output: {
76 + comments: false,
77 + ascii_only: true,
78 + },
79 + }),
80 + new CopyWebpackPlugin([
81 + { from: paths.serverAssets, to: 'assets' },
82 + ])
83 + ],
84 + devtool: 'sourcemap'
85 +};
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "name": "server",
3 + "version": "1.0.0",
4 + "main": "index.js",
5 + "license": "MIT",
6 + "scripts": {
7 + "start": "node scripts/start.js",
8 + "build": "node scripts/build.js",
9 + "post": "ts-node --project scripts/tsconfig.json scripts/post.ts",
10 + "sync": "ts-node --project scripts/tsconfig.json scripts/sync.ts"
11 + },
12 + "devDependencies": {
13 + "@types/compression": "^0.0.36",
14 + "@types/express": "^4.11.1",
15 + "@types/formidable": "^1.0.31",
16 + "@types/fs-extra": "^5.0.2",
17 + "@types/graphql": "^0.12.5",
18 + "@types/morgan": "^1.7.35",
19 + "@types/ramda": "^0.25.21",
20 + "@types/redux-actions": "^2.2.4",
21 + "@types/sequelize": "^4.27.10",
22 + "babel-core": "^6.26.0",
23 + "babel-loader": "^7.1.2",
24 + "babel-plugin-transform-class-properties": "^6.24.1",
25 + "babel-plugin-transform-decorators-legacy": "^1.3.4",
26 + "babel-preset-env": "^1.6.1",
27 + "babel-preset-stage-0": "^6.24.1",
28 + "chokidar": "^2.0.2",
29 + "copy-webpack-plugin": "^4.5.1",
30 + "fork-ts-checker-webpack-plugin": "^0.4.1",
31 + "graphql-tag": "^2.7.3",
32 + "nodemon": "^1.15.0",
33 + "source-map-loader": "^0.2.3",
34 + "source-map-support": "^0.5.3",
35 + "start-server-webpack-plugin": "^2.2.5",
36 + "ts-loader": "2.3.7",
37 + "tsconfig-paths-webpack-plugin": "^3.0.2",
38 + "tslint": "^5.9.1",
39 + "typescript": "^2.7.2",
40 + "webpack": "^3.11.0",
41 + "webpack-node-externals": "^1.6.0"
42 + },
43 + "dependencies": {
44 + "apollo-server-express": "^1.3.2",
45 + "apollo-upload-server": "^5.0.0",
46 + "body-parser": "^1.18.2",
47 + "compression": "^1.7.2",
48 + "express": "^4.16.2",
49 + "formidable": "^1.2.1",
50 + "fs-extra": "^5.0.0",
51 + "graphql": "0.12",
52 + "graphql-tools": "^2.21.0",
53 + "helmet": "^3.11.0",
54 + "jsonwebtoken": "^8.2.1",
55 + "morgan": "^1.9.0",
56 + "node-fetch": "^2.1.1",
57 + "oracledb": "^2.3.0",
58 + "ramda": "^0.25.0",
59 + "serve-favicon": "^2.5.0",
60 + "typeorm": "^0.1.16"
61 + }
62 +}
1 +'use strict';
2 +
3 +process.env.BABEL_ENV = 'production';
4 +process.env.NODE_ENV = 'production';
5 +
6 +process.on('unhandledRejection', (err) => { throw err; });
7 +
8 +const webpack = require('webpack');
9 +const config = require('../config/webpack.config.prod');
10 +const paths = require('../config/paths');
11 +const fs = require('fs-extra');
12 +
13 +fs.emptyDirSync(paths.appBuild);
14 +const compiler = webpack(config);
15 +compiler.run((err, stats) => { console.log(stats.compilation.errors) });
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +process.env.BABEL_ENV = 'development';
4 +process.env.NODE_ENV = 'development';
5 +
6 +process.on('unhandledRejection', (err) => { throw err; });
7 +
8 +const fs = require('fs-extra');
9 +const webpack = require('webpack');
10 +const nodemon = require('nodemon');
11 +const config = require('../config/webpack.config.dev');
12 +const paths = require('../config/paths');
13 +
14 +const compiler = webpack(config);
15 +
16 +fs.emptyDirSync(paths.temporalOutput);
17 +
18 +const run = () => new Promise((res, rej) => {
19 + compiler.watch({}, (err, stats) => {
20 + if (err)
21 + rej(err)
22 + else
23 + res(stats);
24 + });
25 +})
26 +
27 +async function go() {
28 + await run();
29 + nodemon({
30 + script: `${paths.temporalOutput}/index.js`,
31 + ext: 'js json'
32 + });
33 +}
34 +
35 +go();
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "compilerOptions": {
3 + "module": "commonjs",
4 + "target": "es5",
5 + "lib": [
6 + "es6",
7 + "dom"
8 + ],
9 + "sourceMap": true,
10 + "allowJs": true,
11 + "jsx": "react",
12 + "moduleResolution": "node",
13 + "forceConsistentCasingInFileNames": true,
14 + "noImplicitReturns": true,
15 + "noImplicitThis": true,
16 + "emitDecoratorMetadata": true,
17 + "experimentalDecorators": true,
18 + "noImplicitAny": false,
19 + "strictNullChecks": true,
20 + "suppressImplicitAnyIndexErrors": true,
21 + "noUnusedLocals": false,
22 + "baseUrl": "../",
23 + "paths": {
24 + "*": [
25 + "node_modules/*",
26 + "src/*",
27 + "lib/*"
28 + ]
29 + }
30 + },
31 + "exclude": [
32 + "node_modules",
33 + "tmp"
34 + ]
35 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import { Application } from "express";
2 +import { ConnectionOptions, createConnection } from "typeorm";
3 +
4 +import Contract from "entity/Contract";
5 +import Drone from "entity/Drone";
6 +import Model from "entity/Model";
7 +import Org from "entity/Org";
8 +import User from "entity/User";
9 +import Dataset from "entity/Dataset";
10 +
11 +import fake from "../fake";
12 +
13 +const options: ConnectionOptions = {
14 + type: "oracle",
15 + host: "localhost",
16 + port: 1521,
17 + username: "system",
18 + password: "oracle",
19 + database: "khu",
20 + logger: "debug",
21 + synchronize: true,
22 + entities: [Contract, Drone, Model, Org, User, Dataset]
23 +};
24 +
25 +export default async (app: Application) => {
26 + try {
27 + const connection = await createConnection(options);
28 + await fake(connection);
29 + Object.assign(app.locals, { connection });
30 + } catch (e) {
31 + console.log(e);
32 + }
33 +};
1 +import * as express from "express";
2 +import { Application, RequestHandler } from "express";
3 +import * as fs from "fs-extra";
4 +import * as morgan from "morgan";
5 +import * as helmet from "helmet";
6 +import * as compression from "compression";
7 +
8 +import graphql from "routers/graphql";
9 +import graphiql from "routers/graphiql";
10 +import configureDB from "./configureDB";
11 +
12 +export default async (app: Application) => {
13 + Object.assign(app.locals, { port: 7777 });
14 + await configureDB(app);
15 + app.use(morgan("dev"));
16 + // app.use("/assets", express.static("assets"));
17 + app.use("/graphql", graphql);
18 + // app.use("/graphiql", graphiql);
19 +
20 + app.listen(app.locals.port, () =>
21 + console.log(`listening ${app.locals.port}`)
22 + );
23 +};
1 +import {
2 + Entity,
3 + CreateDateColumn,
4 + PrimaryGeneratedColumn,
5 + Column,
6 + ManyToMany,
7 + ManyToOne,
8 + EntityOptions,
9 + OneToMany,
10 + OneToOne
11 +} from "typeorm";
12 +
13 +import User from "./User";
14 +import Drone from "./Drone";
15 +import Org from "./Org";
16 +
17 +@Entity("contracts")
18 +export default class Contract {
19 + @PrimaryGeneratedColumn() id: string;
20 + @Column() reason: string;
21 + @Column() date: string;
22 + @Column() area: string;
23 + @Column() address: string;
24 + @Column() status: string;
25 + @Column() review: string;
26 +
27 + @ManyToOne(type => User)
28 + writer: User;
29 +
30 + @ManyToOne(type => Drone)
31 + drone: Drone;
32 +
33 + @ManyToOne(type => Org)
34 + org: Org;
35 +}
1 +import {
2 + Entity,
3 + CreateDateColumn,
4 + PrimaryGeneratedColumn,
5 + Column,
6 + ManyToMany,
7 + ManyToOne,
8 + EntityOptions,
9 + OneToMany,
10 + OneToOne
11 +} from "typeorm";
12 +
13 +import User from "./User";
14 +import Drone from "./Drone";
15 +import Org from "./Org";
16 +
17 +@Entity("datasets")
18 +export default class Dataset {
19 + @PrimaryGeneratedColumn() id: string;
20 + @Column() comment: string;
21 +
22 + @ManyToOne(type => Drone)
23 + producer: Drone;
24 +
25 + @ManyToMany(type => User, user => user.datasets)
26 + buyers: Array<User>;
27 +}
1 +import {
2 + Entity,
3 + CreateDateColumn,
4 + PrimaryGeneratedColumn,
5 + Column,
6 + ManyToMany,
7 + ManyToOne,
8 + EntityOptions,
9 + OneToMany,
10 + OneToOne
11 +} from "typeorm";
12 +
13 +import User from "./User";
14 +import Model from "./Model";
15 +import Dataset from "./Dataset";
16 +
17 +@Entity("drones")
18 +export default class Drone {
19 + @PrimaryGeneratedColumn() id: string;
20 + @Column() date: string;
21 + @Column() name: string;
22 +
23 + @ManyToOne(type => User)
24 + owner: User;
25 +
26 + @ManyToOne(type => Model)
27 + model: Model;
28 +
29 + @OneToMany(type => Dataset, dataset => dataset.producer)
30 + datasets: Dataset;
31 +}
1 +import {
2 + Entity,
3 + CreateDateColumn,
4 + PrimaryGeneratedColumn,
5 + Column,
6 + ManyToMany,
7 + ManyToOne,
8 + EntityOptions,
9 + OneToMany,
10 + OneToOne
11 +} from "typeorm";
12 +
13 +import Drone from "./Drone";
14 +
15 +@Entity("models")
16 +export default class Model {
17 + @PrimaryGeneratedColumn() id: string;
18 + @Column() name: string;
19 +}
1 +import {
2 + Entity,
3 + CreateDateColumn,
4 + PrimaryGeneratedColumn,
5 + Column,
6 + ManyToMany,
7 + ManyToOne,
8 + EntityOptions,
9 + OneToMany,
10 + OneToOne
11 +} from "typeorm";
12 +
13 +import Contract from "./Contract";
14 +
15 +@Entity("orgs")
16 +export default class Org {
17 + @PrimaryGeneratedColumn()
18 + id: string;
19 +
20 + @Column()
21 + name: string;
22 +
23 + @OneToMany(type => Contract, contract => contract.org)
24 + contracts: Array<Contract>;
25 +}
1 +import {
2 + Entity,
3 + CreateDateColumn,
4 + PrimaryGeneratedColumn,
5 + Column,
6 + ManyToMany,
7 + JoinTable,
8 + ManyToOne,
9 + EntityOptions,
10 + OneToMany,
11 + OneToOne
12 +} from "typeorm";
13 +
14 +import Dataset from "./Dataset";
15 +import Drone from "./Drone";
16 +import Contract from "./Contract";
17 +
18 +@Entity("users")
19 +export default class User {
20 + @PrimaryGeneratedColumn() id: string;
21 + @Column() email: string;
22 + @Column() password: string;
23 +
24 + @OneToMany(type => Drone, drone => drone.owner)
25 + drones: Array<Drone>;
26 +
27 + @OneToMany(type => Contract, contract => contract.writer)
28 + contracts: Array<Contract>;
29 +
30 + @ManyToMany(type => Dataset, dataset => dataset.buyers)
31 + @JoinTable()
32 + datasets: Array<Dataset>;
33 +}
1 +import { Connection } from "typeorm";
2 +import User from "entity/User";
3 +import Org from "entity/Org";
4 +import Model from "entity/Model";
5 +
6 +export default async function fake(connection: Connection) {
7 + const userRepo = connection.getRepository(User);
8 + const result = await userRepo.find();
9 + console.log(result);
10 + if (result.length > 0) {
11 + console.log("NOT FIRST.. END FAKE");
12 + return;
13 + }
14 +
15 + try {
16 + console.log("FIRST.. FAKE START");
17 + let user = new User();
18 + user.email = "db@khu.ac.kr";
19 + user.password = "db";
20 + await userRepo.save(user);
21 +
22 + console.log("USER DONE");
23 +
24 + let modelA = new Model();
25 + modelA.name = "F15";
26 +
27 + let modelB = new Model();
28 + modelB.name = "F20";
29 +
30 + let modelC = new Model();
31 + modelC.name = "Raptor";
32 +
33 + let modelD = new Model();
34 + modelD.name = "F22";
35 +
36 + let modelE = new Model();
37 + modelE.name = "Valkyrie";
38 +
39 + let modelF = new Model();
40 + modelF.name = "Battlecruiser";
41 +
42 + console.log("MODEL READY");
43 +
44 + await connection
45 + .createQueryBuilder()
46 + .insert()
47 + .into(Model)
48 + .values([modelA, modelB, modelC, modelD, modelE, modelF])
49 + .execute();
50 +
51 + console.log("MODEL DONE");
52 +
53 +
54 + let OrgA = new Org();
55 + OrgA.name = "서울";
56 +
57 + let OrgB = new Org();
58 + OrgB.name = "수원";
59 +
60 + let OrgC = new Org();
61 + OrgC.name = "부산";
62 +
63 + let OrgD = new Org();
64 + OrgD.name = "춘천";
65 +
66 + console.log("ORG READY");
67 +
68 + await connection
69 + .createQueryBuilder()
70 + .insert()
71 + .into(Org)
72 + .values([OrgA, OrgB, OrgC, OrgD])
73 + .execute();
74 +
75 + console.log("ORG DONE");
76 +
77 + console.log("FAKE OVER");
78 + } catch (e) {
79 + console.log(e, "FAKE ERROR");
80 + }
81 +}
File mode changed
1 +import 'reflect-metadata';
2 +import * as express from 'express';
3 +import configureApp from './configureApp';
4 +
5 +const app = express();
6 +
7 +configureApp(app);
...\ No newline at end of file ...\ No newline at end of file
1 +import * as express from 'express';
2 +import { graphiqlExpress } from 'apollo-server-express';
3 +
4 +const router = express.Router();
5 +router.get('/', graphiqlExpress({ endpointURL: '/graphql' }));
6 +
7 +export default router;
8 +
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import Contract from "entity/Contract";
4 +import Drone from "entity/Drone";
5 +import Dataset from "entity/Dataset";
6 +import User from "entity/User";
7 +import Org from "entity/Org";
8 +
9 +export default async (root: {}, { id }, context: Context) => {
10 + const { connection, session } = context;
11 + console.log("AAA");
12 + const userRepo = connection.getRepository(User);
13 + const datasetRepo = connection.getRepository(Dataset);
14 + const user = await userRepo.findOneById(session.id);
15 +
16 + const datasets = await userRepo
17 + .createQueryBuilder()
18 + .relation(User, "datasets")
19 + .of(user)
20 + .loadMany();
21 +
22 + const dataset = await datasetRepo.findOneById(id);
23 + console.log(user);
24 + user!.datasets = [...datasets, dataset];
25 +
26 + try {
27 + const result = await userRepo.save(user!);
28 + console.log("UPDATE", result);
29 + } catch (err) {
30 + console.log(err, 11111);
31 + }
32 +
33 + return dataset;
34 +};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import Contract from "entity/Contract";
4 +import Drone from "entity/Drone";
5 +import User from "entity/User";
6 +import Org from "entity/Org";
7 +
8 +export default async (
9 + root: {},
10 + { input: { reason, date, droneId, area, address } },
11 + context: Context
12 +) => {
13 + const { connection } = context;
14 + const contractRepo = connection.getRepository(Contract);
15 + const droneRepo = connection.getRepository(Drone);
16 + const userRepo = connection.getRepository(User);
17 + const orgRepo = connection.getRepository(Org);
18 +
19 + const userId = context.session.id;
20 + const user = await userRepo.findOneById(userId);
21 +
22 + if (R.isNil(user)) throw new Error("Session Error");
23 +
24 + const drone = await droneRepo.findOneById(droneId);
25 +
26 + if (R.isNil(drone)) throw new Error("Invalid Drone ID");
27 +
28 + const org = await orgRepo.findOne({ where: { name: area } });
29 +
30 + let contract = new Contract();
31 +
32 + contract.reason = reason;
33 + contract.date = date;
34 + contract.area = area;
35 + contract.address = address;
36 + contract.drone = drone;
37 + contract.status = "wait";
38 + contract.review = "심사중";
39 + contract.writer = user!;
40 + contract.org = org!;
41 +
42 + await contractRepo.save(contract);
43 + return contract;
44 +};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import Contract from "entity/Contract";
4 +import Drone from "entity/Drone";
5 +import Dataset from "entity/Dataset";
6 +import User from "entity/User";
7 +import Org from "entity/Org";
8 +
9 +export default async (
10 + root: {},
11 + { input: { comment, droneId } },
12 + context: Context
13 +) => {
14 + const { connection } = context;
15 + const datasetRepo = connection.getRepository(Dataset);
16 + const droneRepo = connection.getRepository(Drone);
17 +
18 + const drone = await droneRepo.findOneById(droneId);
19 +
20 + let dataset = new Dataset();
21 +
22 + dataset.comment = comment;
23 + dataset.producer = drone!;
24 +
25 + await datasetRepo.save(dataset);
26 + return dataset;
27 +};
1 +import { Context } from "../";
2 +import User from "entity/User";
3 +
4 +export default async (
5 + root: {},
6 + { input: { email, password } },
7 + context: Context
8 +) => {
9 + const { connection } = context;
10 + const userRepo = connection.getRepository(User);
11 + let user = new User();
12 + user.email = email;
13 + user.password = password;
14 +
15 + await userRepo.save(user);
16 + return user;
17 +};
1 +import buyDataset from "./buyDataset";
2 +import createUser from "./createUser";
3 +import createContract from "./createContract";
4 +import createDataset from "./createDataset";
5 +import login from "./login";
6 +import registerDrone from "./registerDrone";
7 +import judgeContract from "./judgeContract";
8 +
9 +export default {
10 + buyDataset,
11 + createContract,
12 + createUser,
13 + createDataset,
14 + judgeContract,
15 + login,
16 + registerDrone
17 +};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import Contract from "entity/Contract";
4 +import Drone from "entity/Drone";
5 +import User from "entity/User";
6 +import Org from "entity/Org";
7 +
8 +export default async (root: {}, { id, ok, review }, context: Context) => {
9 + const { connection } = context;
10 + const contractRepo = connection.getRepository(Contract);
11 +
12 + const result = await contractRepo
13 + .createQueryBuilder()
14 + .update(Contract)
15 + .set({ status: ok ? "ok" : "rejected", review })
16 + .where("id = :id", { id })
17 + .execute();
18 +
19 + return null;
20 +};
1 +import { Context } from "../";
2 +import User from "entity/User";
3 +import * as R from "ramda";
4 +
5 +// password를 암호화하자
6 +export default async (
7 + root: {},
8 + { input: { email, password } },
9 + context: Context
10 +) => {
11 + const { connection } = context;
12 + const userRepo = connection.getRepository(User);
13 +
14 + const user = await userRepo.findOne({
15 + where: {
16 + email,
17 + password
18 + }
19 + });
20 +
21 + if (R.isNil(user)) return null;
22 +
23 + const token = user!.id;
24 + return { user, token };
25 +};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import Drone from "entity/Drone";
4 +import Model from "entity/Model";
5 +import User from "entity/User";
6 +
7 +export default async (root: {}, { input: { modelId, name } }, context: Context) => {
8 + const { connection, session } = context;
9 + const droneRepo = connection.getRepository(Drone);
10 + const modelRepo = connection.getRepository(Model);
11 + const userRepo = connection.getRepository(User);
12 +
13 + const userId = session.id;
14 + const user = await userRepo.findOneById(userId);
15 +
16 + if (R.isNil(user)) throw new Error("Session Error");
17 +
18 + const model = await modelRepo.findOneById(modelId);
19 +
20 + if (R.isNil(model)) throw new Error("Invalid Drone Model");
21 +
22 + let drone = new Drone();
23 + drone.name = name;
24 + drone.date = new Date().toString();
25 + drone.owner = user!;
26 + drone.model = model;
27 +
28 + await droneRepo.save(drone);
29 + console.log(drone);
30 + return drone;
31 +};
1 +import { Context } from "../";
2 +import Dataset from "entity/Dataset";
3 +
4 +export default async (root: {}, { id }, context: Context) => {
5 + const { connection } = context;
6 + const datasetRepo = connection.getRepository(Dataset);
7 + const datasets = await datasetRepo.find();
8 + console.log(datasets);
9 + return datasets;
10 +};
1 +import { Context } from "../";
2 +import Model from "entity/Model";
3 +
4 +export default async (root: {}, { id }, context: Context) => {
5 + const { connection } = context;
6 + const modelRepo = connection.getRepository(Model);
7 + const models = await modelRepo.find();
8 + return models;
9 +};
1 +import { Context } from "../";
2 +import Org from "entity/Org";
3 +
4 +export default async (root: {}, { id }, context: Context) => {
5 + const { connection } = context;
6 + const orgRepo = connection.getRepository(Org);
7 + const orgs = await orgRepo.find();
8 + return orgs;
9 +};
1 +import { Context } from "../";
2 +import Contract from "entity/Contract";
3 +
4 +export default async (root: {}, { id }, context: Context) => {
5 + const { connection } = context;
6 + const contractRepo = connection.getRepository(Contract);
7 + const contract = await contractRepo.findOneById(id);
8 + return contract;
9 +};
1 +import { Context } from "../";
2 +import User from "entity/User";
3 +
4 +export default async (root: {}, {}, context: Context) => {
5 + const { connection, session } = context;
6 + const userRepo = connection.getRepository(User);
7 + const userId = session.id;
8 + const user = await userRepo.findOneById(userId);
9 + console.log(user);
10 + return user;
11 +};
1 +import { Context } from "../";
2 +import Org from "entity/Org";
3 +
4 +export default async (root: {}, { id }, context: Context) => {
5 + const { connection } = context;
6 + const orgRepo = connection.getRepository(Org);
7 + const org = await orgRepo.findOneById(id);
8 + return org;
9 +};
1 +import { Context } from "../";
2 +import User from "entity/User";
3 +
4 +export default async (root: {}, { id }, context: Context) => {
5 + const { connection } = context;
6 + const userRepo = connection.getRepository(User);
7 + const user = await userRepo.findOneById(id);
8 + return user;
9 +};
1 +import fetchAllModels from "./fetchAllModels";
2 +import fetchAllDatasets from "./fetchAllDatasets";
3 +import fetchAllOrgs from "./fetchAllOrgs";
4 +import fetchUser from "./fetchUser";
5 +import fetchContract from "./fetchContract";
6 +import fetchCurrentUser from "./fetchCurrentUser";
7 +import fetchOrg from "./fetchOrg";
8 +
9 +export default {
10 + fetchAllModels,
11 + fetchAllDatasets,
12 + fetchAllOrgs,
13 + fetchUser,
14 + fetchOrg,
15 + fetchContract,
16 + fetchCurrentUser
17 +};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import Contract from "entity/Contract";
4 +
5 +export default {
6 + async drone(contract, {}, context: Context) {
7 + if (contract.drone) return contract.drone;
8 +
9 + const contractRepo = context.connection.getRepository(Contract);
10 +
11 + const model = await contractRepo
12 + .createQueryBuilder()
13 + .relation(Contract, "drone")
14 + .of(contract)
15 + .loadOne();
16 +
17 + return model;
18 + }
19 +};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import Dataset from "entity/Dataset";
4 +
5 +export default {
6 + async producer(dataset, {}, context: Context) {
7 + if (dataset.producer) return dataset.producer;
8 +
9 + const datasetRepo = context.connection.getRepository(Dataset);
10 +
11 + const producer = await datasetRepo
12 + .createQueryBuilder()
13 + .relation(Dataset, "producer")
14 + .of(dataset)
15 + .loadOne();
16 +
17 + return producer;
18 + }
19 +};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import Drone from "entity/Drone";
4 +
5 +export default {
6 + async model(drone, {}, context: Context) {
7 + if (drone.model) return drone.model;
8 +
9 + const droneRepo = context.connection.getRepository(Drone);
10 +
11 + const model = await droneRepo
12 + .createQueryBuilder()
13 + .relation(Drone, "model")
14 + .of(drone)
15 + .loadOne();
16 +
17 + return model;
18 + },
19 + async owner(drone, {}, context: Context) {
20 + if (drone.owner) return drone.owner;
21 +
22 + const droneRepo = context.connection.getRepository(Drone);
23 +
24 + const owner = await droneRepo
25 + .createQueryBuilder()
26 + .relation(Drone, "owner")
27 + .of(drone)
28 + .loadOne();
29 +
30 + return owner;
31 + }
32 +};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +
4 +export default {};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import Org from "entity/Org";
4 +
5 +export default {
6 + async contracts(org, {}, context: Context) {
7 + if (org.contracts) return org.model;
8 +
9 + const orgRepo = context.connection.getRepository(Org);
10 +
11 + const contracts = await orgRepo
12 + .createQueryBuilder()
13 + .relation(Org, "contracts")
14 + .of(org)
15 + .loadOne();
16 +
17 + console.log("Hello", contracts);
18 + return contracts;
19 + }
20 +};
1 +import * as R from "ramda";
2 +import { Context } from "../";
3 +import User from "entity/User";
4 +
5 +export default {
6 + async drones(user, {}, context: Context) {
7 + const userRepo = context.connection.getRepository(User);
8 +
9 + const drones = await userRepo
10 + .createQueryBuilder()
11 + .relation(User, "drones")
12 + .of(user)
13 + .loadMany();
14 +
15 + return drones;
16 + },
17 + async contracts(user, {}, context: Context) {
18 + const userRepo = context.connection.getRepository(User);
19 +
20 + const contracts = await userRepo
21 + .createQueryBuilder()
22 + .relation(User, "contracts")
23 + .of(user)
24 + .loadMany();
25 +
26 + return contracts;
27 + },
28 + async datasets(user, {}, context: Context) {
29 + const userRepo = context.connection.getRepository(User);
30 +
31 + const datasets = await userRepo
32 + .createQueryBuilder()
33 + .relation(User, "datasets")
34 + .of(user)
35 + .loadMany();
36 +
37 + return datasets;
38 + }
39 +};
1 +import Contract from "./Contract";
2 +import Drone from "./Drone";
3 +import Dataset from "./Dataset";
4 +import Model from "./Model";
5 +import Org from "./Org";
6 +import User from "./User";
7 +
8 +export default { Contract, Drone, Dataset, Model, Org, User };
1 +import * as express from "express";
2 +import { graphqlExpress } from "apollo-server-express";
3 +import * as R from "ramda";
4 +import * as jwt from "jsonwebtoken";
5 +import * as bodyParser from "body-parser";
6 +import schema from "./schema";
7 +import { Connection } from "typeorm";
8 +
9 +const { apolloUploadExpress } = require("apollo-upload-server");
10 +
11 +const router = express.Router();
12 +const formatError = R.always("GraphQL Error"); // OFF NOW
13 +
14 +const extractSession = req =>
15 + req.headers["authorization"]
16 + ? req.headers["authorization"].split(" ")[1]
17 + : null;
18 +
19 +export interface Context {
20 + connection: Connection;
21 + session: {
22 + id: string;
23 + };
24 +}
25 +
26 +router.use(
27 + "/",
28 + bodyParser.json(),
29 + apolloUploadExpress(),
30 + graphqlExpress(async (req, res) => {
31 + const connection = req!.app.locals.connection;
32 + const session = { id: extractSession(req) };
33 + console.log(session);
34 + const context: Context = { connection, session };
35 + return { schema, context };
36 + })
37 +);
38 +
39 +export default router;
1 +import { makeExecutableSchema } from "graphql-tools";
2 +import Query from "./Query";
3 +import Mutation from "./Mutation";
4 +import Types from "./Types";
5 +
6 +const typeDefs = require("./typeDefs.gql");
7 +const { GraphQLUpload: Upload } = require("apollo-upload-server");
8 +
9 +const resolvers = {
10 + Query,
11 + Mutation,
12 + ...Types
13 +};
14 +
15 +export default makeExecutableSchema({ typeDefs, resolvers });
1 +type Contract {
2 + id: ID!
3 + reason: String!
4 + date: String!
5 + address: String!
6 + area: String!
7 + status: String!
8 + review: String!
9 + writer: User!
10 + drone: Drone!
11 +}
12 +
13 +type Drone {
14 + id: ID!
15 + name: String!
16 + date: String!
17 + model: Model!
18 + datasets: [Dataset!]!
19 + owner: User!
20 +}
21 +
22 +type Dataset {
23 + id: ID!
24 + comment: String!
25 + producer: Drone!
26 +}
27 +
28 +type Model {
29 + id: ID!
30 + name: String!
31 +}
32 +
33 +type Org {
34 + id: ID!
35 + name: String!
36 + contracts: [Contract!]!
37 +}
38 +
39 +type User {
40 + id: ID!
41 + email: String!
42 + password: String!
43 + contracts: [Contract!]!
44 + drones: [Drone!]!
45 + datasets: [Dataset!]!
46 +}
47 +
48 +type Query {
49 + fetchAllModels: [Model!]!
50 + fetchAllDatasets: [Dataset!]!
51 + fetchAllOrgs: [Org!]!
52 + fetchCurrentUser: User
53 + fetchOrg(id: ID!): Org
54 + fetchUser(id: ID!): User
55 + fetchContract(id: ID!): Contract
56 +}
57 +
58 +type Mutation {
59 + buyDataset(id: ID!): Dataset
60 + createContract(input: ContractInput!): Contract
61 + createUser(input: UserInput!): User
62 + createDataset(input: DatasetInput!): Dataset
63 + login(input: UserInput!): LoginResult
64 + registerDrone(input: DroneInput!): Drone
65 + judgeContract(id: ID!, ok: Boolean!, review: String!): Contract
66 +
67 +}
68 +
69 +input ContractInput {
70 + droneId: ID!
71 + reason: String!
72 + date: String!
73 + address: String!
74 + area: String!
75 +}
76 +
77 +input DroneInput {
78 + modelId: ID!
79 + name: String!
80 +}
81 +
82 +input DatasetInput {
83 + droneId: ID!
84 + comment: String!
85 +}
86 +
87 +type LoginResult {
88 + user: User!
89 + token: String!
90 +}
91 +
92 +input UserInput {
93 + email: String!
94 + password: String!
95 +}
96 +
97 +type Schema {
98 + query: Query
99 + mutation: Mutation
100 +}
1 +{
2 + "compilerOptions": {
3 + "outDir": "../build/server",
4 + "module": "es2015",
5 + "target": "es5",
6 + "lib": [
7 + "es6",
8 + "dom"
9 + ],
10 + "sourceMap": true,
11 + "allowJs": true,
12 + "moduleResolution": "node",
13 + "forceConsistentCasingInFileNames": true,
14 + "noImplicitReturns": true,
15 + "noImplicitThis": true,
16 + "emitDecoratorMetadata": true,
17 + "experimentalDecorators": true,
18 + "noImplicitAny": false,
19 + "strictNullChecks": true,
20 + "suppressImplicitAnyIndexErrors": true,
21 + "noUnusedLocals": false,
22 + "baseUrl": ".",
23 + "paths": {
24 + "*": [
25 + "node_modules/*",
26 + "src/*",
27 + "lib/*"
28 + ]
29 + }
30 + },
31 + "exclude": [
32 + "node_modules",
33 + "tmp"
34 + ]
35 +}
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "rules": {
3 + "align": [
4 + false,
5 + "parameters",
6 + "arguments",
7 + "statements"
8 + ],
9 + "ban": false,
10 + "class-name": false,
11 + "comment-format": [
12 + false,
13 + "check-space"
14 + ],
15 + "curly": false,
16 + "eofline": false,
17 + "forin": false,
18 + "indent": [ false, "spaces" ],
19 + "interface-name": [false, "never-prefix"],
20 + "jsdoc-format": false,
21 + "jsx-no-lambda": false,
22 + "jsx-no-multiline-js": false,
23 + "label-position": false,
24 + "max-line-length": [ false, 120 ],
25 + "member-ordering": [
26 + false,
27 + "public-before-private",
28 + "static-before-instance",
29 + "variables-before-functions"
30 + ],
31 + "no-any": false,
32 + "no-arg": false,
33 + "no-bitwise": false,
34 + "no-console": [
35 + false,
36 + "log",
37 + "error",
38 + "debug",
39 + "info",
40 + "time",
41 + "timeEnd",
42 + "trace"
43 + ],
44 + "no-consecutive-blank-lines": false,
45 + "no-construct": false,
46 + "no-debugger": false,
47 + "no-duplicate-variable": false,
48 + "no-empty": false,
49 + "no-eval": false,
50 + "no-shadowed-variable": false,
51 + "no-string-literal": false,
52 + "no-switch-case-fall-through": false,
53 + "no-trailing-whitespace": false,
54 + "no-unused-expression": false,
55 + "no-use-before-declare": false,
56 + "one-line": [
57 + false,
58 + "check-catch",
59 + "check-else",
60 + "check-open-brace",
61 + "check-whitespace"
62 + ],
63 + "quotemark": [false, "single", "jsx-double"],
64 + "radix": false,
65 + "semicolon": [false, "always"],
66 + "switch-default": false,
67 +
68 + "trailing-comma": [false],
69 +
70 + "triple-equals": [ false, "allow-null-check" ],
71 + "typedef": [
72 + false,
73 + "parameter",
74 + "property-declaration"
75 + ],
76 + "typedef-whitespace": [
77 + false,
78 + {
79 + "call-signature": "nospace",
80 + "index-signature": "nospace",
81 + "parameter": "nospace",
82 + "property-declaration": "nospace",
83 + "variable-declaration": "nospace"
84 + }
85 + ],
86 + "variable-name": [false, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
87 + "whitespace": [
88 + false,
89 + "check-branch",
90 + "check-decl",
91 + "check-module",
92 + "check-operator",
93 + "check-separator",
94 + "check-type",
95 + "check-typecast"
96 + ]
97 + }
98 +}