박선진

remade from create-react-app for completely deleting unnecessary codes from template code

Showing 180 changed files with 209 additions and 4685 deletions
This diff could not be displayed because it is too large.
1 -module.exports = {
2 - "presets": [
3 - "react-app"
4 - ],
5 - "plugins": [
6 - "@babel/plugin-proposal-class-properties",
7 - "@babel/plugin-proposal-optional-chaining"
8 - ]
9 -};
...\ 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 -// 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/facebook/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/facebook/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((env, key) => {
85 - env[key] = JSON.stringify(raw[key]);
86 - return env;
87 - }, {}),
88 - };
89 -
90 - return { raw, stringified };
91 -}
92 -
93 -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 - const assetFilename = JSON.stringify(path.basename(filename));
11 -
12 - if (filename.match(/\.svg$/)) {
13 - return `module.exports = {
14 - __esModule: true,
15 - default: ${assetFilename},
16 - ReactComponent: (props) => ({
17 - $$typeof: Symbol.for('react.element'),
18 - type: 'svg',
19 - ref: null,
20 - key: null,
21 - props: Object.assign({}, props, {
22 - children: ${assetFilename}
23 - })
24 - }),
25 - };`;
26 - }
27 -
28 - return `module.exports = ${assetFilename};`;
29 - },
30 -};
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/facebook/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(inputPath, needsSlash) {
15 - const hasSlash = inputPath.endsWith('/');
16 - if (hasSlash && !needsSlash) {
17 - return inputPath.substr(0, inputPath.length - 1);
18 - } else if (!hasSlash && needsSlash) {
19 - return `${inputPath}/`;
20 - } else {
21 - return inputPath;
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 =
37 - envPublicUrl || (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 - appPath: resolveApp('.'),
45 - appBuild: resolveApp('build'),
46 - appPublic: resolveApp('public'),
47 - appHtml: resolveApp('public/index.html'),
48 - appIndexJs: resolveApp('src/index.js'),
49 - appPackageJson: resolveApp('package.json'),
50 - appSrc: resolveApp('src'),
51 - yarnLockFile: resolveApp('yarn.lock'),
52 - testsSetup: resolveApp('src/setupTests.js'),
53 - proxySetup: resolveApp('src/setupProxy.js'),
54 - appNodeModules: resolveApp('node_modules'),
55 - publicUrl: getPublicUrl(resolveApp('package.json')),
56 - servedPath: getServedPath(resolveApp('package.json')),
57 -};
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 -'use strict';
2 -
3 -const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
4 -const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
5 -const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
6 -const ignoredFiles = require('react-dev-utils/ignoredFiles');
7 -const config = require('./webpack.config.dev');
8 -const paths = require('./paths');
9 -const fs = require('fs');
10 -
11 -const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
12 -const host = process.env.HOST || '0.0.0.0';
13 -
14 -module.exports = function(proxy, allowedHost) {
15 - return {
16 - // WebpackDevServer 2.4.3 introduced a security fix that prevents remote
17 - // websites from potentially accessing local content through DNS rebinding:
18 - // https://github.com/webpack/webpack-dev-server/issues/887
19 - // https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
20 - // However, it made several existing use cases such as development in cloud
21 - // environment or subdomains in development significantly more complicated:
22 - // https://github.com/facebook/create-react-app/issues/2271
23 - // https://github.com/facebook/create-react-app/issues/2233
24 - // While we're investigating better solutions, for now we will take a
25 - // compromise. Since our WDS configuration only serves files in the `public`
26 - // folder we won't consider accessing them a vulnerability. However, if you
27 - // use the `proxy` feature, it gets more dangerous because it can expose
28 - // remote code execution vulnerabilities in backends like Django and Rails.
29 - // So we will disable the host check normally, but enable it if you have
30 - // specified the `proxy` setting. Finally, we let you override it if you
31 - // really know what you're doing with a special environment variable.
32 - disableHostCheck:
33 - !proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
34 - // Enable gzip compression of generated files.
35 - compress: true,
36 - // Silence WebpackDevServer's own logs since they're generally not useful.
37 - // It will still show compile warnings and errors with this setting.
38 - clientLogLevel: 'none',
39 - // By default WebpackDevServer serves physical files from current directory
40 - // in addition to all the virtual build products that it serves from memory.
41 - // This is confusing because those files won’t automatically be available in
42 - // production build folder unless we copy them. However, copying the whole
43 - // project directory is dangerous because we may expose sensitive files.
44 - // Instead, we establish a convention that only files in `public` directory
45 - // get served. Our build script will copy `public` into the `build` folder.
46 - // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
47 - // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
48 - // In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
49 - // Note that we only recommend to use `public` folder as an escape hatch
50 - // for files like `favicon.ico`, `manifest.json`, and libraries that are
51 - // for some reason broken when imported through Webpack. If you just want to
52 - // use an image, put it in `src` and `import` it from JavaScript instead.
53 - contentBase: paths.appPublic,
54 - // By default files from `contentBase` will not trigger a page reload.
55 - watchContentBase: true,
56 - // Enable hot reloading server. It will provide /sockjs-node/ endpoint
57 - // for the WebpackDevServer client so it can learn when the files were
58 - // updated. The WebpackDevServer client is included as an entry point
59 - // in the Webpack development configuration. Note that only changes
60 - // to CSS are currently hot reloaded. JS changes will refresh the browser.
61 - hot: true,
62 - // It is important to tell WebpackDevServer to use the same "root" path
63 - // as we specified in the config. In development, we always serve from /.
64 - publicPath: config.output.publicPath,
65 - // WebpackDevServer is noisy by default so we emit custom message instead
66 - // by listening to the compiler events with `compiler.hooks[...].tap` calls above.
67 - quiet: true,
68 - // Reportedly, this avoids CPU overload on some systems.
69 - // https://github.com/facebook/create-react-app/issues/293
70 - // src/node_modules is not ignored to support absolute imports
71 - // https://github.com/facebook/create-react-app/issues/1065
72 - watchOptions: {
73 - ignored: ignoredFiles(paths.appSrc),
74 - },
75 - // Enable HTTPS if the HTTPS environment variable is set to 'true'
76 - https: protocol === 'https',
77 - host,
78 - overlay: false,
79 - historyApiFallback: {
80 - // Paths with dots should still use the history fallback.
81 - // See https://github.com/facebook/create-react-app/issues/387.
82 - disableDotRule: true,
83 - },
84 - public: allowedHost,
85 - proxy,
86 - before(app, server) {
87 - if (fs.existsSync(paths.proxySetup)) {
88 - // This registers user provided middleware for proxy reasons
89 - require(paths.proxySetup)(app);
90 - }
91 -
92 - // This lets us fetch source contents from webpack for the error overlay
93 - app.use(evalSourceMapMiddleware(server));
94 - // This lets us open files from the runtime error overlay.
95 - app.use(errorOverlayMiddleware());
96 -
97 - // This service worker file is effectively a 'no-op' that will reset any
98 - // previous service worker registered for the same host:port combination.
99 - // We do this in development to avoid hitting the production cache if
100 - // it used the same host and port.
101 - // https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
102 - app.use(noopServiceWorkerMiddleware());
103 - },
104 - };
105 -};
This diff could not be displayed because it is too large.
1 { 1 {
2 - "name": "sing-app-react", 2 + "name": "oss-front-end",
3 - "version": "5.0.0", 3 + "version": "0.1.0",
4 + "moduleNameMapper": {
5 + "^react-native$": "react-native-web",
6 + "^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
7 + },
4 "private": true, 8 "private": true,
9 + "dependencies": {
10 + "@testing-library/jest-dom": "^4.2.4",
11 + "@testing-library/react": "^9.5.0",
12 + "@testing-library/user-event": "^7.2.1",
13 + "animate.css": "^4.1.0",
14 + "awesome-bootstrap-checkbox": "^1.0.1",
15 + "bootstrap": "^4.5.0",
16 + "classnames": "^2.2.6",
17 + "debug": "^4.1.1",
18 + "font-awesome": "^4.7.0",
19 + "glyphicons-halflings": "^1.9.1",
20 + "jquery": "^3.5.1",
21 + "line-awesome": "^1.3.0",
22 + "mixins": "0.0.1",
23 + "node-sass": "^4.14.1",
24 + "prop-types": "^15.7.2",
25 + "rc-hammerjs": "^0.6.10",
26 + "react": "^16.13.1",
27 + "react-dom": "^16.13.1",
28 + "react-redux": "^7.2.0",
29 + "react-router": "^5.2.0",
30 + "react-router-dom": "^5.2.0",
31 + "react-scripts": "3.4.1",
32 + "react-table": "^7.2.0",
33 + "react-transition-group": "^4.4.1",
34 + "reactstrap": "^8.4.1",
35 + "redux": "^4.0.5",
36 + "redux-thunk": "^2.3.0",
37 + "scss": "^0.2.4"
38 + },
5 "scripts": { 39 "scripts": {
6 - "build": "node scripts/build.js", 40 + "start": "react-scripts start",
7 - "start": "node scripts/start.js", 41 + "build": "react-scripts build",
8 - "test": "node scripts/test.js" 42 + "test": "react-scripts test",
43 + "eject": "react-scripts eject"
9 }, 44 },
10 - "browserslist": [
11 - ">0.2%",
12 - "not dead",
13 - "not ie <= 11",
14 - "not op_mini all"
15 - ],
16 "eslintConfig": { 45 "eslintConfig": {
17 "extends": "react-app" 46 "extends": "react-app"
18 }, 47 },
19 - "jest": { 48 + "browserslist": {
20 - "collectCoverageFrom": [ 49 + "production": [
21 - "src/**/*.{js,jsx}" 50 + ">0.2%",
22 - ], 51 + "not dead",
23 - "moduleFileExtensions": [ 52 + "not op_mini all"
24 - "web.js",
25 - "js",
26 - "json",
27 - "web.jsx",
28 - "jsx",
29 - "node"
30 - ],
31 - "moduleNameMapper": {
32 - "^react-native$": "react-native-web",
33 - "^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
34 - },
35 - "resolver": "jest-pnp-resolver",
36 - "setupFiles": [
37 - "react-app-polyfill/jsdom"
38 ], 53 ],
39 - "testEnvironment": "jsdom", 54 + "development": [
40 - "testMatch": [ 55 + "last 1 chrome version",
41 - "<rootDir>/src/**/__tests__/**/*.{js,jsx}", 56 + "last 1 firefox version",
42 - "<rootDir>/src/**/?(*.)(spec|test).{js,jsx}" 57 + "last 1 safari version"
43 - ],
44 - "testURL": "http://localhost",
45 - "transform": {
46 - "^.+\\.(js|jsx)$": "<rootDir>/node_modules/babel-jest",
47 - "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
48 - "^(?!.*\\.(js|jsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
49 - },
50 - "transformIgnorePatterns": [
51 - "[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$",
52 - "^.+\\.module\\.(css|sass|scss)$"
53 ] 58 ]
54 - },
55 - "dependencies": {
56 - "animate.css": "3.7.0",
57 - "awesome-bootstrap-checkbox": "1.0.1",
58 - "axios": "^0.18.0",
59 - "bootstrap": "4.0.0",
60 - "bootstrap-slider": "^10.2.1",
61 - "bootstrap_calendar": "https://github.com/xero/bootstrap_calendar.git#1.0.1",
62 - "classnames": "^2.2.6",
63 - "draft-js": "^0.10.5",
64 - "flot": "^0.8.0-alpha",
65 - "flot.dashes": "https://github.com/cquartier/flot.dashes.git",
66 - "font-awesome": "4.7.0",
67 - "formsy-react": "0.19.5",
68 - "fullcalendar": "^3.9.0",
69 - "glyphicons-halflings": "^1.9.1",
70 - "jasny-bootstrap": "^3.1.3",
71 - "jquery": "^3.3.1",
72 - "jquery-mapael": "^2.2.0",
73 - "jquery-sparkline": "^2.4.0",
74 - "jquery-ui": "1.12.1",
75 - "jquery.animate-number": "0.0.14",
76 - "jquery.flot-orderBars": "https://github.com/emmerich/flot-orderBars.git",
77 - "jquery.flot.animator": "https://github.com/Codicode/flotanimator.git#3c256c0183d713fd3bf41d04417873928eb1a751",
78 - "jsonwebtoken": "^8.5.1",
79 - "jvectormap": "2.0.4",
80 - "line-awesome": "github:icons8/line-awesome",
81 - "messenger": "git+https://github.com/HubSpot/messenger.git#v1.4.2",
82 - "metrojs": "0.9.77",
83 - "moment": "^2.22.2",
84 - "moment-timezone": "^0.5.26",
85 - "nvd3": "1.8.6",
86 - "pretty": "^2.0.0",
87 - "prettysize": "^2.0.0",
88 - "rc-color-picker": "^1.2.6",
89 - "rc-hammerjs": "0.6.9",
90 - "react": "^16.5.2",
91 - "react-animated-number": "^0.4.4",
92 - "react-app-polyfill": "^0.1.3",
93 - "react-autosize-textarea": "^5.0.0",
94 - "react-bootstrap-slider": "^2.1.5",
95 - "react-bootstrap-table": "4.1.5",
96 - "react-datetime": "^2.16.1",
97 - "react-dev-utils": "^6.0.5",
98 - "react-dom": "^16.5.2",
99 - "react-draft-wysiwyg": "1.10.12",
100 - "react-dropzone": "^6.2.4",
101 - "react-flot": "^1.3.0",
102 - "react-google-maps": "^9.4.5",
103 - "react-images": "^0.5.19",
104 - "react-maskedinput": "^4.0.1",
105 - "react-mde": "2.3.4",
106 - "react-redux": "^5.0.7",
107 - "react-router": "^4.3.1",
108 - "react-router-dom": "^4.3.1",
109 - "react-router-hash-link": "^1.2.1",
110 - "react-scrollspy": "^3.3.5",
111 - "react-select": "^3.0.4",
112 - "react-select2-wrapper": "^1.0.4-beta6",
113 - "react-shuffle": "2.1.0",
114 - "react-slick": "^0.23.1",
115 - "react-sortable-hoc": "^0.8.3",
116 - "react-sortable-tree": "^2.2.0",
117 - "react-sparklines": "^1.7.0",
118 - "react-syntax-highlighter": "^10.1.2",
119 - "react-table": "6.7.6",
120 - "react-tagsinput": "^3.19.0",
121 - "react-toastify": "^5.1.1",
122 - "react-transition-group": "^2.5.2",
123 - "reactstrap": "7.1.0",
124 - "redux": "^4.0.1",
125 - "redux-thunk": "^2.3.0",
126 - "rickshaw": "1.6.6",
127 - "semantic-ui-react": "^0.87.3",
128 - "showdown": "1.8.6",
129 - "skycons": "^1.0.0",
130 - "widgster": "^1.0.0",
131 - "xlsx": "^0.14.4"
132 - },
133 - "devDependencies": {
134 - "@babel/core": "7.4.4",
135 - "@babel/plugin-proposal-class-properties": "7.4.4",
136 - "@babel/plugin-proposal-optional-chaining": "^7.2.0",
137 - "@svgr/webpack": "4.2.0",
138 - "babel-core": "7.0.0-bridge.0",
139 - "babel-eslint": "10.0.1",
140 - "babel-jest": "24.8.0",
141 - "babel-loader": "8.0.5",
142 - "babel-plugin-named-asset-import": "1.0.0-next.103",
143 - "babel-preset-react-app": "9.0.0",
144 - "bfj": "6.1.1",
145 - "bundle-loader": "0.5.6",
146 - "case-sensitive-paths-webpack-plugin": "2.2.0",
147 - "chalk": "^2.4.2",
148 - "css-loader": "2.1.1",
149 - "dotenv": "^8.2.0",
150 - "dotenv-expand": "^5.1.0",
151 - "eslint": "5.16.0",
152 - "eslint-config-react-app": "4.0.1",
153 - "eslint-loader": "2.1.1",
154 - "eslint-plugin-flowtype": "3.8.1",
155 - "eslint-plugin-import": "2.17.2",
156 - "eslint-plugin-jsx-a11y": "6.2.1",
157 - "eslint-plugin-react": "7.13.0",
158 - "eslint-plugin-react-hooks": "1.6.0",
159 - "expose-loader": "0.7.5",
160 - "file-loader": "3.0.1",
161 - "fs-extra": "7.0.1",
162 - "html-webpack-plugin": "4.0.0-alpha.2",
163 - "identity-obj-proxy": "3.0.0",
164 - "imports-loader": "0.8.0",
165 - "jest": "24.8.0",
166 - "jest-pnp-resolver": "1.2.1",
167 - "jest-resolve": "24.8.0",
168 - "lodash": "4.17.11",
169 - "mini-css-extract-plugin": "0.6.0",
170 - "node-sass": "4.12.0",
171 - "optimize-css-assets-webpack-plugin": "5.0.1",
172 - "pnp-webpack-plugin": "1.4.3",
173 - "postcss-flexbugs-fixes": "4.1.0",
174 - "postcss-loader": "3.0.0",
175 - "postcss-preset-env": "6.6.0",
176 - "postcss-safe-parser": "4.0.1",
177 - "resolve": "1.10.1",
178 - "sass-loader": "7.1.0",
179 - "style-loader": "0.23.0",
180 - "terser-webpack-plugin": "1.2.3",
181 - "url-loader": "1.1.2",
182 - "webpack": "^4.31.0",
183 - "webpack-dev-server": "3.3.1",
184 - "webpack-manifest-plugin": "2.0.4",
185 - "webpack-raphael": "2.1.4",
186 - "workbox-webpack-plugin": "4.3.1"
187 - },
188 - "resolutions": {
189 - "jquery": "3.3.1"
190 } 59 }
191 } 60 }
......

12 KB | W: | H:

37 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <html lang="en"> 2 <html lang="en">
3 <head> 3 <head>
4 - <meta charset="utf-8"> 4 + <meta charset="utf-8" />
5 - <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.png"> 5 + <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6 - <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> 6 + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css"/>
7 - <meta name="theme-color" content="#000000"> 7 + <meta name="viewport" content="width=device-width, initial-scale=1" />
8 + <meta name="theme-color" content="#000000" />
9 + <meta
10 + name="description"
11 + content="Web site created using create-react-app"
12 + />
13 + <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
8 <!-- 14 <!--
9 - manifest.json provides metadata used when your web app is added to the 15 + manifest.json provides metadata used when your web app is installed on a
10 - homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/ 16 + user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
11 --> 17 -->
12 - <link rel="manifest" href="%PUBLIC_URL%/manifest.json"> 18 + <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
13 <!-- 19 <!--
14 Notice the use of %PUBLIC_URL% in the tags above. 20 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. 21 It will be replaced with the URL of the `public` folder during the build.
...@@ -19,27 +25,10 @@ ...@@ -19,27 +25,10 @@
19 work correctly both with client-side routing and a non-root public URL. 25 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`. 26 Learn how to configure a non-root public URL by running `npm run build`.
21 --> 27 -->
22 - <title>Video Emergency Detection</title> 28 + <title>React App</title>
23 - <meta name="description" content="React Admin Dashboard Template built with Bootstrap, Redux and React Router by Flatlogic. Over 40 unique pages, hundreds of components and theme support.">
24 - <meta name="keywords" content="react admin, react dashboard, react admin template, react theme, react dashboard template, react dashboard template">
25 - <meta name="author" content="Flatlogic LLC.">
26 -
27 - <!-- Global site tag (gtag.js) - Google Analytics -->
28 - <script async src="https://www.googletagmanager.com/gtag/js?id=UA-36759672-9"></script>
29 - <script>
30 - window.dataLayer = window.dataLayer || [];
31 - function gtag(){dataLayer.push(arguments);}
32 - gtag('js', new Date());
33 -
34 - gtag('config', 'UA-36759672-9');
35 - </script>
36 -
37 - <!-- Yandex.Metrika counter --> <script type="text/javascript" > (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js", "ym"); ym(48020168, "init", { id:48020168, clickmap:true, trackLinks:true, accurateTrackBounce:true, webvisor:true, trackHash:true, ecommerce:"dataLayer" }); </script> <!-- /Yandex.Metrika counter -->
38 </head> 29 </head>
39 <body> 30 <body>
40 - <noscript> 31 + <noscript>You need to enable JavaScript to run this app.</noscript>
41 - You need to enable JavaScript to run this app.
42 - </noscript>
43 <div id="root"></div> 32 <div id="root"></div>
44 <!-- 33 <!--
45 This HTML file is a template. 34 This HTML file is a template.
......
1 { 1 {
2 - "short_name": "Sing App 5.0.0 - Isomorphic React Dashboard", 2 + "short_name": "React App",
3 "name": "Create React App Sample", 3 "name": "Create React App Sample",
4 "icons": [ 4 "icons": [
5 { 5 {
6 - "src": "/favicon.png", 6 + "src": "favicon.ico",
7 "sizes": "64x64 32x32 24x24 16x16", 7 "sizes": "64x64 32x32 24x24 16x16",
8 "type": "image/x-icon" 8 "type": "image/x-icon"
9 + },
10 + {
11 + "src": "logo192.png",
12 + "type": "image/png",
13 + "sizes": "192x192"
14 + },
15 + {
16 + "src": "logo512.png",
17 + "type": "image/png",
18 + "sizes": "512x512"
9 } 19 }
10 ], 20 ],
11 "start_url": ".", 21 "start_url": ".",
......
1 +# https://www.robotstxt.org/robotstxt.html
2 +User-agent: *
3 +Disallow:
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 -
18 -const path = require('path');
19 -const chalk = require('chalk');
20 -const fs = require('fs-extra');
21 -const webpack = require('webpack');
22 -const bfj = require('bfj');
23 -const config = require('../config/webpack.config.prod');
24 -const paths = require('../config/paths');
25 -const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
26 -const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
27 -const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
28 -const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
29 -const printBuildError = require('react-dev-utils/printBuildError');
30 -
31 -const measureFileSizesBeforeBuild =
32 - FileSizeReporter.measureFileSizesBeforeBuild;
33 -const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
34 -const useYarn = fs.existsSync(paths.yarnLockFile);
35 -
36 -// These sizes are pretty large. We'll warn for bundles exceeding them.
37 -const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
38 -const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
39 -
40 -const isInteractive = process.stdout.isTTY;
41 -
42 -// Warn and crash if required files are missing
43 -if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
44 - process.exit(1);
45 -}
46 -
47 -// Process CLI arguments
48 -const argv = process.argv.slice(2);
49 -const writeStatsJson = argv.indexOf('--stats') !== -1;
50 -
51 -// We require that you explictly set browsers and do not fall back to
52 -// browserslist defaults.
53 -const { checkBrowsers } = require('react-dev-utils/browsersHelper');
54 -checkBrowsers(paths.appPath, isInteractive)
55 - .then(() => {
56 - // First, read the current file sizes in build directory.
57 - // This lets us display how much they changed later.
58 - return measureFileSizesBeforeBuild(paths.appBuild);
59 - })
60 - .then(previousFileSizes => {
61 - // Remove all content but keep the directory so that
62 - // if you're in it, you don't end up in Trash
63 - fs.emptyDirSync(paths.appBuild);
64 - // Merge with the public folder
65 - copyPublicFolder();
66 - // Start the webpack build
67 - return build(previousFileSizes);
68 - })
69 - .then(
70 - ({ stats, previousFileSizes, warnings }) => {
71 - if (warnings.length) {
72 - console.log(chalk.yellow('Compiled with warnings.\n'));
73 - console.log(warnings.join('\n\n'));
74 - console.log(
75 - '\nSearch for the ' +
76 - chalk.underline(chalk.yellow('keywords')) +
77 - ' to learn more about each warning.'
78 - );
79 - console.log(
80 - 'To ignore, add ' +
81 - chalk.cyan('// eslint-disable-next-line') +
82 - ' to the line before.\n'
83 - );
84 - } else {
85 - console.log(chalk.green('Compiled successfully.\n'));
86 - }
87 -
88 - console.log('File sizes after gzip:\n');
89 - printFileSizesAfterBuild(
90 - stats,
91 - previousFileSizes,
92 - paths.appBuild,
93 - WARN_AFTER_BUNDLE_GZIP_SIZE,
94 - WARN_AFTER_CHUNK_GZIP_SIZE
95 - );
96 - console.log();
97 -
98 - const appPackage = require(paths.appPackageJson);
99 - const publicUrl = paths.publicUrl;
100 - const publicPath = config.output.publicPath;
101 - const buildFolder = path.relative(process.cwd(), paths.appBuild);
102 - printHostingInstructions(
103 - appPackage,
104 - publicUrl,
105 - publicPath,
106 - buildFolder,
107 - useYarn
108 - );
109 - },
110 - err => {
111 - console.log(chalk.red('Failed to compile.\n'));
112 - printBuildError(err);
113 - process.exit(1);
114 - }
115 - )
116 - .catch(err => {
117 - if (err && err.message) {
118 - console.log(err.message);
119 - }
120 - process.exit(1);
121 - });
122 -
123 -// Create the production build and print the deployment instructions.
124 -function build(previousFileSizes) {
125 - console.log('Creating an optimized production build...');
126 -
127 - let compiler = webpack(config);
128 - return new Promise((resolve, reject) => {
129 - compiler.run((err, stats) => {
130 - let messages;
131 - if (err) {
132 - if (!err.message) {
133 - return reject(err);
134 - }
135 - messages = formatWebpackMessages({
136 - errors: [err.message],
137 - warnings: [],
138 - });
139 - } else {
140 - messages = formatWebpackMessages(
141 - stats.toJson({ all: false, warnings: true, errors: true })
142 - );
143 - }
144 - if (messages.errors.length) {
145 - // Only keep the first error. Others are often indicative
146 - // of the same problem, but confuse the reader with noise.
147 - if (messages.errors.length > 1) {
148 - messages.errors.length = 1;
149 - }
150 - return reject(new Error(messages.errors.join('\n\n')));
151 - }
152 - if (
153 - process.env.CI &&
154 - (typeof process.env.CI !== 'string' ||
155 - process.env.CI.toLowerCase() !== 'false') &&
156 - messages.warnings.length
157 - ) {
158 - console.log(
159 - chalk.yellow(
160 - '\nTreating warnings as errors because process.env.CI = true.\n' +
161 - 'Most CI servers set it automatically.\n'
162 - )
163 - );
164 - return reject(new Error(messages.warnings.join('\n\n')));
165 - }
166 -
167 - const resolveArgs = {
168 - stats,
169 - previousFileSizes,
170 - warnings: messages.warnings,
171 - };
172 - if (writeStatsJson) {
173 - return bfj
174 - .write(paths.appBuild + '/bundle-stats.json', stats.toJson())
175 - .then(() => resolve(resolveArgs))
176 - .catch(error => reject(new Error(error)));
177 - }
178 -
179 - return resolve(resolveArgs);
180 - });
181 - });
182 -}
183 -
184 -function copyPublicFolder() {
185 - fs.copySync(paths.appPublic, paths.appBuild, {
186 - dereference: true,
187 - filter: file => file !== paths.appHtml,
188 - });
189 -}
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 -
18 -const fs = require('fs');
19 -const chalk = require('chalk');
20 -const webpack = require('webpack');
21 -const WebpackDevServer = require('webpack-dev-server');
22 -const clearConsole = require('react-dev-utils/clearConsole');
23 -const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
24 -const {
25 - choosePort,
26 - createCompiler,
27 - prepareProxy,
28 - prepareUrls,
29 -} = require('react-dev-utils/WebpackDevServerUtils');
30 -const openBrowser = require('react-dev-utils/openBrowser');
31 -const paths = require('../config/paths');
32 -const config = require('../config/webpack.config.dev');
33 -const createDevServerConfig = require('../config/webpackDevServer.config');
34 -
35 -const useYarn = fs.existsSync(paths.yarnLockFile);
36 -const isInteractive = process.stdout.isTTY;
37 -
38 -// Warn and crash if required files are missing
39 -if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
40 - process.exit(1);
41 -}
42 -
43 -// Tools like Cloud9 rely on this.
44 -const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
45 -const HOST = process.env.HOST || '0.0.0.0';
46 -
47 -if (process.env.HOST) {
48 - console.log(
49 - chalk.cyan(
50 - `Attempting to bind to HOST environment variable: ${chalk.yellow(
51 - chalk.bold(process.env.HOST)
52 - )}`
53 - )
54 - );
55 - console.log(
56 - `If this was unintentional, check that you haven't mistakenly set it in your shell.`
57 - );
58 - console.log(
59 - `Learn more here: ${chalk.yellow('http://bit.ly/CRA-advanced-config')}`
60 - );
61 - console.log();
62 -}
63 -
64 -// We require that you explictly set browsers and do not fall back to
65 -// browserslist defaults.
66 -const { checkBrowsers } = require('react-dev-utils/browsersHelper');
67 -checkBrowsers(paths.appPath, isInteractive)
68 - .then(() => {
69 - // We attempt to use the default port but if it is busy, we offer the user to
70 - // run on a different port. `choosePort()` Promise resolves to the next free port.
71 - return choosePort(HOST, DEFAULT_PORT);
72 - })
73 - .then(port => {
74 - if (port == null) {
75 - // We have not found a port.
76 - return;
77 - }
78 - const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
79 - const appName = require(paths.appPackageJson).name;
80 - const urls = prepareUrls(protocol, HOST, port);
81 - // Create a webpack compiler that is configured with custom messages.
82 - const compiler = createCompiler(webpack, config, appName, urls, useYarn);
83 - // Load proxy config
84 - const proxySetting = require(paths.appPackageJson).proxy;
85 - const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
86 - // Serve webpack assets generated by the compiler over a web server.
87 - const serverConfig = createDevServerConfig(
88 - proxyConfig,
89 - urls.lanUrlForConfig
90 - );
91 - const devServer = new WebpackDevServer(compiler, serverConfig);
92 - // Launch WebpackDevServer.
93 - devServer.listen(port, HOST, err => {
94 - if (err) {
95 - return console.log(err);
96 - }
97 - if (isInteractive) {
98 - clearConsole();
99 - }
100 - console.log(chalk.cyan('Starting the development server...\n'));
101 - openBrowser(urls.localUrlForBrowser);
102 - });
103 -
104 - ['SIGINT', 'SIGTERM'].forEach(function(sig) {
105 - process.on(sig, function() {
106 - devServer.close();
107 - process.exit();
108 - });
109 - });
110 - })
111 - .catch(err => {
112 - if (err && err.message) {
113 - console.log(err.message);
114 - }
115 - process.exit(1);
116 - });
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 -
19 -const jest = require('jest');
20 -const execSync = require('child_process').execSync;
21 -let argv = process.argv.slice(2);
22 -
23 -function isInGitRepository() {
24 - try {
25 - execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
26 - return true;
27 - } catch (e) {
28 - return false;
29 - }
30 -}
31 -
32 -function isInMercurialRepository() {
33 - try {
34 - execSync('hg --cwd . root', { stdio: 'ignore' });
35 - return true;
36 - } catch (e) {
37 - return false;
38 - }
39 -}
40 -
41 -// Watch unless on CI, in coverage mode, or explicitly running all tests
42 -if (
43 - !process.env.CI &&
44 - argv.indexOf('--coverage') === -1 &&
45 - argv.indexOf('--watchAll') === -1
46 -) {
47 - // https://github.com/facebook/create-react-app/issues/5210
48 - const hasSourceControl = isInGitRepository() || isInMercurialRepository();
49 - argv.push(hasSourceControl ? '--watch' : '--watchAll');
50 -}
51 -
52 -
53 -jest.run(argv);
1 import React from 'react'; 1 import React from 'react';
2 -import { connect } from 'react-redux';
3 import { Switch, Route, Redirect } from 'react-router'; 2 import { Switch, Route, Redirect } from 'react-router';
4 import { HashRouter } from 'react-router-dom'; 3 import { HashRouter } from 'react-router-dom';
5 -import { ToastContainer } from 'react-toastify';
6 -
7 -/* eslint-disable */
8 -import ErrorPage from '../pages/error';
9 -/* eslint-enable */
10 4
11 import '../styles/theme.scss'; 5 import '../styles/theme.scss';
12 -import LayoutComponent from '../components/Layout'; 6 +import LayoutComponent from '../components/Layout/Layout';
13 -
14 -const CloseButton = ({closeToast}) => <i onClick={closeToast} className="la la-close notifications-close"/>
15 7
16 class App extends React.PureComponent { 8 class App extends React.PureComponent {
17 render() { 9 render() {
18 return ( 10 return (
19 <div> 11 <div>
20 - <ToastContainer
21 - autoClose={5000}
22 - hideProgressBar
23 - closeButton={<CloseButton/>}
24 - />
25 <HashRouter> 12 <HashRouter>
26 <Switch> 13 <Switch>
27 <Route path="/" exact render={() => <Redirect to="/app/main"/>}/> 14 <Route path="/" exact render={() => <Redirect to="/app/main"/>}/>
28 <Route path="/app" exact render={() => <Redirect to="/app/main"/>}/> 15 <Route path="/app" exact render={() => <Redirect to="/app/main"/>}/>
29 <Route path="/app" component={LayoutComponent}/> 16 <Route path="/app" component={LayoutComponent}/>
30 - <Route path="/error" exact component={ErrorPage}/>
31 <Redirect from="*" to="/app/main/"/> 17 <Redirect from="*" to="/app/main/"/>
32 </Switch> 18 </Switch>
33 </HashRouter> 19 </HashRouter>
34 </div> 20 </div>
35 -
36 ); 21 );
37 } 22 }
38 } 23 }
39 24
40 -const mapStateToProps = state => ({ 25 +export default App;
41 -});
42 -
43 -export default connect(mapStateToProps)(App);
......
...@@ -13,103 +13,103 @@ import s from './Layout.module.scss'; ...@@ -13,103 +13,103 @@ import s from './Layout.module.scss';
13 import { DashboardThemes } from '../../reducers/layout'; 13 import { DashboardThemes } from '../../reducers/layout';
14 14
15 class Layout extends React.Component { 15 class Layout extends React.Component {
16 - static propTypes = { 16 + static propTypes = {
17 - sidebarStatic: PropTypes.bool, 17 + sidebarStatic: PropTypes.bool,
18 - sidebarOpened: PropTypes.bool, 18 + sidebarOpened: PropTypes.bool,
19 - dashboardTheme: PropTypes.string, 19 + dashboardTheme: PropTypes.string,
20 - dispatch: PropTypes.func.isRequired, 20 + dispatch: PropTypes.func.isRequired,
21 - }; 21 + };
22 - 22 +
23 - static defaultProps = { 23 + static defaultProps = {
24 - sidebarStatic: false, 24 + sidebarStatic: false,
25 - sidebarOpened: false, 25 + sidebarOpened: false,
26 - dashboardTheme: DashboardThemes.DARK 26 + dashboardTheme: DashboardThemes.DARK
27 - }; 27 + };
28 - constructor(props) { 28 + constructor(props) {
29 - super(props); 29 + super(props);
30 - this.handleSwipe = this.handleSwipe.bind(this); 30 + this.handleSwipe = this.handleSwipe.bind(this);
31 - }
32 -
33 - async componentDidMount() {
34 - const staticSidebar = JSON.parse(localStorage.getItem('staticSidebar'));
35 - if (staticSidebar && window.innerWidth > 768) {
36 - this.props.dispatch(toggleSidebar());
37 - } else if (this.props.sidebarOpened) {
38 - setTimeout(() => {
39 - this.props.dispatch(closeSidebar());
40 - this.props.dispatch(changeActiveSidebarItem(null));
41 - }, 2500);
42 - }
43 - this.handleResize();
44 - window.addEventListener('resize', this.handleResize.bind(this));
45 - }
46 -
47 - componentWillUnmount() {
48 - window.removeEventListener('resize', this.handleResize.bind(this));
49 - }
50 -
51 - handleResize() {
52 - if (window.innerWidth <= 768 && this.props.sidebarStatic) {
53 - this.props.dispatch(toggleSidebar());
54 } 31 }
55 - } 32 +
56 - 33 + async componentDidMount() {
57 - handleSwipe(e) { 34 + const staticSidebar = JSON.parse(localStorage.getItem('staticSidebar'));
58 - if ('ontouchstart' in window) { 35 + if (staticSidebar && window.innerWidth > 768) {
59 - this.props.dispatch(openSidebar()); 36 + this.props.dispatch(toggleSidebar());
60 - return; 37 + } else if (this.props.sidebarOpened) {
38 + setTimeout(() => {
39 + this.props.dispatch(closeSidebar());
40 + this.props.dispatch(changeActiveSidebarItem(null));
41 + }, 2500);
61 } 42 }
62 - if (e.direction === 2 && this.props.sidebarOpened) { 43 + this.handleResize();
63 - this.props.dispatch(closeSidebar()); 44 + window.addEventListener('resize', this.handleResize.bind(this));
64 - return; 45 + }
46 +
47 + componentWillUnmount() {
48 + window.removeEventListener('resize', this.handleResize.bind(this));
49 + }
50 +
51 + handleResize() {
52 + if (window.innerWidth <= 768 && this.props.sidebarStatic) {
53 + this.props.dispatch(toggleSidebar());
65 } 54 }
66 - } 55 + }
67 - 56 +
68 - render() { 57 + handleSwipe(e) {
69 - return ( 58 + if ('ontouchstart' in window) {
70 - <div 59 + this.props.dispatch(openSidebar());
71 - className={[ 60 + return;
72 - s.root, 61 + }
73 - this.props.sidebarStatic ? s.sidebarStatic : '', 62 + if (e.direction === 2 && this.props.sidebarOpened) {
74 - !this.props.sidebarOpened ? s.sidebarClose : '', 63 + this.props.dispatch(closeSidebar());
75 - 'sing-dashboard', 64 + return;
76 - 'dashboard-' + this.props.dashboardTheme, 65 + }
77 - ].join(' ')} 66 + }
78 - > 67 +
79 - <Sidebar /> 68 + render() {
80 - <div className={s.wrap}> 69 + return (
81 - <Hammer onSwipe={this.handleSwipe}> 70 + <div
82 - <main className={s.content}> 71 + className={[
83 - <TransitionGroup> 72 + s.root,
84 - <CSSTransition 73 + this.props.sidebarStatic ? s.sidebarStatic : '',
85 - key={this.props.location.pathname} 74 + !this.props.sidebarOpened ? s.sidebarClose : '',
86 - classNames="fade" 75 + 'video emergency analysis',
87 - timeout={200} 76 + 'video emergency-' + this.props.dashboardTheme,
88 - > 77 + ].join(' ')}
89 - <Switch> 78 + >
90 - <Route path="/app/main/" exact component={Main} /> 79 + <Sidebar />
91 - <Route path="/app/subject" exact component={Subject} /> 80 + <div className={s.wrap}>
92 - </Switch> 81 + <Hammer onSwipe={this.handleSwipe}>
93 - </CSSTransition> 82 + <main className={s.content}>
94 - </TransitionGroup> 83 + <TransitionGroup>
95 - <footer className={s.contentFooter}> 84 + <CSSTransition
96 - OSS project 85 + key={this.props.location.pathname}
97 - </footer> 86 + classNames="fade"
98 - </main> 87 + timeout={200}
99 - </Hammer> 88 + >
89 + <Switch>
90 + <Route path="/app/main/" exact component={Main} />
91 + <Route path="/app/subject" exact component={Subject} />
92 + </Switch>
93 + </CSSTransition>
94 + </TransitionGroup>
95 + <footer className={s.contentFooter}>
96 + OSS project
97 + </footer>
98 + </main>
99 + </Hammer>
100 + </div>
100 </div> 101 </div>
101 - </div> 102 + );
102 - ); 103 + }
103 } 104 }
104 -} 105 +
105 - 106 + function mapStateToProps(store) {
106 -function mapStateToProps(store) { 107 + return {
107 - return { 108 + sidebarOpened: store.navigation.sidebarOpened,
108 - sidebarOpened: store.navigation.sidebarOpened, 109 + sidebarStatic: store.navigation.sidebarStatic,
109 - sidebarStatic: store.navigation.sidebarStatic, 110 + dashboardTheme: store.layout.dashboardTheme,
110 - dashboardTheme: store.layout.dashboardTheme, 111 + labelDataGroup: store.labelDataGroup,
111 - labelDataGroup: store.labelDataGroup, 112 + };
112 - }; 113 + }
113 -} 114 +
114 - 115 + export default withRouter(connect(mapStateToProps)(Layout));
115 -export default withRouter(connect(mapStateToProps)(Layout));
...\ No newline at end of file ...\ No newline at end of file
......
1 -{
2 - "name": "Layout",
3 - "version": "0.0.0",
4 - "private": true,
5 - "main": "./Layout.js"
6 -}
1 -{
2 - "name": "Loader",
3 - "version": "0.0.0",
4 - "private": true,
5 - "main": "./Loader.js"
6 -}
...@@ -73,7 +73,7 @@ class LinksGroup extends Component { ...@@ -73,7 +73,7 @@ class LinksGroup extends Component {
73 target={this.props.target} 73 target={this.props.target}
74 > 74 >
75 <span className={classnames('icon', s.icon)}> 75 <span className={classnames('icon', s.icon)}>
76 - <i className={`fi ${this.props.iconName}`} /> 76 + <i className={this.props.iconName} />
77 </span> 77 </span>
78 {this.props.header} {this.props.label && <sup className={`${s.headerLabel} text-${this.props.labelColor || 'warning'}`}>{this.props.label}</sup>} 78 {this.props.header} {this.props.label && <sup className={`${s.headerLabel} text-${this.props.labelColor || 'warning'}`}>{this.props.label}</sup>}
79 {this.props.badge && <Badge className={s.badge} color="warning" pill>9</Badge>} 79 {this.props.badge && <Badge className={s.badge} color="warning" pill>9</Badge>}
...@@ -99,7 +99,7 @@ class LinksGroup extends Component { ...@@ -99,7 +99,7 @@ class LinksGroup extends Component {
99 </NavLink> 99 </NavLink>
100 </li> 100 </li>
101 ); 101 );
102 - } 102 + }
103 /* eslint-disable */ 103 /* eslint-disable */
104 return ( 104 return (
105 <Route 105 <Route
...@@ -114,7 +114,7 @@ class LinksGroup extends Component { ...@@ -114,7 +114,7 @@ class LinksGroup extends Component {
114 > 114 >
115 {this.props.isHeader ? 115 {this.props.isHeader ?
116 <span className={classnames('icon', s.icon)}> 116 <span className={classnames('icon', s.icon)}>
117 - <i className={`fi ${this.props.iconName}`} /> 117 + <i className={this.props.iconName} />
118 </span> : null 118 </span> : null
119 } 119 }
120 {this.props.header} {this.props.label && <sup className={`${s.headerLabel} text-${this.props.labelColor || 'warning'} ml-1`}>{this.props.label}</sup>} 120 {this.props.header} {this.props.label && <sup className={`${s.headerLabel} text-${this.props.labelColor || 'warning'} ml-1`}>{this.props.label}</sup>}
......
...@@ -78,14 +78,14 @@ ...@@ -78,14 +78,14 @@
78 &:hover { 78 &:hover {
79 color: $sidebar-item-active-color; 79 color: $sidebar-item-active-color;
80 } 80 }
81 - 81 +
82 .icon { 82 .icon {
83 border-radius: 50%; 83 border-radius: 50%;
84 - background-color: $sidebar-item-active-color; 84 + background-color: #ffc247;
85 opacity: 1; 85 opacity: 1;
86 86
87 i { 87 i {
88 - color: var(--sidebar-bg-color); 88 + color: #313947;
89 } 89 }
90 } 90 }
91 } 91 }
...@@ -124,6 +124,7 @@ ...@@ -124,6 +124,7 @@
124 } 124 }
125 } 125 }
126 126
127 +
127 ul { 128 ul {
128 background: var(--sidebar-action-bg); 129 background: var(--sidebar-action-bg);
129 padding: $spacer; 130 padding: $spacer;
......
...@@ -54,7 +54,7 @@ class Sidebar extends React.Component { ...@@ -54,7 +54,7 @@ class Sidebar extends React.Component {
54 className={[s.root, this.props.sidebarStatic ? s.staticSidebar : '', !this.props.sidebarOpened ? s.sidebarClose : ''].join(' ')} 54 className={[s.root, this.props.sidebarStatic ? s.staticSidebar : '', !this.props.sidebarOpened ? s.sidebarClose : ''].join(' ')}
55 > 55 >
56 <header className={s.logo}> 56 <header className={s.logo}>
57 - <img src="/images/emergency.png" style={{width: '112px', padding: '7px'}} alt="Emergency Inc. logo"/> 57 + <img src="/images/emergency.png" style={{width: '130px', padding: '7px'}} alt="Emergency Inc. logo"/>
58 </header> 58 </header>
59 <ul className={s.nav}> 59 <ul className={s.nav}>
60 <LinksGroup 60 <LinksGroup
...@@ -62,24 +62,24 @@ class Sidebar extends React.Component { ...@@ -62,24 +62,24 @@ class Sidebar extends React.Component {
62 activeItem={this.props.activeItem} 62 activeItem={this.props.activeItem}
63 header="영상 분석" 63 header="영상 분석"
64 isHeader 64 isHeader
65 - iconName="flaticon-record" 65 + iconName="fas fa-camera"
66 link="/app/main" 66 link="/app/main"
67 index="main" 67 index="main"
68 - childrenLinks={[ 68 + // childrenLinks={[
69 - { 69 + // {
70 - header: 'Phone', link: '/app/file/phone', 70 + // header: 'Phone', link: '/app/file/phone',
71 - }, 71 + // },
72 - { 72 + // {
73 - header: 'RaspberryPi', link: '/app/file/raspberrypi', 73 + // header: 'RaspberryPi', link: '/app/file/raspberrypi',
74 - }, 74 + // },
75 - ]} 75 + // ]}
76 /> 76 />
77 <LinksGroup 77 <LinksGroup
78 onActiveSidebarItemChange={activeItem => this.props.dispatch(changeActiveSidebarItem(activeItem))} 78 onActiveSidebarItemChange={activeItem => this.props.dispatch(changeActiveSidebarItem(activeItem))}
79 activeItem={this.props.activeItem} 79 activeItem={this.props.activeItem}
80 header="사진 등록" 80 header="사진 등록"
81 isHeader 81 isHeader
82 - iconName="flaticon-user" 82 + iconName="fas fa-user"
83 link="/app/subject" 83 link="/app/subject"
84 index="subject" 84 index="subject"
85 /> 85 />
......
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
7 top: 0; 7 top: 0;
8 bottom: 0; 8 bottom: 0;
9 border-right: $sidebar-border; 9 border-right: $sidebar-border;
10 - background-color: var(--sidebar-bg-color); 10 + background-color: #313947;
11 - color: var(--sidebar-color); 11 + color: #a6b2c1;
12 overflow-y: auto; 12 overflow-y: auto;
13 13
14 @include scroll-bar($sidebar-scrollbar-bg); 14 @include scroll-bar($sidebar-scrollbar-bg);
......
1 import React from 'react'; 1 import React from 'react';
2 import PropTypes from 'prop-types'; 2 import PropTypes from 'prop-types';
3 -import jQuery from 'jquery';
4 -import { UncontrolledTooltip } from 'reactstrap';
5 -import 'imports-loader?window.jQuery=jquery,this=>window!widgster'; // eslint-disable-line
6 import s from './Widget.module.scss'; 3 import s from './Widget.module.scss';
7 -import Loader from '../Loader'; // eslint-disable-line css-modules/no-unused-class 4 +import Loader from '../Loader/Loader';
8 5
9 class Widget extends React.Component { 6 class Widget extends React.Component {
10 static propTypes = { 7 static propTypes = {
...@@ -14,17 +11,7 @@ class Widget extends React.Component { ...@@ -14,17 +11,7 @@ class Widget extends React.Component {
14 PropTypes.arrayOf(PropTypes.node), 11 PropTypes.arrayOf(PropTypes.node),
15 PropTypes.node, 12 PropTypes.node,
16 ]), 13 ]),
17 - close: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
18 - fullscreen: PropTypes.bool,
19 - collapse: PropTypes.bool,
20 - refresh: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
21 - settings: PropTypes.bool,
22 - settingsInverse: PropTypes.bool,
23 - tooltipPlacement: PropTypes.string,
24 - showTooltip: PropTypes.bool,
25 bodyClass: PropTypes.string, 14 bodyClass: PropTypes.string,
26 - customControls: PropTypes.node,
27 - options: PropTypes.object, //eslint-disable-line,
28 fetchingData: PropTypes.bool 15 fetchingData: PropTypes.bool
29 }; 16 };
30 17
...@@ -32,17 +19,7 @@ class Widget extends React.Component { ...@@ -32,17 +19,7 @@ class Widget extends React.Component {
32 title: null, 19 title: null,
33 className: '', 20 className: '',
34 children: [], 21 children: [],
35 - close: false,
36 - fullscreen: false,
37 - collapse: false,
38 - refresh: false,
39 - settings: false,
40 - settingsInverse: false,
41 - tooltipPlacement: 'bottom',
42 - showTooltip: false,
43 bodyClass: '', 22 bodyClass: '',
44 - customControls: null,
45 - options: {},
46 fetchingData: false 23 fetchingData: false
47 }; 24 };
48 25
...@@ -53,33 +30,15 @@ class Widget extends React.Component { ...@@ -53,33 +30,15 @@ class Widget extends React.Component {
53 }; 30 };
54 } 31 }
55 32
56 - componentDidMount() {
57 - const options = this.props.options;
58 - options.bodySelector = '.widget-body';
59 - jQuery(this.el).widgster(options);
60 - }
61 -
62 render() { 33 render() {
63 const { 34 const {
64 title, 35 title,
65 className, 36 className,
66 children, 37 children,
67 - close,
68 - fullscreen,
69 - collapse,
70 - refresh,
71 - settings,
72 - settingsInverse,
73 - tooltipPlacement,
74 - showTooltip,
75 bodyClass, 38 bodyClass,
76 - customControls,
77 fetchingData, 39 fetchingData,
78 - options, //eslint-disable-line
79 ...attributes 40 ...attributes
80 } = this.props; 41 } = this.props;
81 - const randomId = this.state.randomId;
82 - const mainControls = !!(close || fullscreen || collapse || refresh || settings || settingsInverse);
83 return ( 42 return (
84 <section 43 <section
85 className={['widget', s.widget, className].join(' ')} 44 className={['widget', s.widget, className].join(' ')}
...@@ -92,101 +51,6 @@ class Widget extends React.Component { ...@@ -92,101 +51,6 @@ class Widget extends React.Component {
92 : <header className={s.title}>{title}</header> 51 : <header className={s.title}>{title}</header>
93 ) 52 )
94 } 53 }
95 - {
96 - !customControls && mainControls && (
97 - <div className={`${s.widgetControls} widget-controls`}>
98 - {settings && (
99 - <button><i className="la la-cog" /></button>
100 - )}
101 - {settingsInverse && (
102 - <button className={`bg-gray-transparent ${s.inverse}`}><i
103 - className="la la-cog text-white"
104 - /></button>
105 - )}
106 - {refresh && (
107 - <button data-widgster="load" id={`reloadId-${randomId}`}>
108 - {typeof refresh === 'string' ?
109 - <strong className="text-gray-light">{refresh}</strong> :
110 - <i className="la la-refresh" />}
111 - {showTooltip && (
112 - <UncontrolledTooltip
113 - placement={tooltipPlacement}
114 - target={`reloadId-${randomId}`}
115 - >Reload</UncontrolledTooltip>
116 - )}
117 - </button>
118 - )}
119 - {fullscreen && (
120 - <button data-widgster="fullscreen" id={`fullscreenId-${randomId}`}>
121 - <i className="glyphicon glyphicon-resize-full" />
122 - {showTooltip && (
123 - <UncontrolledTooltip
124 - placement={tooltipPlacement}
125 - target={`fullscreenId-${randomId}`}
126 - >Fullscreen</UncontrolledTooltip>
127 - )}
128 - </button>
129 - )}
130 - {fullscreen && (
131 - <button data-widgster="restore" id={`restoreId-${randomId}`}>
132 - <i className="glyphicon glyphicon-resize-small" />
133 - {showTooltip && (
134 - <UncontrolledTooltip
135 - placement={tooltipPlacement}
136 - target={`restoreId-${randomId}`}
137 - >Restore</UncontrolledTooltip>
138 - )}
139 - </button>
140 - )}
141 - {collapse && (
142 - <span>
143 - <button data-widgster="collapse" id={`collapseId-${randomId}`}>
144 - <i className="la la-angle-down" />
145 - {showTooltip && (
146 - <UncontrolledTooltip
147 - placement={tooltipPlacement}
148 - target={`collapseId-${randomId}`}
149 - >Collapse</UncontrolledTooltip>
150 - )}
151 - </button>
152 - </span>
153 - )}
154 - {collapse && (
155 - <span>
156 - <button data-widgster="expand" id={`expandId-${randomId}`}>
157 - <i className="la la-angle-up" />
158 - {showTooltip && (
159 - <UncontrolledTooltip
160 - placement={tooltipPlacement}
161 - target={`expandId-${randomId}`}
162 - >Expand</UncontrolledTooltip>
163 - )}
164 - </button>
165 - </span>
166 - )}
167 -
168 - {close && (
169 - <button data-widgster="close" id={`closeId-${randomId}`}>
170 - {typeof close === 'string' ?
171 - <strong className="text-gray-light">{close}</strong> :
172 - <i className="la la-remove" />}
173 - {showTooltip && (
174 - <UncontrolledTooltip
175 - placement={tooltipPlacement}
176 - target={`closeId-${randomId}`}
177 - >Close</UncontrolledTooltip>
178 - )}
179 - </button>
180 - )}
181 - </div>
182 - )}
183 - {
184 - customControls && (
185 - <div className={`${s.widgetControls} widget-controls`}>
186 - {customControls}
187 - </div>
188 - )
189 - }
190 <div className={`${s.widgetBody} widget-body ${bodyClass}`}> 54 <div className={`${s.widgetBody} widget-body ${bodyClass}`}>
191 {fetchingData ? <Loader className={s.widgetLoader} size={40}/> : children} 55 {fetchingData ? <Loader className={s.widgetLoader} size={40}/> : children}
192 </div> 56 </div>
...@@ -195,4 +59,4 @@ class Widget extends React.Component { ...@@ -195,4 +59,4 @@ class Widget extends React.Component {
195 } 59 }
196 } 60 }
197 61
198 -export default Widget; 62 +export default Widget;
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -7,10 +7,6 @@ ...@@ -7,10 +7,6 @@
7 @include clearfix(); 7 @include clearfix();
8 } 8 }
9 9
10 -:global .widget.collapsed {
11 - min-height: unset;
12 -}
13 -
14 .widget { 10 .widget {
15 display: block; 11 display: block;
16 position: relative; 12 position: relative;
...@@ -76,51 +72,6 @@ ...@@ -76,51 +72,6 @@
76 } 72 }
77 } 73 }
78 74
79 -.widgetControls + .widgetBody {
80 - margin-top: $widget-padding-vertical;
81 -}
82 -
83 -.widgetControls,
84 -:global(.widget-controls) {
85 - position: absolute;
86 - z-index: 1;
87 - top: 0;
88 - right: 0;
89 - padding: 14px;
90 - font-size: $font-size-sm;
91 -
92 - button {
93 - padding: 1px 4px;
94 - border-radius: 4px;
95 - color: rgba($black, 0.4);
96 - background: transparent;
97 - border: none;
98 -
99 - @include transition(color 0.15s ease-in-out);
100 -
101 - &:hover {
102 - color: rgba($black, 0.1);
103 - text-decoration: none;
104 - }
105 -
106 - &:active,
107 - &:focus {
108 - outline: none;
109 - }
110 -
111 - :global {
112 - .la {
113 - position: relative;
114 - top: 2px;
115 - }
116 -
117 - .glyphicon {
118 - font-size: 0.7rem;
119 - }
120 - }
121 - }
122 -}
123 -
124 .inverse { 75 .inverse {
125 top: 2px; 76 top: 2px;
126 position: relative; 77 position: relative;
......
1 -{
2 - "name": "Widget",
3 - "version": "0.0.0",
4 - "private": true,
5 - "main": "./Widget.js"
6 -}
1 -const hostApi = process.env.NODE_ENV === "development" ? "http://localhost" : "http://localhost";
2 -const portApi = process.env.NODE_ENV === "development" ? 8080 : 4000;
3 -const baseURLApi = `${hostApi}${portApi ? `:${portApi}` : ``}`;
4 -
5 -export default {
6 - hostApi,
7 - portApi,
8 - baseURLApi
9 -};
...\ No newline at end of file ...\ No newline at end of file
1 -<?xml version="1.0" encoding="utf-8"?>
2 -<!-- Generator: Adobe Illustrator 19.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3 -<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4 - viewBox="0 0 30 30" style="enable-background:new 0 0 30 30;" xml:space="preserve">
5 -<g id="Слой_1">
6 - <rect x="0" y="0" width="13.9" height="30"/>
7 -</g>
8 -<g id="Слой_1__x28_копия_x29_">
9 - <rect x="16.1" y="0" width="13.9" height="30"/>
10 -</g>
11 -</svg>
1 -<?xml version="1.0" encoding="utf-8"?>
2 -<!-- Generator: Adobe Illustrator 19.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3 -<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4 - viewBox="0 0 30 30" style="enable-background:new 0 0 30 30;" xml:space="preserve">
5 -<g id="Слой_1">
6 - <rect x="0" y="0" width="8.3" height="30"/>
7 -</g>
8 -<g id="Слой_1__x28_копия_x29_">
9 - <rect x="21.7" y="0" width="8.3" height="30"/>
10 -</g>
11 -<g id="Слой_1__x28_копия2_x29_">
12 - <rect x="10.8" y="0" width="8.3" height="30"/>
13 -</g>
14 -</svg>
1 -<?xml version="1.0" encoding="utf-8"?>
2 -<!-- Generator: Adobe Illustrator 19.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3 -<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4 - viewBox="0 0 30 30" style="enable-background:new 0 0 30 30;" xml:space="preserve">
5 -<g id="Слой_1">
6 - <rect x="0" y="0" width="6.2" height="30"/>
7 -</g>
8 -<g id="Слой_1__x28_копия_x29_">
9 - <rect x="23.8" y="0" width="6.2" height="30"/>
10 -</g>
11 -<g id="Слой_1__x28_копия2_x29_">
12 - <rect x="15.9" y="0" width="6.2" height="30"/>
13 -</g>
14 -<g id="Слой_1__x28_копия3_x29_">
15 - <rect x="8" y="0" width="6.2" height="30"/>
16 -</g>
17 -</svg>
1 -<?xml version="1.0" encoding="iso-8859-1"?>
2 -<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3 -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 49.94 49.94" style="enable-background:new 0 0 49.94 49.94;" xml:space="preserve" width="512px" height="512px">
4 -<path d="M48.856,22.73c0.983-0.958,1.33-2.364,0.906-3.671c-0.425-1.307-1.532-2.24-2.892-2.438l-12.092-1.757 c-0.515-0.075-0.96-0.398-1.19-0.865L28.182,3.043c-0.607-1.231-1.839-1.996-3.212-1.996c-1.372,0-2.604,0.765-3.211,1.996 L16.352,14c-0.23,0.467-0.676,0.79-1.191,0.865L3.069,16.622c-1.359,0.197-2.467,1.131-2.892,2.438 c-0.424,1.307-0.077,2.713,0.906,3.671l8.749,8.528c0.373,0.364,0.544,0.888,0.456,1.4L8.224,44.701 c-0.183,1.06,0.095,2.091,0.781,2.904c1.066,1.267,2.927,1.653,4.415,0.871l10.814-5.686c0.452-0.237,1.021-0.235,1.472,0 l10.815,5.686c0.526,0.277,1.087,0.417,1.666,0.417c1.057,0,2.059-0.47,2.748-1.288c0.687-0.813,0.964-1.846,0.781-2.904 l-2.065-12.042c-0.088-0.513,0.083-1.036,0.456-1.4L48.856,22.73z" fill="#363f4e"/>
5 -<g>
6 -</g>
7 -<g>
8 -</g>
9 -<g>
10 -</g>
11 -<g>
12 -</g>
13 -<g>
14 -</g>
15 -<g>
16 -</g>
17 -<g>
18 -</g>
19 -<g>
20 -</g>
21 -<g>
22 -</g>
23 -<g>
24 -</g>
25 -<g>
26 -</g>
27 -<g>
28 -</g>
29 -<g>
30 -</g>
31 -<g>
32 -</g>
33 -<g>
34 -</g>
35 -</svg>
1 -<?xml version="1.0" encoding="iso-8859-1"?>
2 -<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3 -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 49.94 49.94" style="enable-background:new 0 0 49.94 49.94;" xml:space="preserve" width="512px" height="512px">
4 -<path d="M48.856,22.731c0.983-0.958,1.33-2.364,0.906-3.671c-0.425-1.307-1.532-2.24-2.892-2.438l-12.092-1.757 c-0.515-0.075-0.96-0.398-1.19-0.865L28.182,3.043c-0.607-1.231-1.839-1.996-3.212-1.996c-1.372,0-2.604,0.765-3.211,1.996 L16.352,14c-0.23,0.467-0.676,0.79-1.191,0.865L3.069,16.623C1.71,16.82,0.603,17.753,0.178,19.06 c-0.424,1.307-0.077,2.713,0.906,3.671l8.749,8.528c0.373,0.364,0.544,0.888,0.456,1.4L8.224,44.702 c-0.232,1.353,0.313,2.694,1.424,3.502c1.11,0.809,2.555,0.914,3.772,0.273l10.814-5.686c0.461-0.242,1.011-0.242,1.472,0 l10.815,5.686c0.528,0.278,1.1,0.415,1.669,0.415c0.739,0,1.475-0.231,2.103-0.688c1.111-0.808,1.656-2.149,1.424-3.502 L39.651,32.66c-0.088-0.513,0.083-1.036,0.456-1.4L48.856,22.731z M37.681,32.998l2.065,12.042c0.104,0.606-0.131,1.185-0.629,1.547 c-0.499,0.361-1.12,0.405-1.665,0.121l-10.815-5.687c-0.521-0.273-1.095-0.411-1.667-0.411s-1.145,0.138-1.667,0.412l-10.813,5.686 c-0.547,0.284-1.168,0.24-1.666-0.121c-0.498-0.362-0.732-0.94-0.629-1.547l2.065-12.042c0.199-1.162-0.186-2.348-1.03-3.17 L2.48,21.299c-0.441-0.43-0.591-1.036-0.4-1.621c0.19-0.586,0.667-0.988,1.276-1.077l12.091-1.757 c1.167-0.169,2.176-0.901,2.697-1.959l5.407-10.957c0.272-0.552,0.803-0.881,1.418-0.881c0.616,0,1.146,0.329,1.419,0.881 l5.407,10.957c0.521,1.058,1.529,1.79,2.696,1.959l12.092,1.757c0.609,0.089,1.086,0.491,1.276,1.077 c0.19,0.585,0.041,1.191-0.4,1.621l-8.749,8.528C37.866,30.65,37.481,31.835,37.681,32.998z" fill="#363f4e"/>
5 -<g>
6 -</g>
7 -<g>
8 -</g>
9 -<g>
10 -</g>
11 -<g>
12 -</g>
13 -<g>
14 -</g>
15 -<g>
16 -</g>
17 -<g>
18 -</g>
19 -<g>
20 -</g>
21 -<g>
22 -</g>
23 -<g>
24 -</g>
25 -<g>
26 -</g>
27 -<g>
28 -</g>
29 -<g>
30 -</g>
31 -<g>
32 -</g>
33 -<g>
34 -</g>
35 -</svg>
...@@ -3,14 +3,11 @@ import ReactDOM from 'react-dom'; ...@@ -3,14 +3,11 @@ import ReactDOM from 'react-dom';
3 import { createStore, applyMiddleware } from 'redux'; 3 import { createStore, applyMiddleware } from 'redux';
4 import { Provider } from 'react-redux' 4 import { Provider } from 'react-redux'
5 import ReduxThunk from 'redux-thunk' 5 import ReduxThunk from 'redux-thunk'
6 -import axios from 'axios';
7 -
8 import App from './components/App'; 6 import App from './components/App';
9 -import config from './config'; 7 +
10 import reducers from './reducers'; 8 import reducers from './reducers';
11 9
12 -axios.defaults.baseURL = config.baseURLApi; 10 +import * as serviceWorker from './serviceWorker';
13 -axios.defaults.headers.common['Content-Type'] = "application/json";
14 11
15 const store = createStore( 12 const store = createStore(
16 reducers, 13 reducers,
...@@ -18,8 +15,13 @@ const store = createStore( ...@@ -18,8 +15,13 @@ const store = createStore(
18 ); 15 );
19 16
20 ReactDOM.render( 17 ReactDOM.render(
21 - <Provider store={store}> 18 + <Provider store={store}>
22 - <App /> 19 + <App />
23 - </Provider>, 20 + </Provider>,
24 - document.getElementById('root') 21 + document.getElementById('root')
25 ); 22 );
23 +
24 +// If you want your app to work offline and load faster, you can change
25 +// unregister() to register() below. Note this comes with some pitfalls.
26 +// Learn more about service workers: https://bit.ly/CRA-PWA
27 +serviceWorker.unregister();
......
1 -import React from 'react';
2 -import {
3 - Container,
4 - Form,
5 - FormGroup,
6 - Input,
7 - Button,
8 -} from 'reactstrap';
9 -import { Link } from 'react-router-dom';
10 -
11 -import s from './ErrorPage.module.scss';
12 -
13 -class ErrorPage extends React.Component {
14 - render() {
15 - return (
16 - <div className={s.errorPage}>
17 - <Container>
18 - <div className={`${s.errorContainer} mx-auto`}>
19 - <h1 className={s.errorCode}>404</h1>
20 - <p className={s.errorInfo}>
21 - Opps, it seems that this page does not exist.
22 - </p>
23 - <p className={[s.errorHelp, 'mb-3'].join(' ')}>
24 - If you are sure it should, search for it.
25 - </p>
26 - <Form method="get">
27 - <FormGroup>
28 - <Input className="input-no-border" type="text" placeholder="Search Pages" />
29 - </FormGroup>
30 - <Link to="app/extra/search">
31 - <Button className={s.errorBtn} type="submit" color="inverse">
32 - Search <i className="fa fa-search text-warning ml-xs" />
33 - </Button>
34 - </Link>
35 - </Form>
36 - </div>
37 - <footer className={s.pageFooter}>
38 - 2019 &copy; Sing App - React Admin Dashboard Template.
39 - </footer>
40 - </Container>
41 - </div>
42 - );
43 - }
44 -}
45 -
46 -export default ErrorPage;
1 -@import '../../styles/app';
2 -
3 -.errorPage {
4 - padding-top: 5%;
5 - height: 100vh;
6 -}
7 -
8 -.errorContainer {
9 - width: 365px;
10 - text-align: center;
11 -}
12 -
13 -.errorBtn {
14 - padding-left: 35px;
15 - padding-right: 35px;
16 -}
17 -
18 -.errorCode {
19 - margin: 20px;
20 - font-size: 80px;
21 - font-weight: $font-weight-normal;
22 - color: $gray-800;
23 -
24 - @include media-breakpoint-up(md) {
25 - font-size: 180px;
26 - }
27 -}
28 -
29 -.errorInfo {
30 - font-size: 20px;
31 - color: $gray-800;
32 -}
33 -
34 -.errorHelp {
35 - font-size: 14px;
36 -}
37 -
38 -.pageFooter {
39 - position: absolute;
40 - bottom: 30px;
41 - left: 0;
42 - right: 0;
43 - width: 100%;
44 - font-size: $font-size-mini;
45 - color: $text-muted;
46 - text-align: center;
47 -}
1 -{
2 - "name": "error",
3 - "version": "0.0.0",
4 - "private": true,
5 - "main": "./ErrorPage.js"
6 -}
This diff is collapsed. Click to expand it.
1 -import React from 'react';
2 -import {
3 - Breadcrumb,
4 - BreadcrumbItem,
5 - Row,
6 - Col,
7 - Table,
8 - Button,
9 -} from 'reactstrap';
10 -
11 -import Widget from '../../../../components/Widget';
12 -
13 -const tableData = [
14 - {
15 - id: 0,
16 - state: 'Success',
17 - usage: ['text-success', 'btn-success'],
18 - },
19 - {
20 - id: 1,
21 - state: 'Warning',
22 - usage: ['badge-warning', 'bg-warning'],
23 - },
24 - {
25 - id: 2,
26 - state: 'Danger',
27 - usage: ['btn-danger', 'text-danger'],
28 - },
29 - {
30 - id: 3,
31 - state: 'Info',
32 - usage: ['alert-info', 'badge-info'],
33 - },
34 - {
35 - id: 4,
36 - state: 'Primary',
37 - usage: ['bg-primary', 'text-primary'],
38 - },
39 - {
40 - id: 5,
41 - state: 'Secondary',
42 - usage: ['bg-secondary'],
43 - },
44 -];
45 -
46 -const Colors = () => (
47 - <div>
48 - <Breadcrumb>
49 - <BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
50 - <BreadcrumbItem active>Colors</BreadcrumbItem>
51 - </Breadcrumb>
52 - <h1 className="page-title">Colors</h1>
53 - <Row>
54 - <Col>
55 - <Widget
56 - title={<h5>States <span className="fw-semi-bold">Colors</span></h5>}
57 - close collapse
58 - >
59 - <p>Sing comes with a number of state colors that can be applied to
60 - the most of elements and components. It reuses Bootstrap&apos;s original 6 states:</p>
61 - <Table>
62 - <thead>
63 - <tr>
64 - <th>STATE</th>
65 - <th>PREVIEW</th>
66 - <th>CLASS POSTFIX</th>
67 - <th>USAGE EXAMPLE</th>
68 - </tr>
69 - </thead>
70 - <tbody>
71 - {tableData.map(({ state, usage, id }) =>
72 - <tr key={id}>
73 - <th scope="row" className="fw-thin">{state}</th>
74 - <td><span className={`circle bg-${state.toLowerCase()}`}>&nbsp;</span></td>
75 - <td><code>*-{state.toLowerCase()}</code></td>
76 - <td>{usage.map(item => <code key={item} className="mr-xs">{item}</code>)}</td>
77 - </tr>,
78 - )}
79 - </tbody>
80 - </Table>
81 - </Widget>
82 - </Col>
83 - </Row>
84 - <Row>
85 - <Col xs={12} md={6}>
86 - <Widget
87 - title={<h5>Text <span className="fw-semi-bold">Colors</span></h5>}
88 - close collapse
89 - >
90 - <p>Convey meaning through color with a handful of color utility classes.
91 - Includes support for styling links with hover states, too. Use <code>text-*</code> class to fill text.</p>
92 - <div className="widget-padding-md border rounded w-100 h-100 text-left">
93 - <h1 className="text-danger">h1. Heading</h1>
94 - <h2 className="text-warning">h2. Heading</h2>
95 - <h3 className="text-success">h3. Heading</h3>
96 - <h4 className="text-primary">h4. Heading</h4>
97 - <h5 className="text-info">h5. Heading</h5>
98 - <h6 className="text-inverse">h6. Heading</h6>
99 - </div>
100 - </Widget>
101 - </Col>
102 - <Col xs={12} md={6}>
103 - <Widget
104 - title={<h5>Example <span className="fw-semi-bold">Buttons</span></h5>}
105 - close collapse
106 - >
107 - <p>Use any of the available button classes to quickly create a styled button.
108 - Semantically distinguishable beauty.</p>
109 - <Button className="width-100 mb-xs mr-xs" color="default">Default</Button>
110 - <Button className="width-100 mb-xs mr-xs" color="primary">Primary</Button>
111 - <Button className="width-100 mb-xs mr-xs" color="info">Info</Button>
112 - <Button className="width-100 mb-xs mr-xs" color="success">Success</Button>
113 - <Button className="width-100 mb-xs mr-xs" color="warning">Warning</Button>
114 - <Button className="width-100 mb-xs mr-xs" color="danger">Danger</Button>
115 - <Button className="width-100 mb-xs mr-xs" color="gray">Gray</Button>
116 - <Button className="width-100 mb-xs mr-xs" color="inverse">Inverse</Button>
117 - </Widget>
118 - </Col>
119 - </Row>
120 - </div>
121 -);
122 -
123 -export default Colors;
1 -{
2 - "name": "Colors",
3 - "version": "0.0.0",
4 - "main": "./Colors.js",
5 - "private": true
6 -}
This diff is collapsed. Click to expand it.
1 -{
2 - "name": "Grid",
3 - "version": "0.0.0",
4 - "main": "./Grid.js",
5 - "private": true
6 -}
1 -import React from 'react';
2 -import {
3 - Breadcrumb,
4 - BreadcrumbItem,
5 - Row,
6 - Col,
7 -} from 'reactstrap';
8 -
9 -import Widget from '../../../../components/Widget';
10 -
11 -const Typography = () => (
12 - <div>
13 - <Breadcrumb>
14 - <BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
15 - <BreadcrumbItem active>Typography</BreadcrumbItem>
16 - </Breadcrumb>
17 - <h1 className="page-title">Typography - <span className="fw-semi-bold">Texts & Display</span></h1>
18 - <Row>
19 - <Col xs={12} md={6}>
20 - <Widget
21 - title={<h5>Headings <small className="text-muted">Default and customized</small></h5>}
22 - close collapse
23 - >
24 - <h4>Default headings</h4>
25 - <p>Basic headings for everyday use</p>
26 - <div className="widget-padding-md w-100 h-100 text-left border rounded">
27 - <Row>
28 - <Col sm={6}>
29 - <h1>h1. Heading</h1>
30 - <h2>h2. Heading</h2>
31 - <h3>h3. Heading</h3>
32 - <h4>h4. Heading</h4>
33 - <h5>h5. Heading</h5>
34 - <h6>h6. Heading</h6>
35 - </Col>
36 - <Col sm={6}>
37 - <h1 className="text-danger">h1. Heading</h1>
38 - <h2 className="text-warning">h2. Heading</h2>
39 - <h3 className="text-success">h3. Heading</h3>
40 - <h4 className="text-primary">h4. Heading</h4>
41 - <h5 className="text-info">h5. Heading</h5>
42 - <h6 className="text-inverse">h6. Heading</h6>
43 - </Col>
44 - </Row>
45 - </div>
46 - <h4 className="mt-5">Customized headings</h4>
47 - <p>Enhanced with additional text</p>
48 - <div className="widget-padding-md w-100 h-100 text-left border rounded">
49 - <h3>
50 - Headings <small>And some clarification text</small>
51 - </h3>
52 - </div>
53 - <h4 className="mt-5">Display</h4>
54 - <p>Headings to stand out</p>
55 - <div className="widget-padding-md w-100 h-100 text-left border rounded">
56 - <h1 className="display-1">Display 1</h1>
57 - <h1 className="display-2">Display 2</h1>
58 - <h1 className="display-3">Display 3</h1>
59 - <h1 className="display-4">Display 4</h1>
60 - </div>
61 - <h4 className="mt-5">Lead</h4>
62 - <p>Make a paragraph stand out by adding <code className="highlighter-rouge">.lead</code>.</p>
63 - <div className="widget-padding-md w-100 h-100 text-left border rounded">
64 - <p className="lead">Sing App is admin dashboard template built with Bootstrap</p>
65 - </div>
66 - </Widget>
67 - </Col>
68 - <Col xs={12} md={6}>
69 - <Widget
70 - title={<h5>Body texts <small className="text-muted">Variations</small></h5>}
71 - close collapse
72 - >
73 - <h4>Basic texts</h4>
74 - <p>Styling for common texts</p>
75 - <div className="widget-padding-md w-100 h-100 text-left border rounded">
76 - <p>You can use the mark tag to <mark>highlight</mark> text.</p>
77 - <p><del>This line of text is meant to be treated as deleted text.</del></p>
78 - <p><ins>This line of text is meant to be treated as an addition to the document.</ins></p>
79 - <p><small>This line of text is meant to be treated as fine print.</small></p>
80 - <p><em>This line rendered as italicized text.</em></p>
81 - <p><strong>This line rendered as bold text.</strong></p>
82 - </div>
83 - <h4 className="mt-5">Font weights</h4>
84 - <p>Various font weights supported</p>
85 - <div className="widget-padding-md w-100 h-100 text-left border rounded">
86 - <p>Thin (default) font weight</p>
87 - <p className="fw-normal">Normal font weight</p>
88 - <p className="fw-semi-bold">Semi bold to empasize important thing</p>
89 - <p className="fw-bold">Bold font as a high priority</p>
90 - </div>
91 - <h4 className="mt-5">Colors</h4>
92 - <p>Bootstrap state colors can be applied to texts too</p>
93 - <div className="widget-padding-md w-100 h-100 text-left border rounded">
94 - <p className="text-danger">Some danger text</p>
95 - <p className="text-warning">Some warning text</p>
96 - <p className="text-success">Some succes text</p>
97 - <p className="text-primary">Some primary text</p>
98 - <p className="text-info">Some info text</p>
99 - </div>
100 - <h4 className="mt-5">Blockquotes</h4>
101 - <p>Citing someone is really easy</p>
102 - <div className="widget-padding-md w-100 h-100 text-left border rounded">
103 - <blockquote className="blockquote">
104 - <p>Don&apos;t get set into one form, adapt it and build your own, and let
105 - it grow, be like water. Empty your mind, be formless, shapeless like water.
106 - Now you put water in a cup, it becomes the cup; You put water into a bottle it
107 - becomes the bottle; You put it in a teapot it becomes the teapot. Now water can
108 - flow or it can crash. Be water, my friend.</p>
109 - <footer className="blockquote-footer">Bruce Lee in <cite title="A Warrior's Journey">A Warrior&apos;s Journey</cite></footer>
110 - </blockquote>
111 - </div>
112 - </Widget>
113 - </Col>
114 - </Row>
115 - </div>
116 -);
117 -
118 -export default Typography;
1 -{
2 - "name": "Typography",
3 - "version": "0.0.0",
4 - "main": "./Typography.js",
5 - "private": true
6 -}
1 -import React, { Component } from 'react';
2 -import cx from 'classnames';
3 -import {
4 - Breadcrumb,
5 - BreadcrumbItem,
6 - Alert,
7 -} from 'reactstrap';
8 -
9 -import Filters from './components/Filters/Filters';
10 -import MessageTable from './components/MessageTable/MessageTable';
11 -
12 -import s from './Email.module.scss';
13 -
14 -class Email extends Component {
15 - state = {
16 - isNotificationOpen: true,
17 - filter: null,
18 - openedMessage: null,
19 - compose: false,
20 - composeData: null,
21 - alertAfter: false,
22 - }
23 -
24 - componentDidMount() {
25 - setTimeout(() => { this.fixAlert(); }, 0);
26 - }
27 -
28 - fixAlert() {
29 - this.setState({ alertAfter: true });
30 - }
31 -
32 - filter = (filter) => {
33 - this.setState({ filter, compose: false, composeData: null });
34 - }
35 -
36 - closeNotification() {
37 - this.setState({ isNotificationOpen: false });
38 - }
39 -
40 - openMessage = (id) => {
41 - this.setState(pvState => ({
42 - openedMessage: id,
43 - compose: id === null ? false : pvState.compose,
44 - composeData: id === null ? null : pvState.composeData,
45 - }));
46 - }
47 -
48 - changeCompose = (compose, data) => {
49 - this.setState({ compose });
50 -
51 - if (data) {
52 - this.setState({ composeData: data });
53 - }
54 - }
55 -
56 - render() {
57 - const {
58 - isNotificationOpen,
59 - filter,
60 - openedMessage,
61 - alertAfter,
62 - compose,
63 - composeData,
64 - } = this.state;
65 - return (
66 - <div>
67 - <Breadcrumb>
68 - <BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
69 - <BreadcrumbItem active>Email</BreadcrumbItem>
70 - </Breadcrumb>
71 - <div className="page-top-line">
72 - <h1 className="page-title">Email - <span className="fw-semi-bold">Inbox</span></h1>
73 - <Alert
74 - isOpen={isNotificationOpen}
75 - color="success"
76 - toggle={() => this.closeNotification()}
77 - className={cx(s.alert, { [s.alertAfter]: alertAfter })}
78 - >
79 - Hey! This is a <span className="fw-semi-bold">real app</span> with CRUD and Search functions. Have fun!
80 - </Alert>
81 - </div>
82 - <div className={s.view}>
83 - <Filters
84 - filter={this.filter}
85 - openMessage={this.openMessage}
86 - compose={this.changeCompose}
87 - />
88 - <MessageTable
89 - filter={filter}
90 - openedMessage={openedMessage}
91 - openMessage={this.openMessage}
92 - compose={compose}
93 - changeCompose={this.changeCompose}
94 - composeData={composeData}
95 - />
96 - </div>
97 - </div>
98 - );
99 - }
100 -}
101 -
102 -export default Email;
1 -.view {
2 - display: flex;
3 -
4 - @media screen and (max-width: 1125px) {
5 - flex-direction: column;
6 - }
7 -}
8 -
9 -.alert {
10 - transition: 0.6s;
11 - transition-timing-function: ease;
12 - transform: translateX(-130vw);
13 -}
14 -
15 -.alertAfter {
16 - transform: translateX(0);
17 -}
1 -import React from 'react';
2 -import PropTypes from 'prop-types';
3 -import { Editor } from 'react-draft-wysiwyg';
4 -import { Input, Button } from 'reactstrap';
5 -
6 -import Widget from '../../../../../components/Widget';
7 -
8 -import s from './Compose.module.scss';
9 -
10 -const Compose = ({ data }) => (
11 - <Widget>
12 - <div className={s.compose}>
13 - <h4>Compose <span className="fw-semi-bold">New</span></h4>
14 - <Input type="text" placeholder="To" defaultValue={data && data.from} />
15 - <Input type="text" placeholder="Subject" defaultValue={data && data.theme} />
16 - <Editor
17 - wrapperClassName={s.wysiwygWrapper}
18 - editorClassName={s.wysiwygEditor}
19 - toolbarClassName={s.wysiwygToolbar}
20 - />
21 - <div className="text-md-right mt-xs">
22 - <Button color="gray">Discard</Button>
23 - <Button color="gray">Save</Button>
24 - <Button color="danger">Send</Button>
25 - </div>
26 - </div>
27 - </Widget>
28 -);
29 -
30 -Compose.propTypes = {
31 - data: PropTypes.shape({
32 - from: PropTypes.string,
33 - to: PropTypes.string,
34 - }),
35 -};
36 -
37 -Compose.defaultProps = {
38 - data: {
39 - from: null,
40 - to: null,
41 - },
42 -};
43 -
44 -export default Compose;
1 -@import '../../../../../styles/app';
2 -
3 -:global {
4 - @import '../../../../../../node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg';
5 -}
6 -
7 -.compose {
8 - h4 {
9 - margin-bottom: 20px;
10 - }
11 -
12 - input {
13 - margin-bottom: 15px;
14 - }
15 -
16 - button {
17 - margin-left: 7.5px;
18 - }
19 -}
20 -
21 -.wysiwygWrapper {
22 - border: 1px solid #ccc !important;
23 - overflow: visible;
24 - height: 270px;
25 - margin-bottom: 15px;
26 -}
27 -
28 -.wysiwygToolbar {
29 - color: $gray-800 !important;
30 - background-color: #ddd !important;
31 - border-color: transparent !important;
32 -
33 - :global {
34 - .rdw-option-wrapper {
35 - font-family: 'Open Sans', sans-serif;
36 - font-size: 14px;
37 - height: 30px;
38 - min-width: 30px;
39 - margin: 0;
40 - background: #f8f8f8;
41 - }
42 -
43 - .rdw-dropdown-wrapper {
44 - background: #f8f8f8;
45 - }
46 - }
47 -}
48 -
49 -.wysiwygEditor {
50 - position: relative !important;
51 - overflow: hidden !important;
52 - height: 150px;
53 - line-height: 0.1;
54 -}
1 -import React, { Component } from 'react';
2 -import PropTypes from 'prop-types';
3 -import cx from 'classnames';
4 -import { Badge } from 'reactstrap';
5 -
6 -import s from './Filters.module.scss';
7 -
8 -class Filters extends Component {
9 - state = { activeButtonId: 0 }
10 -
11 - handleButtonClick(id, filterCond) {
12 - const { filter, openMessage } = this.props;
13 - this.setState({ activeButtonId: id });
14 -
15 - openMessage(null);
16 - filter(filterCond);
17 - }
18 -
19 - render() {
20 - const mainButtons = [
21 - { id: 0, title: 'Inbox', notifications: 2, filter: null },
22 - { id: 1, title: 'Starred', filter: 'starred' },
23 - { id: 2, title: 'Sent Mail', filter: 'sent' },
24 - { id: 3, title: 'Draft', notifications: 3, lable: 'danger', filter: 'draft' },
25 - { id: 4, title: 'Trash', filter: 'trash' },
26 - ];
27 - const quickViewButton = [
28 - { id: 0, title: 'Work', colour: 'danger' },
29 - { id: 1, title: 'Private', colour: 'white' },
30 - { id: 2, title: 'Saved', colour: '' },
31 - ];
32 - const { activeButtonId } = this.state;
33 - const { compose } = this.props;
34 - return (
35 - <div className={s.filters}>
36 - <button
37 - className="btn btn-danger btn-block"
38 - onClick={() => compose(true)}
39 - >
40 - Compose
41 - </button>
42 - <div className={s.mainFilterButtons}>
43 - {mainButtons.map(button =>
44 - <button
45 - className={cx('btn', s.button, { [s.buttonActive]: button.id === activeButtonId })}
46 - key={button.id}
47 - onClick={() => this.handleButtonClick(button.id, button.filter)}
48 - >
49 - {button.title}
50 - {button.notifications &&
51 - <Badge color={button.lable || 'default'} pill>{button.notifications}</Badge>}
52 - </button>,
53 - )}
54 - </div>
55 - <div>
56 - <h6>QUICK VIEW</h6>
57 - {quickViewButton.map(button =>
58 - <button className={cx('btn', s.button)} key={button.id}>
59 - {button.title}
60 - <i className={cx('fa fa-circle', { [`text-${button.colour}`]: true })} />
61 - </button>,
62 - )}
63 - </div>
64 - </div>
65 - );
66 - }
67 -}
68 -
69 -Filters.propTypes = {
70 - filter: PropTypes.func.isRequired,
71 - openMessage: PropTypes.func.isRequired,
72 - compose: PropTypes.func.isRequired,
73 -};
74 -
75 -export default Filters;
1 -@import '../../../../../styles/app';
2 -
3 -.filters {
4 - width: 16%;
5 - padding-right: 15px;
6 -
7 - @media screen and (max-width: 1125px) {
8 - width: 100%;
9 - padding-right: 0;
10 - }
11 -}
12 -
13 -.mainFilterButtons {
14 - margin: 15px 0;
15 -}
16 -
17 -.button {
18 - width: 100%;
19 - padding: 10px 14px !important;
20 - display: flex !important;
21 - justify-content: space-between;
22 - align-items: center;
23 - font-weight: $font-weight-normal;
24 - border-radius: 0.2rem;
25 - color: #868e96;
26 - background: transparent;
27 -
28 - &:hover {
29 - background-color: #e5e5e5;
30 - color: $gray-700;
31 - }
32 -
33 - & :global .badge {
34 - width: 20px;
35 - height: 20px;
36 - padding: 0;
37 - display: flex;
38 - align-items: center;
39 - justify-content: center;
40 - line-height: 10px;
41 - }
42 -}
43 -
44 -.buttonActive {
45 - background-color: $white;
46 - color: #555;
47 - font-weight: 600;
48 -}
1 -import React from 'react';
2 -import PropTypes from 'prop-types';
3 -
4 -import Widget from '../../../../../components/Widget';
5 -import MessageHeader from '../MessageHeader/MessageHeader';
6 -import MessageAttachments from '../MessageAttachments/MessageAttachments';
7 -
8 -const Message = ({ message, compose }) => (
9 - <Widget>
10 - <MessageHeader
11 - title={message.theme}
12 - name={message.from}
13 - email={message.fromEmail}
14 - to={message.to}
15 - date={message.date}
16 - compose={compose}
17 - />
18 - {/* eslint-disable */}
19 - <div
20 - dangerouslySetInnerHTML={{ __html: message.content }}
21 - />
22 - {/* eslint-enable */}
23 - {message.attachments && <MessageAttachments attachments={message.attachments} />}
24 - </Widget>
25 -);
26 -
27 -Message.propTypes = {
28 - message: PropTypes.shape({
29 - theme: PropTypes.string,
30 - from: PropTypes.string,
31 - fromEmail: PropTypes.string,
32 - to: PropTypes.string,
33 - date: PropTypes.string,
34 - }).isRequired,
35 - compose: PropTypes.func.isRequired,
36 -};
37 -
38 -export default Message;
1 -import React from 'react';
2 -import PropTypes from 'prop-types';
3 -
4 -import s from './MessageAttachments.module.scss';
5 -
6 -const MessageAttachments = ({ attachments }) => (
7 - <div className={s.messageAttachments}>
8 - <hr />
9 - <div className={s.attachmentsInfo}>
10 - <strong>{attachments.length} attachments</strong> -
11 - <button className="btn-link">Download all attachments</button>
12 - <button className="btn-link">View all attachments</button>
13 - </div>
14 - {attachments.map(att =>
15 - <div className={s.attachment} key={att.id}>
16 - <img src={att.photo} alt="attachment" />
17 - <h5>{att.photoName}</h5>
18 - <div className={s.attachmentButtons}>
19 - {att.weight}
20 - <button className="btn-link">View</button>
21 - <button className="btn-link">Download</button>
22 - </div>
23 - </div>,
24 - )}
25 - </div>
26 -);
27 -
28 -MessageAttachments.propTypes = {
29 - attachments: PropTypes.arrayOf(PropTypes.shape({
30 - photo: PropTypes.string,
31 - photoName: PropTypes.string,
32 - weight: PropTypes.string,
33 - })).isRequired,
34 -};
35 -
36 -export default MessageAttachments;
1 -@import '../../../../../styles/app';
2 -
3 -.messageAttachments {
4 - width: 50%;
5 -
6 - @media screen and (max-width: 576px) {
7 - width: 100%;
8 - }
9 -}
10 -
11 -.attachmentsInfo {
12 - margin: -5px 0 10px;
13 -
14 - a {
15 - margin-left: 5px;
16 - }
17 -}
18 -
19 -.attachment {
20 - max-width: 100%;
21 -
22 - img {
23 - width: 100%;
24 - }
25 -
26 - h5 {
27 - font-weight: $font-weight-semi-bold;
28 - }
29 -}
30 -
31 -.attachmentButtons {
32 - margin: -5px 0 15px;
33 -
34 - a {
35 - margin-left: 10px;
36 - }
37 -}
1 -import React from 'react';
2 -import PropTypes from 'prop-types';
3 -
4 -import ReplyDropdown from '../ReplyDropdown/ReplyDropdown';
5 -
6 -import userPhoto from '../../../../../images/people/a5.jpg';
7 -import s from './MessageHeader.module.scss';
8 -
9 -const MessageHeader = ({ title, name, email, to, date, compose }) => (
10 - <div className={s.messageHeader}>
11 - <h3>{title}</h3>
12 - <div className={s.messageHeaderLine}>
13 - <div className={s.messageFrom}>
14 - <img src={userPhoto} alt="user" className="rounded-circle" />
15 - <div className={s.messageFromInfo}>
16 - <span>
17 - <strong>{name}</strong>
18 - <span className={s.email}>
19 - {`<${email}>`}
20 - </span>
21 - </span>
22 - <span className={s.to}>to {to}</span>
23 - </div>
24 - </div>
25 - <div className={s.messageHeaderDate}>
26 - {date}
27 - <ReplyDropdown compose={() => compose(true, { from: name, theme: title })} />
28 - </div>
29 - </div>
30 - </div>
31 -);
32 -
33 -MessageHeader.propTypes = {
34 - title: PropTypes.string.isRequired,
35 - name: PropTypes.string.isRequired,
36 - email: PropTypes.string.isRequired,
37 - to: PropTypes.string.isRequired,
38 - date: PropTypes.string.isRequired,
39 - compose: PropTypes.func.isRequired,
40 -};
41 -
42 -export default MessageHeader;
1 -@import '../../../../../styles/app';
2 -
3 -.messageHeader {
4 - width: 100%;
5 -}
6 -
7 -.messageHeaderLine {
8 - display: flex;
9 - justify-content: space-between;
10 - align-items: center;
11 - margin: 15px 0;
12 - flex-wrap: wrap;
13 -}
14 -
15 -.messageFrom {
16 - display: flex;
17 - align-items: center;
18 -
19 - img {
20 - height: 30px;
21 - width: 30px;
22 - margin-right: 5px;
23 - }
24 -}
25 -
26 -.messageFromInfo {
27 - display: flex;
28 - flex-direction: column;
29 - line-height: 1.1;
30 -}
31 -
32 -.email {
33 - color: #868e96;
34 - font-size: $font-size-mini;
35 - margin-left: 5px;
36 -}
37 -
38 -.to {
39 - color: #868e96;
40 -}
41 -
42 -.messageHeaderDate {
43 - padding: 15px 0;
44 -
45 - & :global .btn-group {
46 - margin-left: 10px;
47 -
48 - button {
49 - font-size: 12px;
50 -
51 - i {
52 - margin-right: 3px;
53 - }
54 - }
55 - }
56 -}
1 -import React, { Component } from 'react';
2 -import PropTypes from 'prop-types';
3 -import cx from 'classnames';
4 -import { Table, Input, FormGroup, Label } from 'reactstrap';
5 -
6 -import Widget from '../../../../../components/Widget';
7 -import MessageTableHeader from '../MessageTableHeader/MessageTableHeader';
8 -import Pagination from '../Pagination/Pagination';
9 -import Compose from '../Compose/Compose';
10 -import Message from '../Message/Message';
11 -
12 -import mock from '../../mock';
13 -import s from './MessageTable.module.scss';
14 -
15 -class MessageTable extends Component {
16 - state = {
17 - messages: mock,
18 - checkedIds: [],
19 - searchString: '',
20 - }
21 -
22 - componentWillReceiveProps(nextProps) {
23 - const { filter } = this.props;
24 -
25 - if (filter !== nextProps.filter) {
26 - this.chooseNone();
27 - this.setState({ openedMessage: null });
28 - }
29 - }
30 -
31 - chooseAll = () => {
32 - const { messages } = this.state;
33 - const { filter } = this.props;
34 - const newCheckedIds = [];
35 -
36 - if (filter) {
37 - messages
38 - .filter(message => message[filter])
39 - .forEach(message => newCheckedIds.push(message.id));
40 - } else {
41 - messages.forEach(message => newCheckedIds.push(message.id));
42 - }
43 -
44 - this.setState({ checkedIds: newCheckedIds });
45 - }
46 -
47 - chooseNone = () => {
48 - this.setState({ checkedIds: [] });
49 - }
50 -
51 - chooseRead = () => {
52 - const { messages } = this.state;
53 - const newCheckedIds = [];
54 -
55 - messages.forEach((message) => {
56 - if (!message.unreaded) {
57 - newCheckedIds.push(message.id);
58 - }
59 - });
60 -
61 - this.setState({
62 - checkedIds: newCheckedIds,
63 - });
64 - }
65 -
66 - chooseUnread = () => {
67 - const { messages } = this.state;
68 - const newCheckedIds = [];
69 -
70 - messages.forEach((message) => {
71 - if (message.unreaded) {
72 - newCheckedIds.push(message.id);
73 - }
74 - });
75 -
76 - this.setState({
77 - checkedIds: newCheckedIds,
78 - });
79 - }
80 -
81 - choose(id) {
82 - const { checkedIds } = this.state;
83 - const indexOfId = checkedIds.indexOf(id);
84 -
85 - if (indexOfId === -1) {
86 - this.setState({ checkedIds: [...checkedIds, id] });
87 - } else {
88 - const newCheckedIds = [...checkedIds];
89 - newCheckedIds.splice(indexOfId, 1);
90 - this.setState({ checkedIds: newCheckedIds });
91 - }
92 - }
93 -
94 - markUnread = () => {
95 - const { messages, checkedIds } = this.state;
96 - const newMessages = [...messages];
97 -
98 - newMessages.map((message) => {
99 - if (checkedIds.indexOf(message.id) !== -1) {
100 - message.unreaded = true;
101 - }
102 - return message;
103 - });
104 -
105 - this.setState({ messages: newMessages });
106 - }
107 -
108 - markRead = () => {
109 - const { messages, checkedIds } = this.state;
110 - const newMessages = [...messages];
111 -
112 - newMessages.map((message) => {
113 - if (checkedIds.indexOf(message.id) !== -1) {
114 - message.unreaded = false;
115 - }
116 - return message;
117 - });
118 -
119 - this.setState({ messages: newMessages });
120 - }
121 -
122 - delete = () => {
123 - const { messages, checkedIds } = this.state;
124 - const newMessages = [...messages];
125 -
126 - newMessages.map((message) => {
127 - if (checkedIds.indexOf(message.id) !== -1) {
128 - message.deleted = true;
129 - }
130 - return message;
131 - });
132 -
133 - this.setState({
134 - messages: newMessages.filter(message => !message.deleted),
135 - checkedIds: [],
136 - });
137 - }
138 -
139 - starItem(id) {
140 - const { messages } = this.state;
141 - const isAlreadyStarred = messages.find(m => m.id === id).starred;
142 - const newMessages = [...messages];
143 -
144 - newMessages.map((message) => {
145 - if (message.id === id) {
146 - message.starred = !isAlreadyStarred;
147 - }
148 - return message;
149 - });
150 -
151 - this.setState({ messages: newMessages });
152 - }
153 -
154 - handleOpenMessage(id) {
155 - const newMessages = [...this.state.messages];
156 -
157 - newMessages.map((message) => {
158 - if (message.id === id) {
159 - message.unreaded = false;
160 - }
161 -
162 - return message;
163 - });
164 -
165 - this.setState({ messages: newMessages });
166 -
167 - this.props.openMessage(id);
168 - }
169 -
170 - search = (value) => {
171 - this.setState({ searchString: value.toLowerCase() });
172 - }
173 -
174 - _searchable(m) {
175 - const { searchString } = this.state;
176 -
177 - if (searchString) {
178 - return (m.content.toLowerCase().indexOf(searchString) !== -1 ||
179 - m.from.toLowerCase().indexOf(searchString) !== -1 ||
180 - m.theme.toLowerCase().indexOf(searchString) !== -1);
181 - }
182 -
183 - return true;
184 - }
185 -
186 - render() {
187 - const { messages, checkedIds } = this.state;
188 - const { filter, openedMessage, openMessage, compose, composeData, changeCompose } = this.props;
189 - const filteredMessages = messages.filter(message => message[filter]);
190 - const dataToDisplay = filter ? filteredMessages : messages;
191 - return (
192 - <div className={s.messages}>
193 - {openedMessage === null && !compose
194 - ? <Pagination />
195 - : <button className={cx('btn btn-default', s.backButton)} onClick={() => openMessage(null)}>
196 - <i className="fa fa-angle-left fa-lg" />
197 - </button>
198 - }
199 - {/* eslint-disable */}
200 - {openedMessage === null && !compose
201 - ? <Widget>
202 - <MessageTableHeader
203 - all={this.chooseAll}
204 - none={this.chooseNone}
205 - read={this.chooseRead}
206 - unread={this.chooseUnread}
207 - markRead={this.markRead}
208 - markUnread={this.markUnread}
209 - deleteItems={this.delete}
210 - search={this.search}
211 - />
212 - <Table striped hover>
213 - <thead>
214 - <tr>
215 - <th>
216 - <FormGroup className="checkbox abc-checkbox" check>
217 - <Input
218 - id="checkbox-main"
219 - type="checkbox"
220 - onChange={dataToDisplay.length !== checkedIds.length ? this.chooseAll : this.chooseNone}
221 - checked={dataToDisplay.length !== 0 && checkedIds.length === dataToDisplay.length}
222 - />{' '}
223 - <Label for="checkbox-main" check />
224 - </FormGroup>
225 - </th>
226 - </tr>
227 - </thead>
228 - <tbody>
229 - {dataToDisplay
230 - .filter((m) => this._searchable(m))
231 - .map(message =>
232 - (<tr
233 - key={message.id}
234 - className={cx({ [s.unreadedMessage]: message.unreaded })}
235 - >
236 - <td className={s.messageCheckbox} >
237 - <FormGroup className="checkbox abc-checkbox" check>
238 - <Input
239 - id={`checkbox${message.id}`}
240 - type="checkbox"
241 - checked={checkedIds.indexOf(message.id) !== -1}
242 - onChange={() => this.choose(message.id)}
243 - />{' '}
244 - <Label for={`checkbox${message.id}`} check />
245 - </FormGroup>
246 - </td>
247 - <td
248 - className={s.messageStar}
249 - onClick={() => this.starItem(message.id)}>{message.starred
250 - ? <span className={s.messageStarred}><i className="fa fa-star" /></span>
251 - : <span><i className="fa fa-star-o" /></span>}
252 - </td>
253 - <td
254 - className={s.messageFrom}
255 - onClick={() => this.handleOpenMessage(message.id)}
256 - >{message.from}</td>
257 - <td onClick={() => this.handleOpenMessage(message.id)}>{message.theme}</td>
258 - <td className={s.messageClip}>{message.attachments && <i className="fa fa-paperclip" />}</td>
259 - <td className={s.messageDate}>{message.date}</td>
260 - </tr>),
261 - )}
262 - </tbody>
263 - </Table>
264 - </Widget>
265 - : compose
266 - ? <Compose data={composeData} />
267 - : <Message message={messages[openedMessage]} compose={changeCompose} />
268 - }
269 - {/* eslint-enable */}
270 - </div>
271 - );
272 - }
273 -}
274 -
275 -MessageTable.propTypes = {
276 - filter: PropTypes.string,
277 - openedMessage: PropTypes.number,
278 - openMessage: PropTypes.func.isRequired,
279 - compose: PropTypes.bool.isRequired,
280 - composeData: PropTypes.shape({
281 - from: PropTypes.string,
282 - theme: PropTypes.string,
283 - }),
284 - changeCompose: PropTypes.func.isRequired,
285 -};
286 -
287 -MessageTable.defaultProps = {
288 - filter: null,
289 - openedMessage: null,
290 - composeData: null,
291 -};
292 -
293 -export default MessageTable;
1 -@import '../../../../../styles/app';
2 -
3 -.messages {
4 - width: 84%;
5 - border-radius: 0.2rem;
6 -
7 - @media screen and (max-width: 1125px) {
8 - width: 100%;
9 - }
10 -
11 - & :global .form-check-input {
12 - margin: 0;
13 - position: relative;
14 - }
15 -
16 - & :global .table {
17 - margin-bottom: 0;
18 - }
19 -}
20 -
21 -.unreadedMessage {
22 - td {
23 - font-weight: $font-weight-semi-bold;
24 - }
25 -}
26 -
27 -.messageCheckbox {
28 - width: 50px;
29 - padding-right: 0;
30 -
31 - :global .form-check {
32 - margin-bottom: 0;
33 - }
34 -}
35 -
36 -.messageStar {
37 - left: 25px;
38 - margin-left: -10px;
39 -}
40 -
41 -.messageStarred {
42 - color: theme-color('warning');
43 -}
44 -
45 -.messageFrom,
46 -.messageClip {
47 - @media screen and (max-width: 768px) {
48 - display: none;
49 - }
50 -}
51 -
52 -.messageDate {
53 - display: flex;
54 - justify-content: flex-end;
55 -
56 - @media screen and (max-width: 768px) {
57 - width: 65px;
58 - }
59 -}
60 -
61 -.backButton {
62 - margin-bottom: 15px;
63 -}
1 -import React from 'react';
2 -import PropTypes from 'prop-types';
3 -import {
4 - UncontrolledButtonDropdown,
5 - DropdownToggle,
6 - DropdownMenu,
7 - DropdownItem,
8 - Input,
9 -} from 'reactstrap';
10 -
11 -import s from './MessageTableHeader.module.scss';
12 -
13 -const MessageTableHeader = (props) => {
14 - const { all, none, read, unread, markRead, markUnread, deleteItems, search } = props;
15 - const select = [
16 - { id: 0, title: 'All', onClick: all },
17 - { id: 1, title: 'None', onClick: none },
18 - { id: 2 },
19 - { id: 3, title: 'Read', onClick: read },
20 - { id: 4, title: 'Unread', onClick: unread },
21 - ];
22 - const action = [
23 - { id: 1, title: 'Reply' },
24 - { id: 2, title: 'Forward' },
25 - { id: 3, title: 'Archive' },
26 - { id: 4 },
27 - { id: 5, title: 'Mark As Read', onClick: markRead },
28 - { id: 6, title: 'Mark As Unread', onClick: markUnread },
29 - { id: 7 },
30 - { id: 8, title: 'Delete', onClick: deleteItems },
31 - ];
32 - return (
33 - <div className={s.messageTableHeader}>
34 - <div>
35 - <UncontrolledButtonDropdown size="sm">
36 - <DropdownToggle
37 - caret color="default"
38 - className="dropdown-toggle-split mr-xs"
39 - >
40 - Select
41 - </DropdownToggle>
42 - <DropdownMenu>
43 - {select.map(item =>
44 - (Object.keys(item).length > 1
45 - ? <DropdownItem key={item.id} onClick={item.onClick}>{item.title}</DropdownItem>
46 - : <DropdownItem key={item.id} divider />),
47 - )}
48 - </DropdownMenu>
49 - </UncontrolledButtonDropdown >
50 - <UncontrolledButtonDropdown size="sm">
51 - <DropdownToggle
52 - caret color="default"
53 - className="dropdown-toggle-split mr-xs"
54 - >
55 - Actions
56 - </DropdownToggle>
57 - <DropdownMenu>
58 - {action.map(item =>
59 - (Object.keys(item).length > 1
60 - ? <DropdownItem key={item.id} onClick={item.onClick}>{item.title}</DropdownItem>
61 - : <DropdownItem key={item.id} divider />),
62 - )}
63 - </DropdownMenu>
64 - </UncontrolledButtonDropdown>
65 - </div>
66 - <Input placeholder="Search Messages" size="sm" onChange={e => search(e.target.value)} />
67 - </div>
68 - );
69 -};
70 -
71 -MessageTableHeader.propTypes = {
72 - all: PropTypes.func.isRequired,
73 - none: PropTypes.func.isRequired,
74 - read: PropTypes.func.isRequired,
75 - unread: PropTypes.func.isRequired,
76 - markRead: PropTypes.func.isRequired,
77 - markUnread: PropTypes.func.isRequired,
78 - deleteItems: PropTypes.func.isRequired,
79 - search: PropTypes.func.isRequired,
80 -};
81 -
82 -export default MessageTableHeader;
1 -.messageTableHeader {
2 - display: flex;
3 - justify-content: space-between;
4 - align-items: center;
5 -
6 - & :global .form-control {
7 - width: auto;
8 - }
9 -}
1 -import React from 'react';
2 -import cx from 'classnames';
3 -
4 -import s from './Pagination.module.scss';
5 -
6 -const Pagination = () => (
7 - <div className={s.pagination}>
8 - <span className={s.paginationText}>Showing 1 - 10 of 96 messages</span>
9 - <div className={s.paginationPages}>
10 - <button className={cx(s.button, s.buttonDisabled)}><i className="fa fa-chevron-left" /></button>
11 - <button className={cx(s.button, s.buttonActive)}>1</button>
12 - <button className={s.button}>2</button>
13 - <button className={s.button}><i className="fa fa-chevron-right" /></button>
14 - </div>
15 - </div>
16 -);
17 -
18 -export default Pagination;
1 -@import '../../../../../styles/app';
2 -
3 -.pagination {
4 - width: 100%;
5 - display: flex;
6 - justify-content: flex-end;
7 - align-items: center;
8 - margin-bottom: 15px;
9 -}
10 -
11 -.paginationText {
12 - color: #868e96;
13 - font-size: $font-size-mini;
14 -}
15 -
16 -.paginationPages {
17 - border-left: 1px solid #868e96;
18 - padding-left: 11px;
19 - margin-left: 10px;
20 - display: flex;
21 -
22 - button {
23 - margin-left: 4px;
24 - }
25 -}
26 -
27 -.button {
28 - transition: 0.3s;
29 - padding: 0.45rem 0.75rem;
30 - display: flex;
31 - justify-content: space-between;
32 - align-items: center;
33 - font-weight: $font-weight-normal;
34 - border-radius: 0.2rem;
35 - color: #888;
36 - background: #fff;
37 - border: none;
38 -
39 - &:hover {
40 - background-color: transparent;
41 - }
42 -}
43 -
44 -.buttonActive {
45 - background: $gray-300;
46 -}
47 -
48 -.buttonDisabled {
49 - &:hover {
50 - background-color: #fff;
51 - }
52 -}
1 -import React, { Component } from 'react';
2 -import PropTypes from 'prop-types';
3 -import {
4 - ButtonDropdown,
5 - Button,
6 - DropdownToggle,
7 - DropdownMenu,
8 - DropdownItem,
9 -} from 'reactstrap';
10 -
11 -class ReplyDropdown extends Component {
12 - state = { open: false };
13 -
14 - toggle() {
15 - this.setState(pvState => ({ open: !pvState.open }));
16 - }
17 -
18 - render() {
19 - const { open } = this.state;
20 - const { compose } = this.props;
21 - return (
22 - <ButtonDropdown isOpen={open} toggle={() => this.toggle()}>
23 - <Button size="sm" id="dropdownFour" color="default" onClick={() => compose()}>
24 - <i className="fa fa-reply" /> Reply
25 - </Button>
26 - <DropdownToggle size="sm" color="default" className="dropdown-toggle-split">
27 - <i className="fa fa-angle-down" />
28 - </DropdownToggle>
29 - <DropdownMenu>
30 - <DropdownItem><i className="fa fa-reply" /> Reply</DropdownItem>
31 - <DropdownItem><i className="fa fa-arrow-right" /> Forward</DropdownItem>
32 - <DropdownItem><i className="fa fa-print" /> Print</DropdownItem>
33 - <DropdownItem divider />
34 - <DropdownItem><i className="fa fa-ban" /> Spam</DropdownItem>
35 - <DropdownItem><i className="fa fa-trash" /> Delete</DropdownItem>
36 - </DropdownMenu>
37 - </ButtonDropdown>
38 - );
39 - }
40 -}
41 -
42 -ReplyDropdown.propTypes = {
43 - compose: PropTypes.func.isRequired,
44 -};
45 -
46 -export default ReplyDropdown;
1 -import photo1 from '../../../images/tables/1.png';
2 -import photo2 from '../../../images/tables/2.png';
3 -import photo3 from '../../../images/tables/3.png';
4 -
5 -export default [
6 - {
7 - id: 0,
8 - starred: true,
9 - from: 'Philip Horbachuski',
10 - fromEmail: 'philip.horbachuski@example.com',
11 - to: 'Wrapbootstrap',
12 - theme: 'Hi, Welcom to Google Mail',
13 - date: '18:31',
14 - unreaded: true,
15 - content: `<p>Projecting surrounded literature yet delightful alteration but bed men. Open are from long why cold.
16 - If must snug by upon sang loud left. As me do preference entreaties compliment motionless ye literature.
17 - Day behaviour explained law remainder.</p>
18 - <p><strong>On then sake home</strong> is am leaf. Of suspicion do departure at extremely he believing.
19 - Do know said mind do rent they oh hope of. General enquire picture letters
20 - garrets on offices of no on.</p>
21 - <p>All the best,</p>
22 - <p>Vitaut the Great, CEO, <br />
23 - Fooby Inc. </p>`,
24 - attachments: [
25 - {
26 - photo: photo1,
27 - photoName: 'some-cool-photo1.jpg',
28 - weight: '568K',
29 - id: 0,
30 - },
31 - {
32 - photo: photo2,
33 - photoName: 'some-cool-photo2.jpg',
34 - weight: '568K',
35 - id: 1,
36 - },
37 - ],
38 - },
39 - {
40 - id: 1,
41 - starred: true,
42 - from: 'StackExchange',
43 - theme: 'New Python questions for this week',
44 - fromEmail: 'stackexchange@example.com',
45 - to: 'Wrapbootstrap',
46 - date: 'Aug 14',
47 - unreaded: false,
48 - draft: true,
49 - content: '<h1>THIS IS HTML!!!!</h1>',
50 - attachments: [
51 - {
52 - photo: photo3,
53 - photoName: 'some-cool-photo1.jpg',
54 - weight: '568K',
55 - id: 0,
56 - },
57 - ],
58 - },
59 - {
60 - id: 2,
61 - starred: false,
62 - from: 'Facebook',
63 - theme: 'Someone just commented on your photo!',
64 - fromEmail: 'notification@facebook.com',
65 - to: 'Wrapbootstrap',
66 - date: 'Aug 7',
67 - unreaded: true,
68 - sent: true,
69 - content: 'Someone just commented on your photo!',
70 - },
71 - {
72 - id: 3,
73 - starred: false,
74 - from: 'Twitter',
75 - theme: '@hackernews is now following you on Twitter',
76 - fromEmail: 'notification@twitter.com',
77 - to: 'Wrapbootstrap',
78 - date: 'Jul 31',
79 - unreaded: false,
80 - sent: true,
81 - content: '@hackernews is now following you on Twitter',
82 - },
83 -];
1 -{
2 - "name": "email",
3 - "version": "0.0.0",
4 - "private": true,
5 - "main": "./Email.js"
6 -}
...\ No newline at end of file ...\ No newline at end of file
1 -import React from 'react';
2 -import {
3 - Row,
4 - Col,
5 - ButtonGroup,
6 - Button,
7 -} from 'reactstrap';
8 -
9 -import 'fullcalendar/dist/fullcalendar';
10 -import 'jquery-ui/ui/widgets/draggable';
11 -import moment from 'moment/moment';
12 -import $ from 'jquery';
13 -
14 -import s from './Calendar.module.scss';
15 -import Widget from '../../../../components/Widget';
16 -
17 -class Calendar extends React.Component {
18 -
19 - constructor(props) {
20 - super(props);
21 -
22 - this.state = {
23 - calendarView: 'month',
24 - currentMonth: moment().format('MMM YYYY'),
25 - currentDay: moment().format('dddd'),
26 - };
27 -
28 - const date = new Date();
29 - const d = date.getDate();
30 - const m = date.getMonth();
31 - const y = date.getFullYear();
32 -
33 - this.calendarOptions = {
34 - header: {
35 - left: '',
36 - center: '',
37 - right: '',
38 - },
39 - events: [
40 - {
41 - title: 'All Day Event',
42 - start: new Date(y, m, 1),
43 - backgroundColor: '#79A5F0',
44 - textColor: '#fff',
45 - description: 'Will be busy throughout the whole day',
46 - },
47 - {
48 - title: 'Long Event',
49 - start: new Date(y, m, d + 5),
50 - end: new Date(y, m, d + 7),
51 - description: 'This conference should be worse visiting',
52 - },
53 - {
54 - id: 999,
55 - title: 'Blah Blah Car',
56 - start: new Date(y, m, d - 3, 16, 0),
57 - allDay: false,
58 - description: 'Agree with this guy on arrival time',
59 - },
60 - {
61 - id: 1000,
62 - title: 'Buy this template',
63 - start: new Date(y, m, d + 3, 12, 0),
64 - allDay: false,
65 - backgroundColor: '#555',
66 - textColor: '#fff',
67 - description: 'Make sure everything is consistent first',
68 - },
69 - {
70 - title: 'Got to school',
71 - start: new Date(y, m, d + 16, 12, 0),
72 - end: new Date(y, m, d + 16, 13, 0),
73 - backgroundColor: '#64bd63',
74 - textColor: '#fff',
75 - description: 'Time to go back',
76 - },
77 - {
78 - title: 'Study some Node',
79 - start: new Date(y, m, d + 18, 12, 0),
80 - end: new Date(y, m, d + 18, 13, 0),
81 - backgroundColor: '#79A5F0',
82 - textColor: '#fff',
83 - description: 'Node.js is a platform built ' +
84 - 'on Chrome\'s JavaScript runtime for easily' +
85 - ' building fast, scalable network applications.' +
86 - ' Node.js uses an event-driven, non-blocking' +
87 - ' I/O model that makes it lightweight and' +
88 - ' efficient, perfect for data-intensive real-time' +
89 - ' applications that run across distributed devices.',
90 - },
91 - {
92 - title: 'Click for Flatlogic',
93 - start: new Date(y, m, 28),
94 - end: new Date(y, m, 29),
95 - url: 'http://flatlogic.com/',
96 - backgroundColor: '#e5603b',
97 - textColor: '#fff',
98 - description: 'Creative solutions',
99 - },
100 - ],
101 - selectable: true,
102 - selectHelper: true,
103 - select: (start, end, allDay) => {
104 - this.createEvent = () => {
105 - const title = this.event.title;
106 - if (title) {
107 - this.$calendar.fullCalendar('renderEvent',
108 - {
109 - title,
110 - start,
111 - end,
112 - allDay,
113 - backgroundColor: '#64bd63',
114 - textColor: '#fff',
115 - },
116 - true, // make the event "stick"
117 - );
118 - }
119 - this.$calendar.fullCalendar('unselect');
120 - $('#create-event-modal').modal('hide');
121 - };
122 -
123 - $('#create-event-modal').modal('show');
124 - },
125 - eventClick: (event) => {
126 - this.event = event;
127 - $('#show-event-modal').modal('show');
128 - },
129 - editable: true,
130 - droppable: true,
131 -
132 - drop: (dateItem, event) => { // this function is called when something is dropped
133 - // retrieve the dropped element's stored Event Object
134 - const originalEventObject = {
135 - // use the element's text as the event title
136 - title: $.trim($(event.target).text()),
137 - };
138 -
139 - // we need to copy it, so that multiple events don't have a reference to the same object
140 - const copiedEventObject = $.extend({}, originalEventObject);
141 -
142 - // assign it the date that was reported
143 - copiedEventObject.start = dateItem;
144 - copiedEventObject.allDay = !dateItem.hasTime();
145 -
146 - const $categoryClass = $(event.target).data('event-class');
147 - if ($categoryClass) {
148 - copiedEventObject.className = [$categoryClass];
149 - }
150 -
151 - // render the event on the calendar
152 - // the last `true` argument determines if
153 - // the event 'sticks'
154 - // http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
155 - this.$calendar.fullCalendar('renderEvent', copiedEventObject, true);
156 -
157 - $(event.target).remove();
158 - },
159 - };
160 -
161 - this.dragOptions = { zIndex: 999, revert: true, revertDuration: 0 };
162 -
163 - this.prev = this.prev.bind(this);
164 - this.next = this.next.bind(this);
165 - this.today = this.today.bind(this);
166 - this.changeView = this.changeView.bind(this);
167 - this.getCurrentMonth = this.getCurrentMonth.bind(this);
168 - this.getCurrentDay = this.getCurrentDay.bind(this);
169 - }
170 -
171 - componentDidMount() {
172 - this.$calendar = $('#calendar');
173 - this.$calendar.fullCalendar(this.calendarOptions);
174 - $('.draggable').draggable(this.dragOptions);
175 - }
176 -
177 - getCurrentMonth() {
178 - return moment(this.$calendar.fullCalendar('getDate')).format('MMM YYYY');
179 - }
180 -
181 - getCurrentDay() {
182 - return moment(this.$calendar.fullCalendar('getDate')).format('dddd');
183 - }
184 -
185 - prev() {
186 - this.$calendar.fullCalendar('prev');
187 - }
188 -
189 - next() {
190 - this.$calendar.fullCalendar('next');
191 - }
192 -
193 - today() {
194 - this.$calendar.fullCalendar('today');
195 - }
196 -
197 - changeView(view) {
198 - this.$calendar.fullCalendar('changeView', view);
199 - this.setState({ calendarView: view });
200 - }
201 -
202 - render() {
203 - return (
204 - <div className={s.root}>
205 - <Row>
206 - <Col lg={4} xs={12} md={6}>
207 - <ol className="breadcrumb">
208 - <li className="breadcrumb-item">YOU ARE HERE</li>
209 - <li className="breadcrumb-item active">Calendar</li>
210 - </ol>
211 - <h1 className="page-title">
212 - {this.state.currentMonth} - <span className="fw-semi-bold">{this.state.currentDay}</span>
213 - </h1>
214 - <h3>Draggable <span className="fw-semi-bold">Events</span></h3>
215 - <p>Just drap and drop events from there directly into the calendar.</p>
216 - <div className="calendar-external-events mb-lg">
217 - <div className="external-event draggable" data-event-class="bg-success text-white">
218 - <i className="fa fa-circle fa-fw text-success ml-xs mr-xs" />
219 - Make a tea
220 - </div>
221 - <div className="external-event draggable" data-event-class="bg-warning text-white">
222 - <i className="fa fa-circle fa-fw text-warning ml-xs mr-xs" />
223 - Open windows
224 - </div>
225 - <div className="external-event draggable" data-event-class="bg-gray text-white">
226 - <i className="fa fa-circle-o fa-fw text-gray-light ml-xs mr-xs" />
227 - Some stuff
228 - </div>
229 - <div className="external-event draggable" data-event-class="bg-danger text-white">
230 - <i className="fa fa-square fa-fw text-danger ml-xs mr-xs" />
231 - Study UX engineering
232 - </div>
233 - <div className="external-event draggable" data-event-class="bg-gray text-white">
234 - <i className="fa fa-circle-o fa-fw text-gray-light ml-xs mr-xs" />
235 - Another stuff
236 - </div>
237 - </div>
238 - </Col>
239 - <Col md={6} lg={8} xs={12}>
240 - <Widget>
241 - <Row className="calendar-controls">
242 - <Col md={3}>
243 - <ButtonGroup className="mr-sm">
244 - <Button color="default" onClick={this.prev}>
245 - <i className="fa fa-angle-left" />
246 - </Button>
247 - <Button color="default" onClick={this.next}>
248 - <i className="fa fa-angle-right" />
249 - </Button>
250 - </ButtonGroup>
251 - </Col>
252 - <Col md={9} className="calendar-controls text-right">
253 - <ButtonGroup>
254 - <Button
255 - color="default" onClick={() => this.changeView('month')}
256 - active={this.state.calendarView === 'month'}
257 - >Month</Button>
258 - <Button
259 - color="default" onClick={() => this.changeView('agendaWeek')}
260 - active={this.state.calendarView === 'agendaWeek'}
261 - >Week</Button>
262 - <Button
263 - color="default" onClick={() => this.changeView('agendaDay')}
264 - active={this.state.calendarView === 'agendaDay'}
265 - >Day</Button>
266 - </ButtonGroup>
267 - </Col>
268 - </Row>
269 - <div id="calendar" className="calendar" />
270 - </Widget>
271 - </Col>
272 - </Row>
273 - </div>
274 - );
275 - }
276 -
277 -}
278 -
279 -export default Calendar;
1 -@import '../../../../styles/app';
2 -
3 -:global {
4 - @import '../../../../../node_modules/fullcalendar/dist/fullcalendar';
5 -}
6 -
7 -.root {
8 - h4 {
9 - font-size: 14px;
10 - }
11 -
12 - :global {
13 - .fc-grid th {
14 - text-transform: uppercase;
15 - }
16 -
17 - .fc-day-grid-event {
18 - margin: 0;
19 - padding: 0;
20 - }
21 -
22 - .fc-event {
23 - border: none;
24 - font-weight: $font-weight-normal;
25 - background-color: $gray-200;
26 - color: $text-color;
27 - }
28 -
29 - .fc-today {
30 - background-color: #fff1b8;
31 - }
32 -
33 - a.fc-event {
34 - height: auto;
35 - line-height: $line-height-base;
36 - width: 100%;
37 - }
38 -
39 - /* **** Full Calendar Custom **** */
40 - .full-calendar {
41 - margin-top: 10px;
42 - }
43 -
44 - .calendar-controls {
45 - .btn {
46 - font-size: $font-size-mini;
47 - }
48 - }
49 -
50 - .calendar-external-events {
51 - margin-top: 20px;
52 -
53 - .external-event {
54 - margin: 10px 0;
55 - padding: 6px;
56 - font-size: $font-size-mini;
57 - cursor: pointer;
58 - border-radius: $border-radius;
59 - background-color: $white;
60 - border: 1px solid #ccc;
61 - box-shadow: var(--widget-shadow);
62 - }
63 - }
64 -
65 - .widget-calendar {
66 - @include media-breakpoint-up(xl) {
67 - margin-top: -100px;
68 - }
69 - }
70 - }
71 -}
72 -
1 -{
2 - "name": "calendar",
3 - "version": "0.0.0",
4 - "private": true,
5 - "main": "./Calendar.js"
6 -}
1 -import React from 'react';
2 -import {
3 - Button,
4 - ButtonGroup,
5 - Breadcrumb,
6 - BreadcrumbItem,
7 -} from 'reactstrap';
8 -
9 -import Lightbox from 'react-images';
10 -import s from './Gallery.module.scss';
11 -
12 -import pic1 from '../../../../images/pictures/1.jpg';
13 -import pic2 from '../../../../images/pictures/2.jpg';
14 -import pic3 from '../../../../images/pictures/3.jpg';
15 -import pic4 from '../../../../images/pictures/4.jpg';
16 -import pic5 from '../../../../images/pictures/5.jpg';
17 -import pic6 from '../../../../images/pictures/6.jpg';
18 -import pic8 from '../../../../images/pictures/8.jpg';
19 -import pic9 from '../../../../images/pictures/9.jpg';
20 -import pic10 from '../../../../images/pictures/10.jpg';
21 -import pic11 from '../../../../images/pictures/11.jpg';
22 -import pic13 from '../../../../images/pictures/13.jpg';
23 -import pic14 from '../../../../images/pictures/14.jpg';
24 -
25 -const items = [
26 - {
27 - name: 'Mountains',
28 - groups: [
29 - 'nature',
30 - ],
31 - src: pic1,
32 - date: '10 mins',
33 - },
34 - {
35 - name: 'Empire State Pigeon',
36 - groups: [
37 - 'people',
38 - ],
39 - src: pic2,
40 - date: '1 hour',
41 - like: true,
42 - },
43 - {
44 - name: 'Big Lake',
45 - groups: [
46 - 'nature',
47 - ],
48 - src: pic3,
49 - date: '2 mins',
50 - like: true,
51 - },
52 - {
53 - name: 'Forest',
54 - groups: [
55 - 'nature',
56 - ],
57 - src: pic4,
58 - date: '2 mins',
59 - like: true,
60 - },
61 - {
62 - name: 'Smile',
63 - groups: [
64 - 'people',
65 - ],
66 - src: pic5,
67 - date: '2 mins',
68 - },
69 - {
70 - name: 'Smile',
71 - groups: [
72 - 'people',
73 - ],
74 - src: pic6,
75 - date: '1 hour',
76 - like: true,
77 - },
78 - {
79 - name: 'Fog',
80 - groups: [
81 - 'nature',
82 - ],
83 - src: pic8,
84 - date: '2 mins',
85 - like: true,
86 - },
87 - {
88 - name: 'Beach',
89 - groups: [
90 - 'people',
91 - ],
92 - src: pic9,
93 - date: '2 mins',
94 - },
95 - {
96 - name: 'Pause',
97 - groups: [
98 - 'people',
99 - ],
100 - src: pic10,
101 - date: '3 hour',
102 - like: true,
103 - },
104 - {
105 - name: 'Space',
106 - groups: [
107 - 'space',
108 - ],
109 - src: pic11,
110 - date: '3 hour',
111 - like: true,
112 - },
113 - {
114 - name: 'Shuttle',
115 - groups: [
116 - 'space',
117 - ],
118 - src: pic13,
119 - date: '35 mins',
120 - like: true,
121 - },
122 - {
123 - name: 'Sky',
124 - groups: [
125 - 'space',
126 - ],
127 - src: pic14,
128 - date: '2 mins',
129 - },
130 -];
131 -
132 -class Gallery extends React.Component {
133 - constructor() {
134 - super();
135 -
136 - this.state = {
137 - currentImage: 0,
138 - lightboxIsOpen: false,
139 - children: items,
140 - activeGroup: 'all',
141 - order: 'asc',
142 - theme: {
143 - arrow: {
144 - ':focus': {
145 - outline: 0,
146 - },
147 - },
148 - close: {
149 - ':focus': {
150 - outline: 0,
151 - },
152 - },
153 - },
154 - };
155 -
156 - this.closeLightbox = this.closeLightbox.bind(this);
157 - this.gotoNext = this.gotoNext.bind(this);
158 - this.gotoPrevious = this.gotoPrevious.bind(this);
159 - this.gotoImage = this.gotoImage.bind(this);
160 - this.handleClickImage = this.handleClickImage.bind(this);
161 - this.openLightbox = this.openLightbox.bind(this);
162 - }
163 -
164 - openLightbox(index, event) {
165 - event.preventDefault();
166 - this.setState({
167 - currentImage: index,
168 - lightboxIsOpen: true,
169 - });
170 - }
171 -
172 - gotoPrevious() {
173 - this.setState({
174 - currentImage: this.state.currentImage - 1,
175 - });
176 - }
177 -
178 - gotoImage(index) {
179 - this.setState({
180 - currentImage: index,
181 - });
182 - }
183 -
184 - gotoNext() {
185 - this.setState({
186 - currentImage: this.state.currentImage + 1,
187 - });
188 - }
189 -
190 - closeLightbox() {
191 - this.setState({
192 - currentImage: 0,
193 - lightboxIsOpen: false,
194 - });
195 - }
196 -
197 - handleClickImage() {
198 - if (this.state.currentImage === this.state.children.length - 1) return;
199 -
200 - this.gotoNext();
201 - }
202 -
203 - filterChildren(type) {
204 - this.setState({
205 - children: type === 'all' ? items : items.filter((child) => {
206 - const group = child.groups.find(item => item === type);
207 - return !!group;
208 - }),
209 - activeGroup: type,
210 - });
211 - }
212 -
213 - orderChildren(order) {
214 - const children = this.state.children.sort((a, b) => {
215 - const nameA = a.name.toLowerCase();
216 - const nameB = b.name.toLowerCase();
217 -
218 - if (nameA < nameB) {
219 - return order === 'asc' ? -1 : 1;
220 - }
221 -
222 - if (nameA > nameB) {
223 - return order === 'asc' ? 1 : -1;
224 - }
225 - return 0;
226 - });
227 -
228 - this.setState({ children, order });
229 - }
230 -
231 - render() {
232 - return (
233 - <div className={s.root}>
234 - <Breadcrumb>
235 - <BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
236 - <BreadcrumbItem active>Gallery</BreadcrumbItem>
237 - </Breadcrumb>
238 - <h1 className="page-title">Media - <span className="fw-semi-bold">Images</span>
239 - </h1>
240 -
241 - <div className={s.galleryControls}>
242 - <ButtonGroup id="shuffle-buttons">
243 - <Button color="default" onClick={() => this.filterChildren('all')} active={this.state.activeGroup === 'all'}>All</Button>
244 - <Button color="default" onClick={() => this.filterChildren('nature')} active={this.state.activeGroup === 'nature'}>Nature</Button>
245 - <Button color="default" onClick={() => this.filterChildren('people')} active={this.state.activeGroup === 'people'}>People</Button>
246 - <Button color="default" onClick={() => this.filterChildren('space')} active={this.state.activeGroup === 'space'}>Space</Button>
247 - </ButtonGroup>
248 - <ButtonGroup id="order-buttons">
249 - <Button color="default" onClick={() => this.orderChildren('asc')} active={this.state.order === 'asc'}><i className="fa fa-sort-numeric-asc" /></Button>
250 - <Button color="default" onClick={() => this.orderChildren('desc')} active={this.state.order === 'desc'}><i className="fa fa-sort-numeric-desc" /></Button>
251 - </ButtonGroup>
252 - </div>
253 - <div className={s.gallery}>
254 - {this.state.children.map((item, index) => {
255 - const key = item.name + index;
256 - return (
257 - <div key={key} className={`${s.picture} card`}>
258 - <a href={item.src} onClick={e => this.openLightbox(index, e)}><img className="figure-img" src={item.src} alt="..." /></a>
259 - <div className={s.description}>
260 - <h6 className="mt-0 mb-xs">{item.name}</h6>
261 - <ul className="post-links">
262 - <li><button className="btn-link">{item.date}</button></li>
263 - <li><button className="btn-link"><span className="text-danger"><i className={`fa ${item.like ? 'fa-heart' : 'fa-heart-o'}`} /> Like</span></button></li>
264 - <li><button className="btn-link">Details</button></li>
265 - </ul>
266 - </div>
267 - </div>
268 - );
269 - })}
270 - </div>
271 - <Lightbox
272 - currentImage={this.state.currentImage}
273 - images={this.state.children}
274 - isOpen={this.state.lightboxIsOpen}
275 - onClickPrev={this.gotoPrevious}
276 - onClickNext={this.gotoNext}
277 - onClose={this.closeLightbox}
278 - onClickImage={this.handleClickImage}
279 - onClickThumbnail={this.gotoImage}
280 - backdropClosesModal
281 - enableKeyboardInput
282 - theme={this.state.theme}
283 - />
284 - </div>);
285 - }
286 -
287 -}
288 -
289 -export default Gallery;
1 -@import '../../../../styles/app';
2 -
3 -.root {
4 - :global .tile {
5 - display: inline-block;
6 - }
7 -}
8 -
9 -.galleryControls {
10 - display: flex;
11 - justify-content: space-between;
12 - margin-bottom: $spacer;
13 -}
14 -
15 -.gallery {
16 - display: grid;
17 - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
18 - grid-gap: 15px;
19 -}
20 -
21 -.picture {
22 - padding: 3px;
23 - border-radius: $border-radius;
24 - background-color: $white;
25 -
26 - > a {
27 - overflow: hidden;
28 - }
29 -
30 - :global .figure-img {
31 - width: 100%;
32 - transition: $transition-base;
33 - }
34 -
35 - &:hover {
36 - :global .figure-img {
37 - transform: scale(1.1, 1.1);
38 - }
39 - }
40 -}
41 -
42 -.description {
43 - padding: ($spacer * 0.85) ($spacer * 0.5);
44 -}
1 -{
2 - "name": "invoice",
3 - "version": "0.0.0",
4 - "private": true,
5 - "main": "./Gallery.js"
6 -}
1 -/* eslint class-methods-use-this: ["error", { "exceptMethods": ["printInvoice"] }] */
2 -import React from 'react';
3 -import {
4 - Row,
5 - Col,
6 - Table,
7 - ButtonToolbar,
8 - Button,
9 -} from 'reactstrap';
10 -
11 -import s from './Invoice.module.scss';
12 -import Widget from '../../../../components/Widget';
13 -import iLogo from '../../../../images/invoice-logo.png';
14 -
15 -class Stats extends React.Component {
16 -
17 - printInvoice() {
18 - window.print();
19 - }
20 -
21 - render() {
22 - return (
23 - <Row>
24 - <Col lg={11}>
25 - <Row className={s.root}>
26 - <Col xs={12}>
27 - <Widget>
28 - <div className="widget">
29 - <header>
30 - <Row>
31 - <Col md="6" xs="12" className="col-print-6">
32 - <img src={iLogo} alt="Logo" className={s.invoiceLogo} />
33 - </Col>
34 - <Col md="6" xs="12" className="col-print-6">
35 - <h4 className="text-right">
36 - #<span className="fw-semi-bold">9.45613</span> /
37 - <small>17 May 2014</small>
38 - </h4>
39 - <div className="text-muted fs-larger text-right">
40 - Some Invoice number description or whatever
41 - </div>
42 - </Col>
43 - </Row>
44 - </header>
45 - <section className={s.invoiceBody}>
46 - <Row className="mb-lg">
47 - <Col sm={6} className="col-print-6">
48 - <h5 className="text-muted no-margin">Company Information</h5>
49 - <h3 className="company-name m-t-1">
50 - Wrapbootstrap LLC
51 - </h3>
52 - <address>
53 - <strong>2 Infinite Loop</strong><br />
54 - Minsk, Belarus 220004<br />
55 - 088.253.5345<br />
56 - <abbr title="Work email">e-mail:</abbr> <a href="mailto:#">email@example.com</a><br />
57 - <abbr title="Work Phone">phone:</abbr> (012) 345-678-901<br />
58 - <abbr title="Work Fax">fax:</abbr> (012) 678-132-901
59 - </address>
60 - </Col>
61 -
62 - <Col sm={6} className="col-print-6 text-right">
63 - <h5 className="text-muted no-margin">Client Information</h5>
64 - <h3 className="client-name m-t-1">
65 - Veronica Niasvizhskaja
66 - </h3>
67 - <address>
68 - <strong>Consultant</strong> at
69 - {/* eslint-disable */}
70 - <a href="#">Allspana</a><br />
71 - {/* eslint-enable */}
72 - <abbr title="Work email">e-mail:</abbr> <a href="mailto:#">maryna@allspana.by</a><br />
73 - <abbr title="Work Phone">phone:</abbr> (012) 345-678-901<br />
74 - <abbr title="Work Fax">fax:</abbr> (012) 678-132-901
75 - <p className="no-margin"><strong>Note:</strong></p>
76 - <p className="text-muted">Some nights I stay up cashing in my bad luck.
77 - Some nights I call it a draw</p>
78 - </address>
79 - </Col>
80 - </Row>
81 -
82 - <Table className="table-striped">
83 - <thead>
84 - <tr>
85 - <th>#</th>
86 - <th>Item</th>
87 - <th className="hidden-sm-down d-print-none">Description</th>
88 - <th>Quantity</th>
89 - <th className="hidden-sm-down d-print-none">Price per Unit</th>
90 - <th>Total</th>
91 - </tr>
92 - </thead>
93 - <tbody>
94 - <tr>
95 - <td>1</td>
96 - <td>Brand-new 27 monitor</td>
97 - <td className="hidden-sm-down d-print-none">2,560x1,440-pixel (WQHD) resolution supported!</td>
98 - <td>2</td>
99 - <td className="hidden-sm-down d-print-none">700</td>
100 - <td>1,400.00</td>
101 - </tr>
102 - <tr>
103 - <td>2</td>
104 - <td>Domain: okendoken.com</td>
105 - <td className="hidden-sm-down d-print-none">6-month registration</td>
106 - <td>1</td>
107 - <td className="hidden-sm-down d-print-none">10.99</td>
108 - <td>21.88</td>
109 - </tr>
110 - <tr>
111 - <td>3</td>
112 - <td>Atlas Shrugged</td>
113 - <td className="hidden-sm-down d-print-none">Novel by Ayn Rand, first published in 1957 in the
114 - United
115 - States
116 - </td>
117 - <td>5</td>
118 - <td className="hidden-sm-down d-print-none">35</td>
119 - <td>175.00</td>
120 - </tr>
121 - <tr>
122 - <td>4</td>
123 - <td>New Song by Dr. Pre</td>
124 - <td className="hidden-sm-down d-print-none">Lyrics: praesent blandit augue non sapien ornare
125 - imperdiet
126 - </td>
127 - <td>1</td>
128 - <td className="hidden-sm-down d-print-none">2</td>
129 - <td>2.00</td>
130 - </tr>
131 - </tbody>
132 - </Table>
133 -
134 - <Row>
135 - <Col xs={12} md={8} className="col-print-6">
136 - <p>
137 - <strong>Note:</strong>
138 - Thank you for your business. Keep in mind, sometimes bad things happen. But it&#39;s just
139 - sometimes.
140 - </p>
141 - </Col>
142 - <Col md={4} xs={12} className="col-print-6">
143 - <Row className="text-right justify-content-end">
144 - <Col xs={6} />
145 - <Col sm={3}>
146 - <p>Subtotal</p>
147 - <p>Tax(10%)</p>
148 - <p className="no-margin"><strong>Total</strong></p>
149 - </Col>
150 - <Col sm={3}>
151 - <p>1,598.88</p>
152 - <p>159.89</p>
153 - <p className="no-margin"><strong>1,758.77</strong></p>
154 - </Col>
155 - </Row>
156 - </Col>
157 - </Row>
158 - <p className="text-right mt-lg mb-xs">
159 - Marketing Consultant
160 - </p>
161 - <p className="text-right">
162 - <span className="fw-semi-bold">Bob Smith</span>
163 - </p>
164 - <ButtonToolbar className="mt-lg justify-content-end d-print-none">
165 - <Button onClick={this.printInvoice} color="inverse" className="mr-2">
166 - <i className="fa fa-print" />
167 - &nbsp;&nbsp;
168 - Print
169 - </Button>
170 - <Button color="danger">
171 - Proceed with Payment
172 - &nbsp;
173 - <span className="circle bg-white">
174 - <i className="fa fa-arrow-right text-danger" />
175 - </span>
176 - </Button>
177 - </ButtonToolbar>
178 - </section>
179 - </div>
180 - </Widget>
181 - </Col>
182 - </Row>
183 - </Col>
184 - </Row>);
185 - }
186 -
187 -}
188 -
189 -export default Stats;
1 -@import '../../../../styles/app';
2 -
3 -.root {
4 - .invoiceLogo {
5 - max-height: 50px;
6 - }
7 -
8 - .invoiceBody {
9 - margin-top: 70px;
10 - }
11 -
12 - :global {
13 - .widget {
14 - padding: 10px 20px;
15 - }
16 - }
17 -}
1 -{
2 - "name": "invoice",
3 - "version": "0.0.0",
4 - "private": true,
5 - "main": "./Invoice.js"
6 -}
This diff is collapsed. Click to expand it.
1 -@import '../../../../styles/app';
2 -
3 -.root {
4 - .searchResultCategories {
5 - > li > a {
6 - color: $gray-600;
7 - font-weight: $font-weight-normal;
8 -
9 - &:hover {
10 - color: $gray-700;
11 - background-color: $gray-400;
12 - }
13 - }
14 - }
15 -
16 - .searchResultsCount {
17 - margin-top: 10px;
18 - }
19 -
20 - .searchResultItem {
21 - padding: 20px;
22 - background-color: $white;
23 - border-radius: $border-radius;
24 - box-shadow: var(--widget-shadow);
25 -
26 - &:first-of-type {
27 - overflow: hidden;
28 - }
29 -
30 - @include clearfix();
31 -
32 - .imageLink {
33 - display: block;
34 - overflow: hidden;
35 - border-top-left-radius: $border-radius;
36 - border-bottom-left-radius: $border-radius;
37 -
38 - @include media-breakpoint-up(md) {
39 - display: inline-block;
40 - margin: -20px 0 -20px -20px;
41 - float: left;
42 - width: 200px;
43 - }
44 -
45 - @include media-breakpoint-down(sm) {
46 - max-height: 200px;
47 - }
48 - }
49 -
50 - .image {
51 - max-width: 100%;
52 - }
53 -
54 - .info {
55 - margin-top: 2px;
56 - font-size: $font-size-sm;
57 - color: $text-muted;
58 - }
59 -
60 - .description {
61 - font-size: $font-size-mini;
62 - margin-bottom: -5px;
63 - }
64 -
65 - + .searchResultItem {
66 - margin-top: 20px;
67 - }
68 -
69 - .searchResultItemBody {
70 - height: auto;
71 -
72 - @include media-breakpoint-down(sm) {
73 - margin-top: 10px;
74 - }
75 -
76 - @include media-breakpoint-up(md) {
77 - margin-left: 200px;
78 - }
79 - }
80 -
81 - .searchResultItemHeading {
82 - font-weight: $font-weight-normal;
83 -
84 - > a {
85 - color: $text-color;
86 - }
87 -
88 - @include media-breakpoint-up(md) {
89 - margin: 0;
90 - }
91 - }
92 - }
93 -}
1 -{
2 - "name": "search",
3 - "version": "0.0.0",
4 - "private": true,
5 - "main": "./Search.js"
6 -}
This diff is collapsed. Click to expand it.
1 -@import '../../../../styles/app';
2 -
3 -/* Post Comments */
4 -.postComments {
5 - font-size: $font-size-sm;
6 - padding-left: 0;
7 -
8 - @include clearfix();
9 -
10 - .postLinks + & {
11 - margin-top: $spacer / 2;
12 - }
13 -
14 - > li {
15 - padding: 10px;
16 - border-top: 1px solid #e7e7e7;
17 - list-style: none;
18 -
19 - @include clearfix();
20 -
21 - &:last-child {
22 - padding-bottom: 0;
23 - }
24 - }
25 -
26 - p:last-child {
27 - margin-bottom: 0;
28 - }
29 -
30 - .avatar {
31 - margin-top: 1px;
32 - }
33 -
34 - .author {
35 - margin-top: 0;
36 - margin-bottom: 2px;
37 - color: #7ca9dd;
38 - }
39 -
40 - .commentBody {
41 - overflow: auto;
42 - }
43 -
44 - h6.author > small {
45 - font-size: 11px;
46 - }
47 -
48 - :global {
49 - .widget > footer & {
50 - margin-left: -$widget-padding-horizontal;
51 - margin-right: -$widget-padding-horizontal;
52 - }
53 - }
54 -}
55 -
56 -/* Post Links */
57 -.postLinks {
58 - margin-bottom: 0;
59 - font-size: $font-size-sm;
60 - padding-left: 0;
61 -
62 - @include clearfix();
63 -
64 - > li {
65 - float: left;
66 - list-style: none;
67 -
68 - + li {
69 - &::before {
70 - color: #999;
71 - content: '\25cf';
72 - padding: 0 8px;
73 - }
74 - }
75 -
76 - > a {
77 - text-decoration: none;
78 - color: $text-muted;
79 -
80 - :hover {
81 - color: $text-muted;
82 - }
83 - }
84 - }
85 -
86 - :global {
87 - .no-separator > li + li {
88 - margin-left: 12px;
89 -
90 - &::before {
91 - content: normal;
92 - }
93 - }
94 - }
95 -}
96 -
97 -/* Time Line */
98 -.timeline {
99 - position: relative;
100 - min-height: 100%;
101 - list-style: none;
102 - padding-left: 0;
103 - margin-bottom: -40px; /* content padding bottom */
104 - padding-bottom: 80px;
105 -
106 - > li {
107 - @include clearfix();
108 -
109 - + li {
110 - margin-top: 30px;
111 - }
112 - }
113 -
114 - /* the time line :) */
115 - &::before {
116 - position: absolute;
117 - top: 0;
118 - bottom: 0;
119 - left: 24%;
120 - width: 8px;
121 - content: ' ';
122 - margin-left: -4px;
123 - background-color: $white;
124 -
125 - @include media-breakpoint-up(lg) {
126 - left: 50%;
127 - margin-left: -4px;
128 - }
129 - }
130 -}
131 -
132 -.event {
133 - background: $white;
134 - border-radius: $border-radius;
135 - padding: 20px 20px 0;
136 - position: relative;
137 - box-shadow: var(--widget-shadow);
138 -
139 - .timeline & {
140 - float: right;
141 - width: 68%;
142 -
143 - &::before {
144 - right: 100%;
145 - content: ' ';
146 - height: 0;
147 - width: 0;
148 - position: absolute;
149 - border: 10px solid rgba(0, 0, 0, 0);
150 - border-right-color: $white;
151 - top: 15px;
152 - }
153 - }
154 -
155 - .postComments {
156 - margin-left: -20px;
157 - margin-right: -20px;
158 - }
159 -
160 - > footer {
161 - margin: 20px -20px 0;
162 - padding: 10px 20px;
163 - border-bottom-left-radius: $border-radius;
164 - border-bottom-right-radius: $border-radius;
165 - background-color: #fafafa;
166 -
167 - @include clearfix();
168 -
169 - :global {
170 - .thumb {
171 - margin-left: 10px;
172 - }
173 - }
174 - }
175 -
176 - @include media-breakpoint-up(lg) {
177 - .timeline & {
178 - width: 45%;
179 - }
180 -
181 - .timeline > li.onLeft & {
182 - float: left;
183 -
184 - &::before {
185 - right: auto;
186 - left: 100%;
187 - border-right-color: rgba(0, 0, 0, 0);
188 - border-left-color: $white;
189 - }
190 - }
191 - }
192 -}
193 -
194 -.eventTime {
195 - .timeline & {
196 - float: left;
197 - width: 18%;
198 - margin-top: 5px;
199 - text-align: right;
200 -
201 - > .date {
202 - display: block;
203 - font-size: $font-size-larger;
204 - }
205 -
206 - > .time {
207 - display: block;
208 - font-size: $font-size-lg;
209 - font-weight: $font-weight-normal;
210 - }
211 - }
212 -
213 - @include media-breakpoint-up(lg) {
214 - .timeline & {
215 - width: 46%;
216 - }
217 -
218 - .timeline > li.onLeft & {
219 - float: right;
220 - text-align: left;
221 - }
222 - }
223 -}
224 -
225 -.eventIcon {
226 - :global {
227 - .glyphicon {
228 - top: -2px;
229 - }
230 - }
231 -
232 - .timeline & {
233 - position: absolute;
234 - left: 24%;
235 - width: 50px;
236 - height: 50px;
237 - line-height: 37px;
238 - margin-left: -25px;
239 - background-color: $white;
240 - border: 7px solid $white;
241 - border-radius: 50%;
242 - text-align: center;
243 - box-shadow: var(--widget-shadow);
244 -
245 - &.eventIconDanger {
246 - background-color: theme-color('danger');
247 - border-color: lighten(theme-color('danger'), 7%);
248 - }
249 -
250 - &.eventIconWarning {
251 - background-color: theme-color('warning');
252 - border-color: lighten(theme-color('warning'), 7%);
253 - }
254 -
255 - &.eventIconSuccess {
256 - background-color: theme-color('success');
257 - border-color: lighten(theme-color('success'), 7%);
258 - }
259 -
260 - &.eventIconInfo {
261 - background-color: theme-color('info');
262 - border-color: lighten(theme-color('info'), 7%);
263 - }
264 -
265 - &.eventIconPrimary {
266 - background-color: theme-color('primary');
267 - border-color: lighten(theme-color('primary'), 7%);
268 - }
269 -
270 - &.eventIconDanger,
271 - &.eventIconWarning,
272 - &.eventIconSuccess,
273 - &.eventIconInfo,
274 - &.eventIconPrimary {
275 - color: $white;
276 - }
277 -
278 - @include media-breakpoint-up(lg) {
279 - left: 50%;
280 - }
281 -
282 - > img {
283 - width: 36px;
284 - height: 36px;
285 - margin-top: -4px;
286 - }
287 - }
288 -}
289 -
290 -.eventHeading {
291 - margin: 0 0 2px;
292 - font-weight: $font-weight-semi-bold;
293 -
294 - > a {
295 - text-decoration: none;
296 - color: #7ca9dd;
297 - }
298 -
299 - > small {
300 - font-weight: $font-weight-semi-bold;
301 -
302 - > a {
303 - text-decoration: none;
304 - color: $text-muted;
305 - }
306 - }
307 -}
308 -
309 -.eventMap {
310 - display: block;
311 - height: 200px;
312 - margin: 0 -20px -20px;
313 - overflow: visible !important;
314 -}
315 -
316 -.eventImage {
317 - margin: 0 -20px -20px;
318 - max-height: 260px;
319 - overflow: hidden;
320 -
321 - > img {
322 - max-width: 100%;
323 - }
324 -}
325 -
1 -{
2 - "name": "timeline",
3 - "version": "0.0.0",
4 - "main": "./Timeline.js",
5 - "private": true
6 -}
This diff is collapsed. Click to expand it.
1 -@import '../../../../styles/app';
2 -
3 -:global {
4 - @import '../../../../../node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg';
5 - @import '../../../../../node_modules/react-select2-wrapper/css/select2';
6 - @import '../../../../../node_modules/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox';
7 - @import '../../../../../node_modules/react-datetime/css/react-datetime';
8 - @import '../../../../../node_modules/rc-color-picker/dist/rc-color-picker';
9 - @import '../../../../../node_modules/bootstrap-slider/dist/css/bootstrap-slider';
10 - @import '../../../../../node_modules/jasny-bootstrap/dist/css/jasny-bootstrap';
11 - @import '../../../../../node_modules/react-mde/lib/styles/scss/react-mde-all';
12 -}
13 -
14 -.autogrow {
15 - overflow: hidden;
16 - resize: none;
17 -}
18 -
19 -.wysiwygWrapper {
20 - border: 1px solid #ccc !important;
21 - overflow: visible;
22 - height: 270px;
23 -}
24 -
25 -.wysiwygToolbar {
26 - color: $gray-800 !important;
27 - background-color: #ddd !important;
28 - border-color: transparent !important;
29 -
30 - :global {
31 - .rdw-option-wrapper {
32 - font-family: 'Open Sans', sans-serif;
33 - font-size: 14px;
34 - height: 30px;
35 - min-width: 30px;
36 - margin: 0;
37 - background: #f8f8f8;
38 - }
39 -
40 - .rdw-dropdown-wrapper {
41 - background: #f8f8f8;
42 - }
43 - }
44 -}
45 -
46 -.wysiwygEditor {
47 - position: relative !important;
48 - overflow: hidden !important;
49 - height: 150px;
50 - line-height: 0.1;
51 -}
52 -
53 -.select2 {
54 - :global {
55 - .select2-container {
56 - width: 100% !important;
57 - }
58 -
59 - .select2-selection--single {
60 - border-color: $input-border-color;
61 -
62 - &,
63 - & :global .select2-selection__arrow {
64 - height: $input-height;
65 - }
66 -
67 - & :global .select2-selection__rendered {
68 - line-height: $input-height;
69 - }
70 - }
71 - }
72 -}
73 -
74 -.root {
75 - :global {
76 - /*
77 - * Switchery.
78 - */
79 -
80 - .abc-checkbox,
81 - .abc-radio {
82 - .form-check-input {
83 - position: relative;
84 - margin: 0;
85 - }
86 - }
87 -
88 - .display-inline-block {
89 - display: inline-block;
90 - }
91 -
92 - .display-none {
93 - display: none;
94 - }
95 -
96 - .switch {
97 - box-sizing: content-box;
98 - }
99 -
100 - .switch input {
101 - display: none;
102 - }
103 -
104 - .switch i {
105 - display: inline-block;
106 - cursor: pointer;
107 - padding-right: 20px;
108 - transition: all ease 0.2s;
109 - -webkit-transition: all ease 0.2s;
110 - border-radius: 20px;
111 - box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5);
112 - }
113 -
114 - .switch i::before {
115 - display: block;
116 - content: '';
117 - width: 30px;
118 - height: 30px;
119 - padding: 1px;
120 - border-radius: 20px;
121 - background: white;
122 - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
123 - }
124 -
125 - .switch :checked + i {
126 - padding-right: 0;
127 - padding-left: 20px;
128 - background: rgb(100, 189, 99);
129 - }
130 -
131 - /* Datepicker */
132 -
133 - .datepicker {
134 - .input-group-addon {
135 - display: inline-block;
136 - position: relative;
137 - top: -2px;
138 - left: -2px;
139 - }
140 -
141 - i.glyphicon {
142 - vertical-align: top;
143 - }
144 -
145 - .rdt {
146 - display: inline-block;
147 - }
148 - }
149 -
150 - /* slider */
151 -
152 - $slider-line-height: 8px;
153 - $slider-handle-size: 26px;
154 -
155 - .slider {
156 - display: inline-block;
157 - vertical-align: middle;
158 - position: relative;
159 -
160 - .slider-handle {
161 - position: absolute;
162 - width: $slider-handle-size;
163 - height: $slider-handle-size;
164 - background: $white;
165 - border: 0 solid transparent;
166 -
167 - @include box-shadow(inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 3px rgba(0, 0, 0, 5));
168 -
169 - &:focus {
170 - outline: 0;
171 - }
172 -
173 - &.round {
174 - border-radius: 50%;
175 - }
176 -
177 - &.triangle {
178 - background: transparent none;
179 - }
180 - }
181 -
182 - &.slider-horizontal {
183 - width: 210px;
184 - height: $slider-line-height;
185 -
186 - .slider-track {
187 - height: $slider-line-height/2;
188 - width: 100%;
189 - margin-top: -$slider-line-height/4;
190 - top: 50%;
191 - left: 0;
192 - }
193 -
194 - .slider-selection {
195 - height: 100%;
196 - top: 0;
197 - bottom: 0;
198 - }
199 -
200 - .slider-handle {
201 - margin-left: -$slider-handle-size/2;
202 - margin-top: -$slider-handle-size*3/8;
203 -
204 - &.triangle {
205 - border-width: 0 $slider-line-height/2 $slider-line-height/2 $slider-line-height/2;
206 - width: 0;
207 - height: 0;
208 - border-bottom-color: #0480be;
209 - margin-top: 0;
210 - }
211 - }
212 - }
213 -
214 - &.slider-vertical {
215 - height: 210px;
216 - width: $slider-line-height;
217 -
218 - .slider-track {
219 - width: $slider-line-height/2;
220 - height: 100%;
221 - margin-left: -$slider-line-height/4;
222 - left: 50%;
223 - top: 0;
224 - }
225 -
226 - .slider-selection {
227 - width: 100%;
228 - left: 0;
229 - top: 0;
230 - bottom: 0;
231 - }
232 -
233 - .slider-handle {
234 - margin-left: -$slider-handle-size*3/8;
235 - margin-top: -$slider-handle-size/2;
236 -
237 - &.triangle {
238 - border-width: $slider-line-height/2 0 $slider-line-height/2 $slider-line-height/2;
239 - width: 1px;
240 - height: 1px;
241 - border-left-color: #0480be;
242 - margin-left: 0;
243 - }
244 - }
245 - }
246 -
247 - &.slider-disabled {
248 - .slider-handle {
249 - // @include gradient-y(#dfdfdf, #bebebe);
250 - }
251 -
252 - .slider-track {
253 - @include gradient-y(#e5e5e5, #e9e9e9);
254 -
255 - cursor: not-allowed;
256 - }
257 - }
258 -
259 - input {
260 - display: none;
261 - }
262 -
263 - .tooltip-inner {
264 - white-space: nowrap;
265 - }
266 - }
267 -
268 - .slider-selection {
269 - position: absolute;
270 - background: theme-color('primary');
271 -
272 - @include box-shadow(inset 0 -1px 0 rgba(0, 0, 0, 0.15));
273 -
274 - box-sizing: border-box;
275 - border-radius: $border-radius;
276 - }
277 -
278 - .slider-danger .slider .slider-selection {
279 - background: theme-color('danger'); // $brand-danger;
280 - }
281 -
282 - .slider-success .slider .slider-selection {
283 - background: theme-color('success'); // $brand-success;
284 - }
285 -
286 - .slider-warning .slider .slider-selection {
287 - background: theme-color('warning'); // $brand-warning;
288 - }
289 -
290 - .slider-info .slider .slider-selection {
291 - background: theme-color('info'); // $brand-info;
292 - }
293 -
294 - .slider-inverse .slider .slider-selection {
295 - background: $gray-700; // $gray;
296 - }
297 -
298 - .slider-track {
299 - position: absolute;
300 - cursor: pointer;
301 - border-radius: $border-radius;
302 -
303 - @include gradient-y(#eee, #f8f8f8);
304 - @include box-shadow(inset 0 1px 2px rgba(0, 0, 0, 0.1));
305 - }
306 -
307 - /* file input */
308 -
309 - .fileinput.fileinput-new {
310 - .thumbnail {
311 - padding: $thumbnail-padding;
312 - line-height: $line-height-base;
313 - background-color: $thumbnail-bg;
314 - border: $thumbnail-border-width solid $thumbnail-border-color;
315 - border-radius: $thumbnail-border-radius;
316 - transition: all 0.2s ease-in-out;
317 -
318 - @include box-shadow(0 1px 2px rgba(0, 0, 0, 0.075));
319 - }
320 -
321 - &.fileinput-fix {
322 - width: 200px;
323 - height: 150px;
324 - }
325 - }
326 -
327 - .btn {
328 - label {
329 - margin-bottom: 0;
330 - }
331 - }
332 -
333 - .fileinput-preview.fileinput-exists {
334 - border: 1px solid $input-border-color;
335 - border-radius: $border-radius;
336 - padding: 5px;
337 - }
338 -
339 - .fileinput.input-group {
340 - display: flex;
341 - }
342 -
343 - .fileinput-new.input-group .btn-file,
344 - .fileinput-new .input-group .btn-file {
345 - border-radius: 0 $border-radius $border-radius 0;
346 -
347 - &.btn-xs,
348 - &.btn-sm {
349 - border-radius: 0 $border-radius-sm $border-radius-sm 0;
350 - }
351 -
352 - &.btn-lg {
353 - border-radius: 0 $border-radius-lg $border-radius-lg 0;
354 - }
355 - }
356 -
357 - .form-group.has-warning .fileinput {
358 - .fileinput-preview {
359 - color: #fff;
360 - }
361 -
362 - .thumbnail {
363 - border-color: theme-color('warning');
364 - }
365 - }
366 -
367 - .form-group.has-error .fileinput {
368 - .fileinput-preview {
369 - color: #fff;
370 - }
371 -
372 - .thumbnail {
373 - border-color: theme-color('danger');
374 - }
375 - }
376 -
377 - .form-group.has-success .fileinput {
378 - .fileinput-preview {
379 - color: #fff;
380 - }
381 -
382 - .thumbnail {
383 - border-color: theme-color('success');
384 - }
385 - }
386 -
387 - .btn-label {
388 - background: transparent;
389 - left: 2px;
390 - padding: 1px 6px;
391 - }
392 -
393 - // Opposite alignment of blockquote
394 - .blockquote {
395 - padding: ($spacer / 2) $spacer;
396 - margin-bottom: $spacer;
397 - font-size: $blockquote-font-size;
398 - border-left: 0.25rem solid $gray-300;
399 - }
400 -
401 - .blockquote footer {
402 - display: block;
403 - font-size: 80%; // back to default font-size
404 - color: $blockquote-small-color;
405 -
406 - &::before {
407 - content: '\2014 \00A0'; // em dash, nbsp
408 - }
409 - }
410 -
411 - .blockquote-reverse {
412 - padding-right: $spacer;
413 - padding-left: 0;
414 - text-align: right;
415 - border-right: 0.25rem solid $gray-300;
416 - border-left: 0;
417 - }
418 -
419 - .blockquote-reverse footer {
420 - &::before {
421 - content: '';
422 - }
423 -
424 - &::after {
425 - content: '\00A0 \2014'; // nbsp, em dash
426 - }
427 - }
428 - }
429 -}
430 -
431 -.dropzone {
432 - width: 100%;
433 - text-align: center;
434 - padding: 40px 10px;
435 - height: 200px;
436 - border: 2px dashed #ccc;
437 -
438 - @include border-radius($border-radius);
439 -
440 - img {
441 - max-height: 100px;
442 - max-width: 150px;
443 - border-radius: 5px;
444 - }
445 -}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.