.js` file.
+
+### Static Server
+
+For environments using [Node](https://nodejs.org/), the easiest way to handle this would be to install [serve](https://github.com/zeit/serve) and let it handle the rest:
+
+```sh
+npm install -g serve
+serve -s build
+```
+
+The last command shown above will serve your static site on the port **5000**. Like many of [serve](https://github.com/zeit/serve)’s internal settings, the port can be adjusted using the `-p` or `--port` flags.
+
+Run this command to get a full list of the options available:
+
+```sh
+serve -h
+```
+
+### Other Solutions
+
+You don’t necessarily need a static server in order to run a Create React App project in production. It works just as fine integrated into an existing dynamic one.
+
+Here’s a programmatic example using [Node](https://nodejs.org/) and [Express](http://expressjs.com/):
+
+```javascript
+const express = require('express');
+const path = require('path');
+const app = express();
+
+app.use(express.static(path.join(__dirname, 'build')));
+
+app.get('/', function (req, res) {
+ res.sendFile(path.join(__dirname, 'build', 'index.html'));
+});
+
+app.listen(9000);
+```
+
+The choice of your server software isn’t important either. Since Create React App is completely platform-agnostic, there’s no need to explicitly use Node.
+
+The `build` folder with static assets is the only output produced by Create React App.
+
+However this is not quite enough if you use client-side routing. Read the next section if you want to support URLs like `/todos/42` in your single-page app.
+
+### Serving Apps with Client-Side Routing
+
+If you use routers that use the HTML5 [`pushState` history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries) under the hood (for example, [React Router](https://github.com/ReactTraining/react-router) with `browserHistory`), many static file servers will fail. For example, if you used React Router with a route for `/todos/42`, the development server will respond to `localhost:3000/todos/42` properly, but an Express serving a production build as above will not.
+
+This is because when there is a fresh page load for a `/todos/42`, the server looks for the file `build/todos/42` and does not find it. The server needs to be configured to respond to a request to `/todos/42` by serving `index.html`. For example, we can amend our Express example above to serve `index.html` for any unknown paths:
+
+```diff
+ app.use(express.static(path.join(__dirname, 'build')));
+
+-app.get('/', function (req, res) {
++app.get('/*', function (req, res) {
+ res.sendFile(path.join(__dirname, 'build', 'index.html'));
+ });
+```
+
+If you’re using [Apache](https://httpd.apache.org/), you need to create a `.htaccess` file in the `public` folder that looks like this:
+
+```
+ Options -MultiViews
+ RewriteEngine On
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^ index.html [QSA,L]
+```
+
+It will get copied to the `build` folder when you run `npm run build`.
+
+Now requests to `/todos/42` will be handled correctly both in development and in production.
+
+On a production build, and in a browser that supports [service workers](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers),
+the service worker will automatically handle all navigation requests, like for
+`/todos/42`, by serving the cached copy of your `index.html`. This
+service worker navigation routing can be configured or disabled by
+[`eject`ing](#npm-run-eject) and then modifying the
+[`navigateFallback`](https://github.com/GoogleChrome/sw-precache#navigatefallback-string)
+and [`navigateFallbackWhitelist`](https://github.com/GoogleChrome/sw-precache#navigatefallbackwhitelist-arrayregexp)
+options of the `SWPreachePlugin` [configuration](../config/webpack.config.prod.js).
+
+### Building for Relative Paths
+
+By default, Create React App produces a build assuming your app is hosted at the server root.
+To override this, specify the `homepage` in your `package.json`, for example:
+
+```js
+ "homepage": "http://mywebsite.com/relativepath",
+```
+
+This will let Create React App correctly infer the root path to use in the generated HTML file.
+
+#### Serving the Same Build from Different Paths
+
+>Note: this feature is available with `react-scripts@0.9.0` and higher.
+
+If you are not using the HTML5 `pushState` history API or not using client-side routing at all, it is unnecessary to specify the URL from which your app will be served. Instead, you can put this in your `package.json`:
+
+```js
+ "homepage": ".",
+```
+
+This will make sure that all the asset paths are relative to `index.html`. You will then be able to move your app from `http://mywebsite.com` to `http://mywebsite.com/relativepath` or even `http://mywebsite.com/relative/path` without having to rebuild it.
+
+### Azure
+
+See [this](https://medium.com/@to_pe/deploying-create-react-app-on-microsoft-azure-c0f6686a4321) blog post on how to deploy your React app to [Microsoft Azure](https://azure.microsoft.com/).
+
+### Firebase
+
+Install the Firebase CLI if you haven’t already by running `npm install -g firebase-tools`. Sign up for a [Firebase account](https://console.firebase.google.com/) and create a new project. Run `firebase login` and login with your previous created Firebase account.
+
+Then run the `firebase init` command from your project’s root. You need to choose the **Hosting: Configure and deploy Firebase Hosting sites** and choose the Firebase project you created in the previous step. You will need to agree with `database.rules.json` being created, choose `build` as the public directory, and also agree to **Configure as a single-page app** by replying with `y`.
+
+```sh
+ === Project Setup
+
+ First, let's associate this project directory with a Firebase project.
+ You can create multiple project aliases by running firebase use --add,
+ but for now we'll just set up a default project.
+
+ ? What Firebase project do you want to associate as default? Example app (example-app-fd690)
+
+ === Database Setup
+
+ Firebase Realtime Database Rules allow you to define how your data should be
+ structured and when your data can be read from and written to.
+
+ ? What file should be used for Database Rules? database.rules.json
+ ✔ Database Rules for example-app-fd690 have been downloaded to database.rules.json.
+ Future modifications to database.rules.json will update Database Rules when you run
+ firebase deploy.
+
+ === Hosting Setup
+
+ Your public directory is the folder (relative to your project directory) that
+ will contain Hosting assets to uploaded with firebase deploy. If you
+ have a build process for your assets, use your build's output directory.
+
+ ? What do you want to use as your public directory? build
+ ? Configure as a single-page app (rewrite all urls to /index.html)? Yes
+ ✔ Wrote build/index.html
+
+ i Writing configuration info to firebase.json...
+ i Writing project information to .firebaserc...
+
+ ✔ Firebase initialization complete!
+```
+
+Now, after you create a production build with `npm run build`, you can deploy it by running `firebase deploy`.
+
+```sh
+ === Deploying to 'example-app-fd690'...
+
+ i deploying database, hosting
+ ✔ database: rules ready to deploy.
+ i hosting: preparing build directory for upload...
+ Uploading: [============================== ] 75%✔ hosting: build folder uploaded successfully
+ ✔ hosting: 8 files uploaded successfully
+ i starting release process (may take several minutes)...
+
+ ✔ Deploy complete!
+
+ Project Console: https://console.firebase.google.com/project/example-app-fd690/overview
+ Hosting URL: https://example-app-fd690.firebaseapp.com
+```
+
+For more information see [Add Firebase to your JavaScript Project](https://firebase.google.com/docs/web/setup).
+
+### GitHub Pages
+
+>Note: this feature is available with `react-scripts@0.2.0` and higher.
+
+#### Step 1: Add `homepage` to `package.json`
+
+**The step below is important!**
+**If you skip it, your app will not deploy correctly.**
+
+Open your `package.json` and add a `homepage` field:
+
+```js
+ "homepage": "https://myusername.github.io/my-app",
+```
+
+Create React App uses the `homepage` field to determine the root URL in the built HTML file.
+
+#### Step 2: Install `gh-pages` and add `deploy` to `scripts` in `package.json`
+
+Now, whenever you run `npm run build`, you will see a cheat sheet with instructions on how to deploy to GitHub Pages.
+
+To publish it at [https://myusername.github.io/my-app](https://myusername.github.io/my-app), run:
+
+```sh
+npm install --save-dev gh-pages
+```
+
+Add the following scripts in your `package.json`:
+
+```js
+ // ...
+ "scripts": {
+ // ...
+ "predeploy": "npm run build",
+ "deploy": "gh-pages -d build"
+ }
+```
+
+The `predeploy` script will run automatically before `deploy` is run.
+
+#### Step 3: Deploy the site by running `npm run deploy`
+
+Then run:
+
+```sh
+npm run deploy
+```
+
+#### Step 4: Ensure your project’s settings use `gh-pages`
+
+Finally, make sure **GitHub Pages** option in your GitHub project settings is set to use the `gh-pages` branch:
+
+
+
+#### Step 5: Optionally, configure the domain
+
+You can configure a custom domain with GitHub Pages by adding a `CNAME` file to the `public/` folder.
+
+#### Notes on client-side routing
+
+GitHub Pages doesn’t support routers that use the HTML5 `pushState` history API under the hood (for example, React Router using `browserHistory`). This is because when there is a fresh page load for a url like `http://user.github.io/todomvc/todos/42`, where `/todos/42` is a frontend route, the GitHub Pages server returns 404 because it knows nothing of `/todos/42`. If you want to add a router to a project hosted on GitHub Pages, here are a couple of solutions:
+
+* You could switch from using HTML5 history API to routing with hashes. If you use React Router, you can switch to `hashHistory` for this effect, but the URL will be longer and more verbose (for example, `http://user.github.io/todomvc/#/todos/42?_k=yknaj`). [Read more](https://github.com/reactjs/react-router/blob/master/docs/guides/Histories.md#histories) about different history implementations in React Router.
+* Alternatively, you can use a trick to teach GitHub Pages to handle 404 by redirecting to your `index.html` page with a special redirect parameter. You would need to add a `404.html` file with the redirection code to the `build` folder before deploying your project, and you’ll need to add code handling the redirect parameter to `index.html`. You can find a detailed explanation of this technique [in this guide](https://github.com/rafrex/spa-github-pages).
+
+### Heroku
+
+Use the [Heroku Buildpack for Create React App](https://github.com/mars/create-react-app-buildpack).
+You can find instructions in [Deploying React with Zero Configuration](https://blog.heroku.com/deploying-react-with-zero-configuration).
+
+#### Resolving Heroku Deployment Errors
+
+Sometimes `npm run build` works locally but fails during deploy via Heroku. Following are the most common cases.
+
+##### "Module not found: Error: Cannot resolve 'file' or 'directory'"
+
+If you get something like this:
+
+```
+remote: Failed to create a production build. Reason:
+remote: Module not found: Error: Cannot resolve 'file' or 'directory'
+MyDirectory in /tmp/build_1234/src
+```
+
+It means you need to ensure that the lettercase of the file or directory you `import` matches the one you see on your filesystem or on GitHub.
+
+This is important because Linux (the operating system used by Heroku) is case sensitive. So `MyDirectory` and `mydirectory` are two distinct directories and thus, even though the project builds locally, the difference in case breaks the `import` statements on Heroku remotes.
+
+##### "Could not find a required file."
+
+If you exclude or ignore necessary files from the package you will see a error similar this one:
+
+```
+remote: Could not find a required file.
+remote: Name: `index.html`
+remote: Searched in: /tmp/build_a2875fc163b209225122d68916f1d4df/public
+remote:
+remote: npm ERR! Linux 3.13.0-105-generic
+remote: npm ERR! argv "/tmp/build_a2875fc163b209225122d68916f1d4df/.heroku/node/bin/node" "/tmp/build_a2875fc163b209225122d68916f1d4df/.heroku/node/bin/npm" "run" "build"
+```
+
+In this case, ensure that the file is there with the proper lettercase and that’s not ignored on your local `.gitignore` or `~/.gitignore_global`.
+
+### Modulus
+
+See the [Modulus blog post](http://blog.modulus.io/deploying-react-apps-on-modulus) on how to deploy your react app to Modulus.
+
+### Netlify
+
+**To do a manual deploy to Netlify’s CDN:**
+
+```sh
+npm install netlify-cli
+netlify deploy
+```
+
+Choose `build` as the path to deploy.
+
+**To setup continuous delivery:**
+
+With this setup Netlify will build and deploy when you push to git or open a pull request:
+
+1. [Start a new netlify project](https://app.netlify.com/signup)
+2. Pick your Git hosting service and select your repository
+3. Click `Build your site`
+
+**Support for client-side routing:**
+
+To support `pushState`, make sure to create a `public/_redirects` file with the following rewrite rules:
+
+```
+/* /index.html 200
+```
+
+When you build the project, Create React App will place the `public` folder contents into the build output.
+
+### Now
+
+[now](https://zeit.co/now) offers a zero-configuration single-command deployment.
+
+1. Install the `now` command-line tool either via the recommended [desktop tool](https://zeit.co/download) or via node with `npm install -g now`.
+
+2. Install `serve` by running `npm install --save serve`.
+
+3. Add this line to `scripts` in `package.json`:
+
+ ```
+ "now-start": "serve -s build/",
+ ```
+
+4. Run `now` from your project directory. You will see a **now.sh** URL in your output like this:
+
+ ```
+ > Ready! https://your-project-dirname-tpspyhtdtk.now.sh (copied to clipboard)
+ ```
+
+ Paste that URL into your browser when the build is complete, and you will see your deployed app.
+
+Details are available in [this article.](https://zeit.co/blog/now-static)
+
+### S3 and CloudFront
+
+See this [blog post](https://medium.com/@omgwtfmarc/deploying-create-react-app-to-s3-or-cloudfront-48dae4ce0af) on how to deploy your React app to Amazon Web Services [S3](https://aws.amazon.com/s3) and [CloudFront](https://aws.amazon.com/cloudfront/).
+
+### Surge
+
+Install the Surge CLI if you haven’t already by running `npm install -g surge`. Run the `surge` command and log in you or create a new account.
+
+When asked about the project path, make sure to specify the `build` folder, for example:
+
+```sh
+ project path: /path/to/project/build
+```
+
+Note that in order to support routers that use HTML5 `pushState` API, you may want to rename the `index.html` in your build folder to `200.html` before deploying to Surge. This [ensures that every URL falls back to that file](https://surge.sh/help/adding-a-200-page-for-client-side-routing).
+
+## Advanced Configuration
+
+You can adjust various development and production settings by setting environment variables in your shell or with [.env](#adding-development-environment-variables-in-env).
+
+Variable | Development | Production | Usage
+:--- | :---: | :---: | :---
+BROWSER | :white_check_mark: | :x: | By default, Create React App will open the default system browser, favoring Chrome on macOS. Specify a [browser](https://github.com/sindresorhus/opn#app) to override this behavior, or set it to `none` to disable it completely. If you need to customize the way the browser is launched, you can specify a node script instead. Any arguments passed to `npm start` will also be passed to this script, and the url where your app is served will be the last argument. Your script's file name must have the `.js` extension.
+HOST | :white_check_mark: | :x: | By default, the development web server binds to `localhost`. You may use this variable to specify a different host.
+PORT | :white_check_mark: | :x: | By default, the development web server will attempt to listen on port 3000 or prompt you to attempt the next available port. You may use this variable to specify a different port.
+HTTPS | :white_check_mark: | :x: | When set to `true`, Create React App will run the development server in `https` mode.
+PUBLIC_URL | :x: | :white_check_mark: | Create React App assumes your application is hosted at the serving web server's root or a subpath as specified in [`package.json` (`homepage`)](#building-for-relative-paths). Normally, Create React App ignores the hostname. You may use this variable to force assets to be referenced verbatim to the url you provide (hostname included). This may be particularly useful when using a CDN to host your application.
+CI | :large_orange_diamond: | :white_check_mark: | When set to `true`, Create React App treats warnings as failures in the build. It also makes the test runner non-watching. Most CIs set this flag by default.
+
+## Troubleshooting
+
+### `npm start` doesn’t detect changes
+
+When you save a file while `npm start` is running, the browser should refresh with the updated code.
+If this doesn’t happen, try one of the following workarounds:
+
+* If your project is in a Dropbox folder, try moving it out.
+* If the watcher doesn’t see a file called `index.js` and you’re referencing it by the folder name, you [need to restart the watcher](https://github.com/facebookincubator/create-react-app/issues/1164) due to a Webpack bug.
+* Some editors like Vim and IntelliJ have a “safe write” feature that currently breaks the watcher. You will need to disable it. Follow the instructions in [“Adjusting Your Text Editor”](https://webpack.js.org/guides/development/#adjusting-your-text-editor).
+* If your project path contains parentheses, try moving the project to a path without them. This is caused by a [Webpack watcher bug](https://github.com/webpack/watchpack/issues/42).
+* On Linux and macOS, you might need to [tweak system settings](https://webpack.github.io/docs/troubleshooting.html#not-enough-watchers) to allow more watchers.
+* If the project runs inside a virtual machine such as (a Vagrant provisioned) VirtualBox, create an `.env` file in your project directory if it doesn’t exist, and add `CHOKIDAR_USEPOLLING=true` to it. This ensures that the next time you run `npm start`, the watcher uses the polling mode, as necessary inside a VM.
+
+If none of these solutions help please leave a comment [in this thread](https://github.com/facebookincubator/create-react-app/issues/659).
+
+### `npm test` hangs on macOS Sierra
+
+If you run `npm test` and the console gets stuck after printing `react-scripts test --env=jsdom` to the console there might be a problem with your [Watchman](https://facebook.github.io/watchman/) installation as described in [facebookincubator/create-react-app#713](https://github.com/facebookincubator/create-react-app/issues/713).
+
+We recommend deleting `node_modules` in your project and running `npm install` (or `yarn` if you use it) first. If it doesn't help, you can try one of the numerous workarounds mentioned in these issues:
+
+* [facebook/jest#1767](https://github.com/facebook/jest/issues/1767)
+* [facebook/watchman#358](https://github.com/facebook/watchman/issues/358)
+* [ember-cli/ember-cli#6259](https://github.com/ember-cli/ember-cli/issues/6259)
+
+It is reported that installing Watchman 4.7.0 or newer fixes the issue. If you use [Homebrew](http://brew.sh/), you can run these commands to update it:
+
+```
+watchman shutdown-server
+brew update
+brew reinstall watchman
+```
+
+You can find [other installation methods](https://facebook.github.io/watchman/docs/install.html#build-install) on the Watchman documentation page.
+
+If this still doesn’t help, try running `launchctl unload -F ~/Library/LaunchAgents/com.github.facebook.watchman.plist`.
+
+There are also reports that *uninstalling* Watchman fixes the issue. So if nothing else helps, remove it from your system and try again.
+
+### `npm run build` silently fails
+
+It is reported that `npm run build` can fail on machines with no swap space, which is common in cloud environments. If [the symptoms are matching](https://github.com/facebookincubator/create-react-app/issues/1133#issuecomment-264612171), consider adding some swap space to the machine you’re building on, or build the project locally.
+
+### `npm run build` fails on Heroku
+
+This may be a problem with case sensitive filenames.
+Please refer to [this section](#resolving-heroku-deployment-errors).
+
+### Moment.js locales are missing
+
+If you use a [Moment.js](https://momentjs.com/), you might notice that only the English locale is available by default. This is because the locale files are large, and you probably only need a subset of [all the locales provided by Moment.js](https://momentjs.com/#multiple-locale-support).
+
+To add a specific Moment.js locale to your bundle, you need to import it explicitly.
+For example:
+
+```js
+import moment from 'moment';
+import 'moment/locale/fr';
+```
+
+If import multiple locales this way, you can later switch between them by calling `moment.locale()` with the locale name:
+
+```js
+import moment from 'moment';
+import 'moment/locale/fr';
+import 'moment/locale/es';
+
+// ...
+
+moment.locale('fr');
+```
+
+This will only work for locales that have been explicitly imported before.
+
+## Something Missing?
+
+If you have ideas for more “How To” recipes that should be on this page, [let us know](https://github.com/facebookincubator/create-react-app/issues) or [contribute some!](https://github.com/facebookincubator/create-react-app/edit/master/packages/react-scripts/template/README.md)
diff --git a/client/package.json b/client/package.json
new file mode 100644
index 00000000..e9c2e736
--- /dev/null
+++ b/client/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "client",
+ "version": "0.1.0",
+ "private": true,
+ "proxy": "http://djello-server.herokuapp.com",
+ "dependencies": {
+ "axios": "^0.16.1",
+ "bcrypt": "^1.0.2",
+ "bootstrap": "^4.0.0-alpha.6",
+ "form-serialize": "^0.7.1",
+ "isomorphic-fetch": "^2.2.1",
+ "moment": "^2.18.1",
+ "react": "^15.5.4",
+ "react-addons-css-transition-group": "^15.5.2",
+ "react-addons-transition-group": "^15.5.2",
+ "react-cookie": "^2.0.7",
+ "react-dom": "^15.5.4",
+ "react-redux": "^4.4.8",
+ "react-router": "^4.1.1",
+ "react-router-dom": "^4.1.1",
+ "react-transition-group": "^1.1.3",
+ "reactstrap": "^4.6.2",
+ "redux": "^3.6.0",
+ "redux-form": "^6.0.0-rc.3",
+ "redux-thunk": "^2.2.0"
+ },
+ "devDependencies": {
+ "node-sass-chokidar": "0.0.2",
+ "react-scripts": "1.0.6",
+ "sass-loader": "^6.0.5"
+ },
+ "scripts": {
+ "build-css": "node-sass-chokidar src/ -o src/",
+ "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
+ "start-js": "react-scripts start",
+ "start": "npm-run-all -p watch-css start-js",
+ "build": "npm run build-css && react-scripts build",
+ "test": "react-scripts test --env=jsdom",
+ "eject": "react-scripts eject"
+ }
+}
diff --git a/client/public/favicon.ico b/client/public/favicon.ico
new file mode 100644
index 00000000..5c125de5
Binary files /dev/null and b/client/public/favicon.ico differ
diff --git a/client/public/index.html b/client/public/index.html
new file mode 100644
index 00000000..7bee0271
--- /dev/null
+++ b/client/public/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+ React App
+
+
+
+ You need to enable JavaScript to run this app.
+
+
+
+
+
diff --git a/client/public/manifest.json b/client/public/manifest.json
new file mode 100644
index 00000000..be607e41
--- /dev/null
+++ b/client/public/manifest.json
@@ -0,0 +1,15 @@
+{
+ "short_name": "React App",
+ "name": "Create React App Sample",
+ "icons": [
+ {
+ "src": "favicon.ico",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "./index.html",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+}
diff --git a/client/src/App.test.js b/client/src/App.test.js
new file mode 100644
index 00000000..b84af98d
--- /dev/null
+++ b/client/src/App.test.js
@@ -0,0 +1,8 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import App from './App';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render( , div);
+});
diff --git a/client/src/_variables.scss b/client/src/_variables.scss
new file mode 100644
index 00000000..cd3e2354
--- /dev/null
+++ b/client/src/_variables.scss
@@ -0,0 +1,13 @@
+
+$brand-primary: #026AA7;
+$brand-success: #91C500;
+$brand-info: #1E97DF;
+$brand-danger: #9804E9;
+$navbar-default-brand-color: #0593E7;
+$dropdown-link-hover-color: #6FBCEA;
+$dropdown-link-active-bg: #6FBCEA;
+$link-color: #8633B3;
+$input-bg: #D1ECFC;
+$body-bg: #F4F5F1;
+$modal-md: 600px
+
diff --git a/client/src/actions/auth.js b/client/src/actions/auth.js
new file mode 100644
index 00000000..9d28e6b0
--- /dev/null
+++ b/client/src/actions/auth.js
@@ -0,0 +1,108 @@
+// There are three possible states for our login
+// process and we need actions for each of them
+export const LOGIN_REQUEST = "LOGIN_REQUEST";
+export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
+export const LOGIN_FAILURE = "LOGIN_FAILURE";
+
+//change fetch url for development or production
+
+function requestLogin(creds) {
+ return {
+ type: LOGIN_REQUEST,
+ isFetching: true,
+ isAuthenticated: false,
+ creds
+ };
+}
+
+function receiveLogin(user) {
+ return {
+ type: LOGIN_SUCCESS,
+ isFetching: false,
+ isAuthenticated: true,
+ id_token: user.id_token,
+ userEmail: user.userEmail,
+ userId: user.userId
+ };
+}
+
+function loginError(message) {
+ return {
+ type: LOGIN_FAILURE,
+ isFetching: false,
+ isAuthenticated: false,
+ message
+ };
+}
+// Calls the API to get a token and
+// dispatches actions along the way
+export function loginUser(creds) {
+ let config = {
+ method: "POST",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ body: `email=${creds.email}&password=${creds.password}`
+ };
+
+ return dispatch => {
+ // We dispatch requestLogin to kickoff the call to the API
+ dispatch(requestLogin(creds));
+
+ return fetch("https://djello-server.herokuapp.com/sessions/create", config)
+ .then(response => {
+ if (!response.ok) {
+ const error = new Error(response.statusText);
+ error.response = response;
+ console.log(error);
+ throw error;
+ }
+ return response.json();
+ })
+ .then(user => {
+ if (user) {
+ console.log(user);
+ // If login was successful, set the token in local storage
+ localStorage.setItem("token", user.token);
+ localStorage.setItem("userEmail", user.userEmail);
+ localStorage.setItem("userId", user.userId);
+ // Dispatch the success action
+ dispatch(receiveLogin(user));
+ }
+ })
+ .catch(error => dispatch(loginError(error.message)));
+ };
+}
+
+// Three possible states for our logout process as well.
+// Since we are using JWTs, we just need to remove the token
+// from localStorage. These actions are more useful if we
+// were calling the API to log the user out
+export const LOGOUT_REQUEST = "LOGOUT_REQUEST";
+export const LOGOUT_SUCCESS = "LOGOUT_SUCCESS";
+export const LOGOUT_FAILURE = "LOGOUT_FAILURE";
+
+function requestLogout() {
+ return {
+ type: LOGOUT_REQUEST,
+ isFetching: true,
+ isAuthenticated: true
+ };
+}
+
+function receiveLogout() {
+ return {
+ type: LOGOUT_SUCCESS,
+ isFetching: false,
+ isAuthenticated: false
+ };
+}
+
+// Logs the user out
+export function logoutUser() {
+ return dispatch => {
+ dispatch(requestLogout());
+ localStorage.removeItem("token");
+ localStorage.removeItem("userEmail");
+ localStorage.removeItem("userId");
+ dispatch(receiveLogout());
+ };
+}
diff --git a/client/src/actions/boards.js b/client/src/actions/boards.js
new file mode 100644
index 00000000..6b781906
--- /dev/null
+++ b/client/src/actions/boards.js
@@ -0,0 +1,283 @@
+import { getUsers } from "./users";
+export const GET_BOARDS_SUCCESS = "GET_BOARDS_SUCCESS";
+export const GET_REQUEST = "GET_REQUEST";
+export const GET_FAILURE = "GET_FAILURE";
+export const CHANGE_CURRENT_BOARD = "CHANGE_CURRENT_BOARD";
+export const CREATE_NEW_BOARD_SUCCESS = "CREATE_NEW_BOARD_SUCCESS";
+export const DELETE_BOARD_SUCCESS = "DELETE_BOARD_SUCCESS";
+//change fetch url for development or production
+export function getBoardsSuccess(data) {
+ return {
+ type: GET_BOARDS_SUCCESS,
+ data
+ };
+}
+
+export function getFailure(error) {
+ return {
+ type: GET_FAILURE,
+ error
+ };
+}
+export function getRequest() {
+ return {
+ type: GET_REQUEST
+ };
+}
+
+export function createNewBoardSuccess(data) {
+ return {
+ type: CREATE_NEW_BOARD_SUCCESS,
+ data
+ };
+}
+
+export function getBoards(userId, boardId) {
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/boards/${userId}?token=${localStorage.getItem("token")}`
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoardsSuccess({ json, boardId }));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+
+export function changeCurrentBoard(data) {
+ return {
+ type: CHANGE_CURRENT_BOARD,
+ data
+ };
+}
+
+export function createNewBoard(data) {
+ let config = {
+ method: "POST",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ body: `name=${data.name}&ownerId=${data.userId}`
+ };
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/boards/new?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoards(data.userId, json.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+
+export function deleteBoardSuccess(boardId) {
+ return {
+ type: DELETE_BOARD_SUCCESS,
+ data: boardId
+ };
+}
+
+export function deleteBoard(boardId) {
+ let config = { method: "DELETE" };
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/boards/delete/${boardId}?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(deleteBoardSuccess(json.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+
+export function createNewList(data) {
+ let config = {
+ method: "POST",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ body: `title=${data.title}&boardId=${+data.boardId}&description=${data.description}`
+ };
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/lists/new?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoards(localStorage.getItem("userId"), data.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+
+//data needs to have listId and boardId
+export function deleteList(data) {
+ let config = { method: "DELETE" };
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/lists/delete/${data.listId}?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoards(localStorage.getItem("userId"), data.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+
+//data must have listId, boardId and title, description
+export function updateList(data) {
+ let config = {
+ method: "PUT",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ body: `title=${data.title}&description=${data.description}`
+ };
+ return dispatch => {
+ console.log("DISP");
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/lists/update/${data.listId}?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoards(localStorage.getItem("userId"), data.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+
+export function createNewCard(data) {
+ let config = {
+ method: "POST",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ body: `title=${data.title}&description=${data.description}&listId=${data.listId}`
+ };
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/cards/new?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoards(localStorage.getItem("userId"), data.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+
+export function updateCard(data) {
+ console.log(data.name);
+ let config = {
+ method: "PUT",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ body: `title=${data.title}&description=${data.description}&name=${data.name}`
+ };
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/cards/update/${data.cardId}?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoards(localStorage.getItem("userId"), data.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+
+export function deleteCard(data) {
+ let config = { method: "DELETE" };
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/cards/delete/${data.cardId}?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoards(localStorage.getItem("userId"), data.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+export function addMember(data) {
+ let config = {
+ method: "POST",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ body: `email=${data.email}&boardId=${data.boardId}`
+ };
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/cards/member/add/${data.cardId}?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoards(localStorage.getItem("userId"), data.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+export function deleteMember(data) {
+ let config = {
+ method: "DELETE",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ body: `email=${data.email}`
+ };
+ return dispatch => {
+ dispatch(getRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/cards/member/delete/${data.cardId}?token=${localStorage.getItem("token")}`,
+ config
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getBoards(localStorage.getItem("userId"), data.boardId));
+ })
+ .catch(error => {
+ dispatch(getFailure(error.message + error.response));
+ });
+ };
+}
+
+function checkStatus(response) {
+ // If response not okay, throw an error
+ if (!response.ok) {
+ const error = new Error(response.statusText);
+ error.response = response;
+ throw error;
+ }
+ return response.json();
+}
diff --git a/client/src/actions/users.js b/client/src/actions/users.js
new file mode 100644
index 00000000..169ff678
--- /dev/null
+++ b/client/src/actions/users.js
@@ -0,0 +1,48 @@
+export const GET_USERS_REQUEST = "GET_USERS_REQUEST";
+export const GET_USERS_FAILURE = "GET_USERS_FAILURE";
+export const GET_USERS_SUCCESS = "GET_USERS_SUCCESS";
+//change fetch url for development or production
+export function getUsersSuccess(data) {
+ return {
+ type: GET_USERS_SUCCESS,
+ data
+ };
+}
+
+export function getUsersFailure(error) {
+ return {
+ type: GET_USERS_FAILURE,
+ error
+ };
+}
+
+export function getUsersRequest() {
+ return {
+ type: GET_USERS_REQUEST
+ };
+}
+
+export function getUsers() {
+ return dispatch => {
+ dispatch(getUsersRequest());
+ fetch(
+ `https://djello-server.herokuapp.com/users?token=${localStorage.getItem("token")}`
+ )
+ .then(checkStatus)
+ .then(json => {
+ dispatch(getUsersSuccess(json));
+ })
+ .catch(error => {
+ dispatch(getUsersFailure(error.message + error.response));
+ });
+ };
+}
+function checkStatus(response) {
+ // If response not okay, throw an error
+ if (!response.ok) {
+ const error = new Error(response.statusText);
+ error.response = response;
+ throw error;
+ }
+ return response.json();
+}
diff --git a/client/src/components/AddMemberDropdown.js b/client/src/components/AddMemberDropdown.js
new file mode 100644
index 00000000..61d12e06
--- /dev/null
+++ b/client/src/components/AddMemberDropdown.js
@@ -0,0 +1,48 @@
+import React from "react";
+import {
+ ButtonDropdown,
+ DropdownToggle,
+ DropdownMenu,
+ DropdownItem
+} from "reactstrap";
+
+export default class AddMemberDropdown extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ dropdownOpen: false
+ };
+ }
+
+ toggle() {
+ this.setState({
+ dropdownOpen: !this.state.dropdownOpen
+ });
+ }
+
+ render() {
+ const { users, members, onClick } = this.props;
+ return (
+
+
+ Add Member
+
+
+ {dropMembers({ users, members, onClick })}
+
+
+ );
+ }
+}
+
+const dropMembers = ({ users, members, onClick }) => {
+ return users.filter(user => !members.includes(user)).map(user => {
+ return (
+
+ {user}
+
+ );
+ });
+};
diff --git a/client/src/components/Board.js b/client/src/components/Board.js
new file mode 100644
index 00000000..4b0fdd4c
--- /dev/null
+++ b/client/src/components/Board.js
@@ -0,0 +1,54 @@
+import React from "react";
+import Lists from "./Lists";
+import CreateList from "./CreateList";
+
+const Board = ({
+ boards,
+ currentBoard,
+ deleteList,
+ updateList,
+ handleSubmitList,
+ handleSubmitCard,
+ updateCard,
+ deleteCard,
+ users,
+ addMember,
+ deleteMember
+}) => {
+ boards ? console.log("Boards", boards, currentBoard) : null;
+ return (
+
+ {!boards || !boards.length
+ ?
+ :
+
+
{currentBoard.name}
+
+
+ {currentBoard.Lists.length
+ ?
+ : }
+
+ }
+
+
+ );
+};
+
+const NoBoards = () => No Boards...
;
+const NoLists = () => No lists...
;
+
+export default Board;
diff --git a/client/src/components/BoardsManager.js b/client/src/components/BoardsManager.js
new file mode 100644
index 00000000..c4828721
--- /dev/null
+++ b/client/src/components/BoardsManager.js
@@ -0,0 +1,74 @@
+import React from "react";
+import {
+ ButtonDropdown,
+ DropdownToggle,
+ DropdownMenu,
+ DropdownItem
+} from "reactstrap";
+import CreateBoard from "./CreateBoard";
+import DeleteBoardButton from "./DeleteBoardButton";
+
+const dropBoards = (boards, changeCurrentBoard, currentBoard) => {
+ return boards.filter(board => board.id !== currentBoard.id).map(board => {
+ return (
+
+ {board.name}
+
+ );
+ });
+};
+
+class BoardsManager extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ dropdownOpen: false
+ };
+ }
+
+ toggle() {
+ this.setState({
+ dropdownOpen: !this.state.dropdownOpen
+ });
+ }
+ render() {
+ const {
+ boards,
+ currentBoard,
+ changeCurrentBoard,
+ deleteBoard,
+ handleSubmitBoard
+ } = this.props;
+ return (
+
+
+ {boards && boards.length
+ ?
+
+ {currentBoard.name}
+
+
+ {dropBoards(boards, changeCurrentBoard, currentBoard)}
+
+
+ : null}
+
+ {boards && boards.length
+ ?
+ : null}
+
+
+ );
+ }
+}
+
+export default BoardsManager;
diff --git a/client/src/components/CardModal.js b/client/src/components/CardModal.js
new file mode 100644
index 00000000..af8bce01
--- /dev/null
+++ b/client/src/components/CardModal.js
@@ -0,0 +1,312 @@
+import React from "react";
+import {
+ Modal,
+ ModalHeader,
+ ModalBody,
+ InputGroup,
+ Input,
+ InputGroupButton,
+ Row,
+ Col,
+ Button
+} from "reactstrap";
+import MarkCompletedButton from "./MarkCompletedButton";
+import AddMemberDropdown from "./AddMemberDropdown";
+import moment from "moment";
+
+const TitleEdit = ({ onChange, onSubmit, title, toggleTitle }) => {
+ return (
+
+
+
+
+ Cancel
+
+
+
+
+ );
+};
+
+const Description = ({ onClick, description }) => {
+ return (
+
+ {description.length
+ ? {description}
+ : Your description goes here... }
+
+ );
+};
+
+const DescriptionEdit = ({
+ onChange,
+ description,
+ onSubmit,
+ toggleDescription
+}) => {
+ return (
+
+
+
+
+ Cancel
+
+
+
+
+ );
+};
+
+class CardModal extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ modal: false,
+ editTitle: false,
+ title: props.card.title,
+ isSubmitted: false,
+ editDescription: false,
+ description: props.card.description,
+ editMembers: false
+ };
+
+ this.toggle = this.toggle.bind(this);
+ this.toggleTitle = this.toggleTitle.bind(this);
+ this.toggleDescription = this.toggleDescription.bind(this);
+ this.toggleMembers = this.toggleMembers.bind(this);
+ this.onChange = this.onChange.bind(this);
+ this.onSubmit = this.onSubmit.bind(this);
+ }
+
+ toggle() {
+ this.setState({
+ modal: !this.state.modal,
+ editTitle: false,
+ editDescription: false,
+ isSubmitted: false,
+ editMembers: false
+ });
+ }
+
+ toggleTitle() {
+ let title = this.state.isSubmitted
+ ? this.state.title
+ : this.props.card.title;
+ this.setState({
+ editTitle: !this.state.editTitle,
+ title,
+ isSubmitted: false,
+ description: this.props.card.description,
+ editDescription: false,
+ editMembers: false
+ });
+ }
+ toggleDescription() {
+ let description = this.state.isSubmitted
+ ? this.state.description
+ : this.props.card.description;
+ this.setState({
+ editDescription: !this.state.editDescription,
+ description,
+ title: this.props.card.title,
+ isSubmitted: false,
+ editTitle: false,
+ editMembers: false
+ });
+ }
+ toggleMembers() {
+ this.setState({
+ editMembers: !this.state.editMembers
+ });
+ }
+ onChange(e) {
+ this.setState({
+ [e.target.name]: e.target.value
+ });
+ }
+ onSubmit(e) {
+ let name = e.target.name;
+ if (e.key === "Enter") {
+ this.setState(
+ {
+ isSubmitted: true
+ },
+ () => {
+ this.props.updateCard({
+ title: this.state.title,
+ cardId: this.props.card.id,
+ boardId: this.props.boardId,
+ description: this.state.description,
+ name
+ });
+
+ name === "title" ? this.toggleTitle() : this.toggleDescription();
+ }
+ );
+ }
+ }
+
+ render() {
+ const {
+ card,
+ listTitle,
+ deleteCard,
+ boardId,
+ users,
+ addMember,
+ deleteMember
+ } = this.props;
+ const members = card.UsersCards.map(user => user.User.email);
+ const activities = card.Activities.map(act => {
+ return {
+ author: act.Author.email,
+ description: act.description,
+ date: act.createdAt
+ };
+ });
+ return (
+
+
+ {card.title}
+ {members.length
+ ?
+ Members:
+ {membersList({ members })}
+
+ : null}
+
+
+
+
+
+ {!this.state.editTitle
+ ?
+ {this.state.title}
+
+ : }
+
+ In list: {listTitle}
+
+
+
+
+
+
+
+
+ {!this.state.editDescription
+ ?
+ : }
+
+ Members
+
+
+ {!this.state.editMembers
+ ?
+ : }
+
+ Activity
+
+
+
+
+
+ );
+ }
+}
+
+const membersList = ({ members }) => {
+ return members.map((member, i) => {
+ return (
+
+ {member}
+
+ );
+ });
+};
+const Members = ({ members, deleteMember, cardId, boardId }) => {
+ const listOfMembers = members.map(member => {
+ return (
+
+ {member}
+
+
+ );
+ });
+ return {listOfMembers}
;
+};
+const Activities = ({ activities }) => {
+ if (activities.length > 6) {
+ activities = activities.slice(0, 6);
+ }
+ const listOfActivities = activities.map((act, i) => {
+ return (
+
+ {act.author}
+ {" "}
+ {act.description}
+ {" "}
+
+ {moment(act.date).format("MMM Do, YYYY")}
+
+
+ );
+ });
+ return {listOfActivities}
;
+};
+
+const DeleteMemberButton = ({ onClick }) => {
+ return remove ;
+};
+const AddMemberButton = ({ onClick }) => {
+ return Add Member ;
+};
+const CancelMemberButton = ({ onClick }) => {
+ return Cancel ;
+};
+
+export default CardModal;
diff --git a/client/src/components/Cards.js b/client/src/components/Cards.js
new file mode 100644
index 00000000..abfc273d
--- /dev/null
+++ b/client/src/components/Cards.js
@@ -0,0 +1,69 @@
+import React from "react";
+import CardModal from "./CardModal";
+
+const cardList = ({
+ cards,
+ listTitle,
+ updateCard,
+ boardId,
+ deleteCard,
+ users,
+ addMember,
+ deleteMember
+}) => {
+ return cards.map(card => {
+ return (
+
+
+
+ );
+ });
+};
+
+const Cards = ({
+ cards,
+ listTitle,
+ updateCard,
+ boardId,
+ deleteCard,
+ users,
+ addMember,
+ deleteMember
+}) => {
+ return (
+
+ {cards.length
+ ? cardList({
+ cards,
+ listTitle,
+ updateCard,
+ boardId,
+ deleteCard,
+ users,
+ addMember,
+ deleteMember
+ })
+ :
No cards...
}
+
+ );
+};
+
+export default Cards;
diff --git a/client/src/components/CreateBoard.js b/client/src/components/CreateBoard.js
new file mode 100644
index 00000000..d35c7051
--- /dev/null
+++ b/client/src/components/CreateBoard.js
@@ -0,0 +1,65 @@
+import React from "react";
+import {
+ Button,
+ Modal,
+ ModalHeader,
+ ModalBody,
+ Form,
+ FormGroup,
+ Label,
+ Input
+} from "reactstrap";
+
+class CreateBoard extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ modal: false
+ };
+
+ this.toggle = this.toggle.bind(this);
+ }
+
+ toggle() {
+ this.setState({
+ modal: !this.state.modal
+ });
+ }
+
+ render() {
+ const { handleSubmitBoard } = this.props;
+ return (
+
+
+ New Board
+
+
+ Create New Board
+
+
+
+
+
+
+ );
+ }
+}
+
+export default CreateBoard;
diff --git a/client/src/components/CreateCard.js b/client/src/components/CreateCard.js
new file mode 100644
index 00000000..a7988bc0
--- /dev/null
+++ b/client/src/components/CreateCard.js
@@ -0,0 +1,62 @@
+import React from "react";
+import {
+ Button,
+ Modal,
+ ModalHeader,
+ ModalBody,
+ Form,
+ FormGroup,
+ Label,
+ Input
+} from "reactstrap";
+
+class CreateCard extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ modal: false
+ };
+
+ this.toggle = this.toggle.bind(this);
+ }
+
+ toggle() {
+ this.setState({
+ modal: !this.state.modal
+ });
+ }
+
+ render() {
+ const { handleSubmitCard, boardId, listId } = this.props;
+ return (
+
+
+ Add New Card
+
+
+ Create New Card
+
+
+
+
+
+
+ );
+ }
+}
+
+export default CreateCard;
diff --git a/client/src/components/CreateList.js b/client/src/components/CreateList.js
new file mode 100644
index 00000000..7dc253ee
--- /dev/null
+++ b/client/src/components/CreateList.js
@@ -0,0 +1,69 @@
+import React from "react";
+import {
+ Button,
+ Modal,
+ ModalHeader,
+ ModalBody,
+ Form,
+ FormGroup,
+ Label,
+ Input
+} from "reactstrap";
+
+class CreateList extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ modal: false
+ };
+
+ this.toggle = this.toggle.bind(this);
+ }
+
+ toggle() {
+ this.setState({
+ modal: !this.state.modal
+ });
+ }
+
+ render() {
+ const { handleSubmitList, currentBoard } = this.props;
+ return (
+
+
+ Add New List
+
+
+ Create New List
+
+
+
+
+
+
+ );
+ }
+}
+
+export default CreateList;
diff --git a/client/src/components/DeleteBoardButton.js b/client/src/components/DeleteBoardButton.js
new file mode 100644
index 00000000..33394131
--- /dev/null
+++ b/client/src/components/DeleteBoardButton.js
@@ -0,0 +1,8 @@
+import React from "react";
+import { Button } from "reactstrap";
+
+const DeleteBoardButton = ({ onClick }) => {
+ return Delete Board ;
+};
+
+export default DeleteBoardButton;
diff --git a/client/src/components/DeleteListButton.js b/client/src/components/DeleteListButton.js
new file mode 100644
index 00000000..1dc00eb4
--- /dev/null
+++ b/client/src/components/DeleteListButton.js
@@ -0,0 +1,12 @@
+import React from "react";
+import { Button } from "reactstrap";
+
+const DeleteListButton = ({ onClick }) => {
+ return (
+
+ Delete List
+
+ );
+};
+
+export default DeleteListButton;
diff --git a/client/src/components/List.js b/client/src/components/List.js
new file mode 100644
index 00000000..aa5bba9f
--- /dev/null
+++ b/client/src/components/List.js
@@ -0,0 +1,209 @@
+import React from "react";
+import {
+ Card,
+ CardTitle,
+ CardSubtitle,
+ CardBlock,
+ InputGroup,
+ InputGroupButton,
+ Input
+} from "reactstrap";
+import Cards from "./Cards";
+import DeleteListButton from "./DeleteListButton";
+import CreateCard from "./CreateCard";
+const NameEdit = ({ toggleTitle, title, onChange, onSubmit }) => {
+ return (
+
+
+
+
+ Cancel
+
+
+
+
+ );
+};
+const DescriptionEdit = ({
+ onChange,
+ description,
+ onSubmit,
+ toggleDescription
+}) => {
+ return (
+
+
+
+
+ Cancel
+
+
+
+
+ );
+};
+const Description = ({ onClick, description }) => {
+ return (
+
+ {description.length
+ ? {description}
+ : Your description goes here... }
+
+ );
+};
+class List extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ editTitle: false,
+ editDescription: false,
+ title: props.title,
+ description: props.description,
+ isSubmitted: false
+ };
+ this.toggleTitle = this.toggleTitle.bind(this);
+ this.toggleDescription = this.toggleDescription.bind(this);
+ this.onChange = this.onChange.bind(this);
+ this.onSubmit = this.onSubmit.bind(this);
+ }
+ toggleTitle() {
+ let title = this.state.isSubmitted ? this.state.title : this.props.title;
+ this.setState({
+ editTitle: !this.state.editTitle,
+ title,
+ description: this.props.description,
+ isSubmitted: false,
+ editDescription: false
+ });
+ }
+
+ toggleDescription() {
+ let description = this.state.isSubmitted
+ ? this.state.description
+ : this.props.description;
+ this.setState({
+ editDescription: !this.state.editDescription,
+ description,
+ title: this.props.title,
+ isSubmitted: false,
+ editTitle: false
+ });
+ }
+ onChange(e) {
+ this.setState({
+ [e.target.name]: e.target.value
+ });
+ }
+ onSubmit(e) {
+ let name = e.target.name;
+ if (e.key === "Enter") {
+ this.setState(
+ {
+ isSubmitted: true
+ },
+ () => {
+ this.props.updateList({
+ title: this.state.title,
+ boardId: this.props.boardId,
+ listId: this.props.listId,
+ description: this.state.description
+ });
+ if (name === "title") {
+ this.toggleTitle();
+ } else {
+ this.toggleDescription();
+ }
+ }
+ );
+ }
+ }
+
+ render() {
+ const {
+ title,
+ description,
+ cards,
+ deleteList,
+ listId,
+ boardId,
+ handleSubmitCard,
+ updateCard,
+ deleteCard,
+ users,
+ addMember,
+ deleteMember
+ } = this.props;
+ return (
+
+
+
+
+ {!this.state.editTitle
+ ? {this.state.title}
+ : }
+ {" "}
+
+
+
+
+
+ {!this.state.editDescription
+ ?
+ : }
+
+
+
+
+
+
+
+ );
+ }
+}
+export default List;
diff --git a/client/src/components/Lists.js b/client/src/components/Lists.js
new file mode 100644
index 00000000..9071ce8c
--- /dev/null
+++ b/client/src/components/Lists.js
@@ -0,0 +1,74 @@
+import React from "react";
+import { CardDeck } from "reactstrap";
+
+import List from "./List";
+
+const listGroup = ({
+ lists,
+ deleteList,
+ currentBoard,
+ updateList,
+ handleSubmitCard,
+ updateCard,
+ deleteCard,
+ users,
+ addMember,
+ deleteMember
+}) =>
+ lists.map(list => {
+ return (
+
+ );
+ });
+
+class Lists extends React.Component {
+ render() {
+ const {
+ currentBoard,
+ deleteList,
+ updateList,
+ handleSubmitCard,
+ updateCard,
+ deleteCard,
+ users,
+ addMember,
+ deleteMember
+ } = this.props;
+ const lists = currentBoard.Lists;
+ return (
+
+
+ {lists.length
+ ? listGroup({
+ lists,
+ currentBoard,
+ deleteList,
+ updateList,
+ handleSubmitCard,
+ updateCard,
+ deleteCard,
+ users,
+ addMember,
+ deleteMember
+ })
+ : No Lists...
}
+
+ );
+ }
+}
+export default Lists;
diff --git a/client/src/components/Login.js b/client/src/components/Login.js
new file mode 100644
index 00000000..f683cf80
--- /dev/null
+++ b/client/src/components/Login.js
@@ -0,0 +1,57 @@
+import { Redirect } from "react-router-dom";
+import { withRouter } from "react-router";
+
+import React from "react";
+
+import { Container, Row, Col } from "reactstrap";
+
+class Login extends React.Component {
+ handleClick = event => {
+ const email = this.refs.email;
+ const password = this.refs.password;
+ const creds = {
+ email: email.value.trim(),
+ password: password.value.trim()
+ };
+ this.props.onLoginClick(creds);
+ };
+ render() {
+ const { errorMessage, isAuthenticated } = this.props;
+ if (isAuthenticated) {
+ return ;
+ }
+
+ return (
+
+
+
+
+
+
+ Login
+
+ {errorMessage && {errorMessage}
}
+
+
+
+ );
+ }
+}
+
+export default withRouter(Login);
diff --git a/client/src/components/Logout.js b/client/src/components/Logout.js
new file mode 100644
index 00000000..0397b23d
--- /dev/null
+++ b/client/src/components/Logout.js
@@ -0,0 +1,11 @@
+import React from "react";
+
+const Logout = ({ onLogoutClick }) => {
+ return (
+ onLogoutClick()} className="btn btn-primary">
+ Logout
+
+ );
+};
+
+export default Logout;
diff --git a/client/src/components/Main.js b/client/src/components/Main.js
new file mode 100644
index 00000000..ad44b7f1
--- /dev/null
+++ b/client/src/components/Main.js
@@ -0,0 +1,15 @@
+import React from "react";
+import { Container } from "reactstrap";
+import BoardContainer from "../containers/BoardContainer";
+
+const Main = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+export default Main;
diff --git a/client/src/components/MarkCompletedButton.js b/client/src/components/MarkCompletedButton.js
new file mode 100644
index 00000000..5aed4aae
--- /dev/null
+++ b/client/src/components/MarkCompletedButton.js
@@ -0,0 +1,12 @@
+import React from "react";
+import { Button } from "reactstrap";
+
+const MarkCompletedButton = ({ onClick }) => {
+ return (
+
+ Mark Completed
+
+ );
+};
+
+export default MarkCompletedButton;
diff --git a/client/src/components/Navbar.js b/client/src/components/Navbar.js
new file mode 100644
index 00000000..eb5977f4
--- /dev/null
+++ b/client/src/components/Navbar.js
@@ -0,0 +1,54 @@
+import React from "react";
+import {
+ Collapse,
+ Navbar,
+ NavbarToggler,
+ NavbarBrand,
+ Nav,
+ NavItem,
+ NavLink
+} from "reactstrap";
+import Logout from "./Logout";
+
+export default class Example extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ isOpen: false
+ };
+ }
+ toggle() {
+ this.setState({
+ isOpen: !this.state.isOpen
+ });
+ }
+ render() {
+ return (
+
+
+
+
+ Djello
+
+
+
+ {this.props.isAuthenticated
+ ?
+
+
+
+ : null}
+
+ {this.props.isAuthenticated
+ ? {localStorage.getItem("userEmail")}
+ : null}
+
+
+
+
+
+ );
+ }
+}
diff --git a/client/src/containers/App.js b/client/src/containers/App.js
new file mode 100644
index 00000000..3569a5eb
--- /dev/null
+++ b/client/src/containers/App.js
@@ -0,0 +1,88 @@
+import React, { Component } from "react";
+import { connect } from "react-redux";
+import { BrowserRouter as Router, Route, Redirect } from "react-router-dom";
+
+import Login from "../components/Login";
+import Main from "../components/Main";
+import Navbar from "../components/Navbar";
+import { loginUser, logoutUser } from "../actions/auth";
+
+class App extends Component {
+ render() {
+ const {
+ isAuthenticated,
+ errorMessage,
+ onLogoutClick,
+ onLoginClick,
+ user
+ } = this.props;
+ return (
+
+
+
+ );
+ }
+}
+const PrivateRoute = ({ component: Component, ...rest }) => (
+ {
+ return rest.isAuthenticated
+ ?
+ : ;
+ }}
+ />
+);
+
+// These props come from the application's
+// state when it is started
+function mapStateToProps(state) {
+ const { auth } = state;
+ const { isAuthenticated, errorMessage, user } = auth;
+
+ return {
+ isAuthenticated,
+ errorMessage,
+ user
+ };
+}
+
+function mapDispatchToProps(dispatch, ownProps) {
+ return {
+ onLoginClick: creds => {
+ dispatch(loginUser(creds));
+ },
+ onLogoutClick: () => {
+ dispatch(logoutUser());
+ }
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(App);
diff --git a/client/src/containers/BoardContainer.js b/client/src/containers/BoardContainer.js
new file mode 100644
index 00000000..f1ebf2d7
--- /dev/null
+++ b/client/src/containers/BoardContainer.js
@@ -0,0 +1,151 @@
+import React, { Component } from "react";
+import { connect } from "react-redux";
+import Board from "../components/Board";
+import {
+ getBoards,
+ deleteList,
+ updateList,
+ createNewList,
+ changeCurrentBoard,
+ deleteBoard,
+ createNewBoard,
+ createNewCard,
+ updateCard,
+ deleteCard,
+ addMember,
+ deleteMember
+} from "../actions/boards";
+import { getUsers } from "../actions/users";
+import BoardsManager from "../components/BoardsManager";
+import serialize from "form-serialize";
+
+class BoardContainer extends Component {
+ componentDidMount() {
+ this.props.getBoards(this.props.userId);
+ this.props.getUsers();
+ }
+
+ render() {
+ const {
+ boards,
+ users,
+ currentBoard,
+ changeCurrentBoard,
+ deleteBoard,
+ deleteList,
+ updateList,
+ handleSubmitList,
+ handleSubmitBoard,
+ handleSubmitCard,
+ updateCard,
+ deleteCard,
+ addMember,
+ deleteMember
+ } = this.props;
+ console.log(users);
+ return (
+
+
+
+
+ );
+ }
+}
+
+const mapStateToProps = state => {
+ return {
+ userId: state.auth.user.userId,
+ boards: state.boards.data.boards,
+ currentBoard: state.boards.currentBoard,
+ users: state.users.data
+ };
+};
+const mapDispatchToProps = dispatch => {
+ return {
+ getBoards: userId => {
+ dispatch(getBoards(userId));
+ },
+ changeCurrentBoard: boards => e => {
+ const board = boards.find(board => board.id === +e.target.value);
+ dispatch(changeCurrentBoard(board.id));
+ },
+ deleteBoard: boardId => e => {
+ dispatch(deleteBoard(boardId));
+ },
+ deleteList: ({ boardId, listId }) => e => {
+ dispatch(deleteList({ boardId, listId }));
+ },
+ deleteCard: ({ boardId, cardId }) => e => {
+ dispatch(deleteCard({ boardId, cardId }));
+ },
+ updateList: ({ boardId, listId, title, description }) => {
+ dispatch(updateList({ boardId, listId, title, description }));
+ },
+ updateCard: ({ boardId, cardId, title, description, name }) => {
+ dispatch(updateCard({ boardId, cardId, title, description, name }));
+ },
+ handleSubmitList: boardId => e => {
+ e.preventDefault();
+ const form = e.target;
+ const data = serialize(form, { hash: true });
+ let description = data.description ? data.description : "";
+ let title = data.title ? data.title : "No Title";
+ dispatch(
+ createNewList({
+ title,
+ boardId,
+ description
+ })
+ );
+ },
+ handleSubmitBoard: e => {
+ e.preventDefault();
+ const form = e.target;
+ const data = serialize(form, { hash: true });
+ dispatch(
+ createNewBoard({
+ name: data.name,
+ userId: localStorage.getItem("userId")
+ })
+ );
+ },
+ handleSubmitCard: ({ boardId, listId }) => e => {
+ e.preventDefault();
+ const form = e.target;
+ const data = serialize(form, { hash: true });
+ let title = data.title ? data.title : "No Title";
+ dispatch(
+ createNewCard({ title: data.title, boardId, description: "", listId })
+ );
+ },
+ getUsers: () => {
+ dispatch(getUsers());
+ },
+ addMember: ({ boardId, cardId }) => e => {
+ dispatch(addMember({ email: e.target.value, boardId, cardId }));
+ },
+ deleteMember: ({ boardId, cardId, email }) => e => {
+ dispatch(deleteMember({ boardId, cardId, email }));
+ }
+ };
+};
+
+export default connect(mapStateToProps, mapDispatchToProps)(BoardContainer);
diff --git a/client/src/index.css b/client/src/index.css
new file mode 100644
index 00000000..c06ffc80
--- /dev/null
+++ b/client/src/index.css
@@ -0,0 +1,5988 @@
+/*!
+ * Bootstrap v4.0.0-alpha.6 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors
+ * Copyright 2011-2017 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
+html {
+ font-family: sans-serif;
+ line-height: 1.15;
+ -ms-text-size-adjust: 100%;
+ -webkit-text-size-adjust: 100%; }
+
+body {
+ margin: 0; }
+
+article,
+aside,
+footer,
+header,
+nav,
+section {
+ display: block; }
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0; }
+
+figcaption,
+figure,
+main {
+ display: block; }
+
+figure {
+ margin: 1em 40px; }
+
+hr {
+ box-sizing: content-box;
+ height: 0;
+ overflow: visible; }
+
+pre {
+ font-family: monospace, monospace;
+ font-size: 1em; }
+
+a {
+ background-color: transparent;
+ -webkit-text-decoration-skip: objects; }
+
+a:active,
+a:hover {
+ outline-width: 0; }
+
+abbr[title] {
+ border-bottom: none;
+ text-decoration: underline;
+ text-decoration: underline dotted; }
+
+b,
+strong {
+ font-weight: inherit; }
+
+b,
+strong {
+ font-weight: bolder; }
+
+code,
+kbd,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em; }
+
+dfn {
+ font-style: italic; }
+
+mark {
+ background-color: #ff0;
+ color: #000; }
+
+small {
+ font-size: 80%; }
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline; }
+
+sub {
+ bottom: -0.25em; }
+
+sup {
+ top: -0.5em; }
+
+audio,
+video {
+ display: inline-block; }
+
+audio:not([controls]) {
+ display: none;
+ height: 0; }
+
+img {
+ border-style: none; }
+
+svg:not(:root) {
+ overflow: hidden; }
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: sans-serif;
+ font-size: 100%;
+ line-height: 1.15;
+ margin: 0; }
+
+button,
+input {
+ overflow: visible; }
+
+button,
+select {
+ text-transform: none; }
+
+button,
+html [type="button"],
+[type="reset"],
+[type="submit"] {
+ -webkit-appearance: button; }
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+ border-style: none;
+ padding: 0; }
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+ outline: 1px dotted ButtonText; }
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em; }
+
+legend {
+ box-sizing: border-box;
+ color: inherit;
+ display: table;
+ max-width: 100%;
+ padding: 0;
+ white-space: normal; }
+
+progress {
+ display: inline-block;
+ vertical-align: baseline; }
+
+textarea {
+ overflow: auto; }
+
+[type="checkbox"],
+[type="radio"] {
+ box-sizing: border-box;
+ padding: 0; }
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+ height: auto; }
+
+[type="search"] {
+ -webkit-appearance: textfield;
+ outline-offset: -2px; }
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none; }
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button;
+ font: inherit; }
+
+details,
+menu {
+ display: block; }
+
+summary {
+ display: list-item; }
+
+canvas {
+ display: inline-block; }
+
+template {
+ display: none; }
+
+[hidden] {
+ display: none; }
+
+@media print {
+ *,
+ *::before,
+ *::after,
+ p::first-letter,
+ div::first-letter,
+ blockquote::first-letter,
+ li::first-letter,
+ p::first-line,
+ div::first-line,
+ blockquote::first-line,
+ li::first-line {
+ text-shadow: none !important;
+ box-shadow: none !important; }
+ a,
+ a:visited {
+ text-decoration: underline; }
+ abbr[title]::after {
+ content: " (" attr(title) ")"; }
+ pre {
+ white-space: pre-wrap !important; }
+ pre,
+ blockquote {
+ border: 1px solid #999;
+ page-break-inside: avoid; }
+ thead {
+ display: table-header-group; }
+ tr,
+ img {
+ page-break-inside: avoid; }
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3; }
+ h2,
+ h3 {
+ page-break-after: avoid; }
+ .navbar {
+ display: none; }
+ .badge {
+ border: 1px solid #000; }
+ .table {
+ border-collapse: collapse !important; }
+ .table td,
+ .table th {
+ background-color: #fff !important; }
+ .table-bordered th,
+ .table-bordered td {
+ border: 1px solid #ddd !important; } }
+
+html {
+ box-sizing: border-box; }
+
+*,
+*::before,
+*::after {
+ box-sizing: inherit; }
+
+@-ms-viewport {
+ width: device-width; }
+
+html {
+ -ms-overflow-style: scrollbar;
+ -webkit-tap-highlight-color: transparent; }
+
+body {
+ font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+ font-size: 1rem;
+ font-weight: normal;
+ line-height: 1.5;
+ color: #292b2c;
+ background-color: #F4F5F1; }
+
+[tabindex="-1"]:focus {
+ outline: none !important; }
+
+h1, h2, h3, h4, h5, h6 {
+ margin-top: 0;
+ margin-bottom: .5rem; }
+
+p {
+ margin-top: 0;
+ margin-bottom: 1rem; }
+
+abbr[title],
+abbr[data-original-title] {
+ cursor: help; }
+
+address {
+ margin-bottom: 1rem;
+ font-style: normal;
+ line-height: inherit; }
+
+ol,
+ul,
+dl {
+ margin-top: 0;
+ margin-bottom: 1rem; }
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+ margin-bottom: 0; }
+
+dt {
+ font-weight: bold; }
+
+dd {
+ margin-bottom: .5rem;
+ margin-left: 0; }
+
+blockquote {
+ margin: 0 0 1rem; }
+
+a {
+ color: #8633B3;
+ text-decoration: none; }
+ a:focus, a:hover {
+ color: #592277;
+ text-decoration: underline; }
+
+a:not([href]):not([tabindex]) {
+ color: inherit;
+ text-decoration: none; }
+ a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
+ color: inherit;
+ text-decoration: none; }
+ a:not([href]):not([tabindex]):focus {
+ outline: 0; }
+
+pre {
+ margin-top: 0;
+ margin-bottom: 1rem;
+ overflow: auto; }
+
+figure {
+ margin: 0 0 1rem; }
+
+img {
+ vertical-align: middle; }
+
+[role="button"] {
+ cursor: pointer; }
+
+a,
+area,
+button,
+[role="button"],
+input,
+label,
+select,
+summary,
+textarea {
+ touch-action: manipulation; }
+
+table {
+ border-collapse: collapse;
+ background-color: transparent; }
+
+caption {
+ padding-top: 0.75rem;
+ padding-bottom: 0.75rem;
+ color: #636c72;
+ text-align: left;
+ caption-side: bottom; }
+
+th {
+ text-align: left; }
+
+label {
+ display: inline-block;
+ margin-bottom: .5rem; }
+
+button:focus {
+ outline: 1px dotted;
+ outline: 5px auto -webkit-focus-ring-color; }
+
+input,
+button,
+select,
+textarea {
+ line-height: inherit; }
+
+input[type="radio"]:disabled,
+input[type="checkbox"]:disabled {
+ cursor: not-allowed; }
+
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+ -webkit-appearance: listbox; }
+
+textarea {
+ resize: vertical; }
+
+fieldset {
+ min-width: 0;
+ padding: 0;
+ margin: 0;
+ border: 0; }
+
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: .5rem;
+ font-size: 1.5rem;
+ line-height: inherit; }
+
+input[type="search"] {
+ -webkit-appearance: none; }
+
+output {
+ display: inline-block; }
+
+[hidden] {
+ display: none !important; }
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+ margin-bottom: 0.5rem;
+ font-family: inherit;
+ font-weight: 500;
+ line-height: 1.1;
+ color: inherit; }
+
+h1, .h1 {
+ font-size: 2.5rem; }
+
+h2, .h2 {
+ font-size: 2rem; }
+
+h3, .h3 {
+ font-size: 1.75rem; }
+
+h4, .h4 {
+ font-size: 1.5rem; }
+
+h5, .h5 {
+ font-size: 1.25rem; }
+
+h6, .h6 {
+ font-size: 1rem; }
+
+.lead {
+ font-size: 1.25rem;
+ font-weight: 300; }
+
+.display-1 {
+ font-size: 6rem;
+ font-weight: 300;
+ line-height: 1.1; }
+
+.display-2 {
+ font-size: 5.5rem;
+ font-weight: 300;
+ line-height: 1.1; }
+
+.display-3 {
+ font-size: 4.5rem;
+ font-weight: 300;
+ line-height: 1.1; }
+
+.display-4 {
+ font-size: 3.5rem;
+ font-weight: 300;
+ line-height: 1.1; }
+
+hr {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ border: 0;
+ border-top: 1px solid rgba(0, 0, 0, 0.1); }
+
+small,
+.small {
+ font-size: 80%;
+ font-weight: normal; }
+
+mark,
+.mark {
+ padding: 0.2em;
+ background-color: #fcf8e3; }
+
+.list-unstyled {
+ padding-left: 0;
+ list-style: none; }
+
+.list-inline {
+ padding-left: 0;
+ list-style: none; }
+
+.list-inline-item {
+ display: inline-block; }
+ .list-inline-item:not(:last-child) {
+ margin-right: 5px; }
+
+.initialism {
+ font-size: 90%;
+ text-transform: uppercase; }
+
+.blockquote {
+ padding: 0.5rem 1rem;
+ margin-bottom: 1rem;
+ font-size: 1.25rem;
+ border-left: 0.25rem solid #eceeef; }
+
+.blockquote-footer {
+ display: block;
+ font-size: 80%;
+ color: #636c72; }
+ .blockquote-footer::before {
+ content: "\2014 \00A0"; }
+
+.blockquote-reverse {
+ padding-right: 1rem;
+ padding-left: 0;
+ text-align: right;
+ border-right: 0.25rem solid #eceeef;
+ border-left: 0; }
+
+.blockquote-reverse .blockquote-footer::before {
+ content: ""; }
+
+.blockquote-reverse .blockquote-footer::after {
+ content: "\00A0 \2014"; }
+
+.img-fluid {
+ max-width: 100%;
+ height: auto; }
+
+.img-thumbnail {
+ padding: 0.25rem;
+ background-color: #F4F5F1;
+ border: 1px solid #ddd;
+ border-radius: 0.25rem;
+ transition: all 0.2s ease-in-out;
+ max-width: 100%;
+ height: auto; }
+
+.figure {
+ display: inline-block; }
+
+.figure-img {
+ margin-bottom: 0.5rem;
+ line-height: 1; }
+
+.figure-caption {
+ font-size: 90%;
+ color: #636c72; }
+
+code,
+kbd,
+pre,
+samp {
+ font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
+
+code {
+ padding: 0.2rem 0.4rem;
+ font-size: 90%;
+ color: #bd4147;
+ background-color: #f7f7f9;
+ border-radius: 0.25rem; }
+ a > code {
+ padding: 0;
+ color: inherit;
+ background-color: inherit; }
+
+kbd {
+ padding: 0.2rem 0.4rem;
+ font-size: 90%;
+ color: #fff;
+ background-color: #292b2c;
+ border-radius: 0.2rem; }
+ kbd kbd {
+ padding: 0;
+ font-size: 100%;
+ font-weight: bold; }
+
+pre {
+ display: block;
+ margin-top: 0;
+ margin-bottom: 1rem;
+ font-size: 90%;
+ color: #292b2c; }
+ pre code {
+ padding: 0;
+ font-size: inherit;
+ color: inherit;
+ background-color: transparent;
+ border-radius: 0; }
+
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll; }
+
+.container {
+ position: relative;
+ margin-left: auto;
+ margin-right: auto;
+ padding-right: 15px;
+ padding-left: 15px; }
+ @media (min-width: 576px) {
+ .container {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 768px) {
+ .container {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 992px) {
+ .container {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 1200px) {
+ .container {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 576px) {
+ .container {
+ width: 540px;
+ max-width: 100%; } }
+ @media (min-width: 768px) {
+ .container {
+ width: 720px;
+ max-width: 100%; } }
+ @media (min-width: 992px) {
+ .container {
+ width: 960px;
+ max-width: 100%; } }
+ @media (min-width: 1200px) {
+ .container {
+ width: 1140px;
+ max-width: 100%; } }
+
+.container-fluid {
+ position: relative;
+ margin-left: auto;
+ margin-right: auto;
+ padding-right: 15px;
+ padding-left: 15px; }
+ @media (min-width: 576px) {
+ .container-fluid {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 768px) {
+ .container-fluid {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 992px) {
+ .container-fluid {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 1200px) {
+ .container-fluid {
+ padding-right: 15px;
+ padding-left: 15px; } }
+
+.row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -15px;
+ margin-left: -15px; }
+ @media (min-width: 576px) {
+ .row {
+ margin-right: -15px;
+ margin-left: -15px; } }
+ @media (min-width: 768px) {
+ .row {
+ margin-right: -15px;
+ margin-left: -15px; } }
+ @media (min-width: 992px) {
+ .row {
+ margin-right: -15px;
+ margin-left: -15px; } }
+ @media (min-width: 1200px) {
+ .row {
+ margin-right: -15px;
+ margin-left: -15px; } }
+
+.no-gutters {
+ margin-right: 0;
+ margin-left: 0; }
+ .no-gutters > .col,
+ .no-gutters > [class*="col-"] {
+ padding-right: 0;
+ padding-left: 0; }
+
+.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl {
+ position: relative;
+ width: 100%;
+ min-height: 1px;
+ padding-right: 15px;
+ padding-left: 15px; }
+ @media (min-width: 576px) {
+ .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 768px) {
+ .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 992px) {
+ .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl {
+ padding-right: 15px;
+ padding-left: 15px; } }
+ @media (min-width: 1200px) {
+ .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl {
+ padding-right: 15px;
+ padding-left: 15px; } }
+
+.col {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%; }
+
+.col-auto {
+ flex: 0 0 auto;
+ width: auto; }
+
+.col-1 {
+ flex: 0 0 8.33333%;
+ max-width: 8.33333%; }
+
+.col-2 {
+ flex: 0 0 16.66667%;
+ max-width: 16.66667%; }
+
+.col-3 {
+ flex: 0 0 25%;
+ max-width: 25%; }
+
+.col-4 {
+ flex: 0 0 33.33333%;
+ max-width: 33.33333%; }
+
+.col-5 {
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%; }
+
+.col-6 {
+ flex: 0 0 50%;
+ max-width: 50%; }
+
+.col-7 {
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%; }
+
+.col-8 {
+ flex: 0 0 66.66667%;
+ max-width: 66.66667%; }
+
+.col-9 {
+ flex: 0 0 75%;
+ max-width: 75%; }
+
+.col-10 {
+ flex: 0 0 83.33333%;
+ max-width: 83.33333%; }
+
+.col-11 {
+ flex: 0 0 91.66667%;
+ max-width: 91.66667%; }
+
+.col-12 {
+ flex: 0 0 100%;
+ max-width: 100%; }
+
+.pull-0 {
+ right: auto; }
+
+.pull-1 {
+ right: 8.33333%; }
+
+.pull-2 {
+ right: 16.66667%; }
+
+.pull-3 {
+ right: 25%; }
+
+.pull-4 {
+ right: 33.33333%; }
+
+.pull-5 {
+ right: 41.66667%; }
+
+.pull-6 {
+ right: 50%; }
+
+.pull-7 {
+ right: 58.33333%; }
+
+.pull-8 {
+ right: 66.66667%; }
+
+.pull-9 {
+ right: 75%; }
+
+.pull-10 {
+ right: 83.33333%; }
+
+.pull-11 {
+ right: 91.66667%; }
+
+.pull-12 {
+ right: 100%; }
+
+.push-0 {
+ left: auto; }
+
+.push-1 {
+ left: 8.33333%; }
+
+.push-2 {
+ left: 16.66667%; }
+
+.push-3 {
+ left: 25%; }
+
+.push-4 {
+ left: 33.33333%; }
+
+.push-5 {
+ left: 41.66667%; }
+
+.push-6 {
+ left: 50%; }
+
+.push-7 {
+ left: 58.33333%; }
+
+.push-8 {
+ left: 66.66667%; }
+
+.push-9 {
+ left: 75%; }
+
+.push-10 {
+ left: 83.33333%; }
+
+.push-11 {
+ left: 91.66667%; }
+
+.push-12 {
+ left: 100%; }
+
+.offset-1 {
+ margin-left: 8.33333%; }
+
+.offset-2 {
+ margin-left: 16.66667%; }
+
+.offset-3 {
+ margin-left: 25%; }
+
+.offset-4 {
+ margin-left: 33.33333%; }
+
+.offset-5 {
+ margin-left: 41.66667%; }
+
+.offset-6 {
+ margin-left: 50%; }
+
+.offset-7 {
+ margin-left: 58.33333%; }
+
+.offset-8 {
+ margin-left: 66.66667%; }
+
+.offset-9 {
+ margin-left: 75%; }
+
+.offset-10 {
+ margin-left: 83.33333%; }
+
+.offset-11 {
+ margin-left: 91.66667%; }
+
+@media (min-width: 576px) {
+ .col-sm {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%; }
+ .col-sm-auto {
+ flex: 0 0 auto;
+ width: auto; }
+ .col-sm-1 {
+ flex: 0 0 8.33333%;
+ max-width: 8.33333%; }
+ .col-sm-2 {
+ flex: 0 0 16.66667%;
+ max-width: 16.66667%; }
+ .col-sm-3 {
+ flex: 0 0 25%;
+ max-width: 25%; }
+ .col-sm-4 {
+ flex: 0 0 33.33333%;
+ max-width: 33.33333%; }
+ .col-sm-5 {
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%; }
+ .col-sm-6 {
+ flex: 0 0 50%;
+ max-width: 50%; }
+ .col-sm-7 {
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%; }
+ .col-sm-8 {
+ flex: 0 0 66.66667%;
+ max-width: 66.66667%; }
+ .col-sm-9 {
+ flex: 0 0 75%;
+ max-width: 75%; }
+ .col-sm-10 {
+ flex: 0 0 83.33333%;
+ max-width: 83.33333%; }
+ .col-sm-11 {
+ flex: 0 0 91.66667%;
+ max-width: 91.66667%; }
+ .col-sm-12 {
+ flex: 0 0 100%;
+ max-width: 100%; }
+ .pull-sm-0 {
+ right: auto; }
+ .pull-sm-1 {
+ right: 8.33333%; }
+ .pull-sm-2 {
+ right: 16.66667%; }
+ .pull-sm-3 {
+ right: 25%; }
+ .pull-sm-4 {
+ right: 33.33333%; }
+ .pull-sm-5 {
+ right: 41.66667%; }
+ .pull-sm-6 {
+ right: 50%; }
+ .pull-sm-7 {
+ right: 58.33333%; }
+ .pull-sm-8 {
+ right: 66.66667%; }
+ .pull-sm-9 {
+ right: 75%; }
+ .pull-sm-10 {
+ right: 83.33333%; }
+ .pull-sm-11 {
+ right: 91.66667%; }
+ .pull-sm-12 {
+ right: 100%; }
+ .push-sm-0 {
+ left: auto; }
+ .push-sm-1 {
+ left: 8.33333%; }
+ .push-sm-2 {
+ left: 16.66667%; }
+ .push-sm-3 {
+ left: 25%; }
+ .push-sm-4 {
+ left: 33.33333%; }
+ .push-sm-5 {
+ left: 41.66667%; }
+ .push-sm-6 {
+ left: 50%; }
+ .push-sm-7 {
+ left: 58.33333%; }
+ .push-sm-8 {
+ left: 66.66667%; }
+ .push-sm-9 {
+ left: 75%; }
+ .push-sm-10 {
+ left: 83.33333%; }
+ .push-sm-11 {
+ left: 91.66667%; }
+ .push-sm-12 {
+ left: 100%; }
+ .offset-sm-0 {
+ margin-left: 0%; }
+ .offset-sm-1 {
+ margin-left: 8.33333%; }
+ .offset-sm-2 {
+ margin-left: 16.66667%; }
+ .offset-sm-3 {
+ margin-left: 25%; }
+ .offset-sm-4 {
+ margin-left: 33.33333%; }
+ .offset-sm-5 {
+ margin-left: 41.66667%; }
+ .offset-sm-6 {
+ margin-left: 50%; }
+ .offset-sm-7 {
+ margin-left: 58.33333%; }
+ .offset-sm-8 {
+ margin-left: 66.66667%; }
+ .offset-sm-9 {
+ margin-left: 75%; }
+ .offset-sm-10 {
+ margin-left: 83.33333%; }
+ .offset-sm-11 {
+ margin-left: 91.66667%; } }
+
+@media (min-width: 768px) {
+ .col-md {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%; }
+ .col-md-auto {
+ flex: 0 0 auto;
+ width: auto; }
+ .col-md-1 {
+ flex: 0 0 8.33333%;
+ max-width: 8.33333%; }
+ .col-md-2 {
+ flex: 0 0 16.66667%;
+ max-width: 16.66667%; }
+ .col-md-3 {
+ flex: 0 0 25%;
+ max-width: 25%; }
+ .col-md-4 {
+ flex: 0 0 33.33333%;
+ max-width: 33.33333%; }
+ .col-md-5 {
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%; }
+ .col-md-6 {
+ flex: 0 0 50%;
+ max-width: 50%; }
+ .col-md-7 {
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%; }
+ .col-md-8 {
+ flex: 0 0 66.66667%;
+ max-width: 66.66667%; }
+ .col-md-9 {
+ flex: 0 0 75%;
+ max-width: 75%; }
+ .col-md-10 {
+ flex: 0 0 83.33333%;
+ max-width: 83.33333%; }
+ .col-md-11 {
+ flex: 0 0 91.66667%;
+ max-width: 91.66667%; }
+ .col-md-12 {
+ flex: 0 0 100%;
+ max-width: 100%; }
+ .pull-md-0 {
+ right: auto; }
+ .pull-md-1 {
+ right: 8.33333%; }
+ .pull-md-2 {
+ right: 16.66667%; }
+ .pull-md-3 {
+ right: 25%; }
+ .pull-md-4 {
+ right: 33.33333%; }
+ .pull-md-5 {
+ right: 41.66667%; }
+ .pull-md-6 {
+ right: 50%; }
+ .pull-md-7 {
+ right: 58.33333%; }
+ .pull-md-8 {
+ right: 66.66667%; }
+ .pull-md-9 {
+ right: 75%; }
+ .pull-md-10 {
+ right: 83.33333%; }
+ .pull-md-11 {
+ right: 91.66667%; }
+ .pull-md-12 {
+ right: 100%; }
+ .push-md-0 {
+ left: auto; }
+ .push-md-1 {
+ left: 8.33333%; }
+ .push-md-2 {
+ left: 16.66667%; }
+ .push-md-3 {
+ left: 25%; }
+ .push-md-4 {
+ left: 33.33333%; }
+ .push-md-5 {
+ left: 41.66667%; }
+ .push-md-6 {
+ left: 50%; }
+ .push-md-7 {
+ left: 58.33333%; }
+ .push-md-8 {
+ left: 66.66667%; }
+ .push-md-9 {
+ left: 75%; }
+ .push-md-10 {
+ left: 83.33333%; }
+ .push-md-11 {
+ left: 91.66667%; }
+ .push-md-12 {
+ left: 100%; }
+ .offset-md-0 {
+ margin-left: 0%; }
+ .offset-md-1 {
+ margin-left: 8.33333%; }
+ .offset-md-2 {
+ margin-left: 16.66667%; }
+ .offset-md-3 {
+ margin-left: 25%; }
+ .offset-md-4 {
+ margin-left: 33.33333%; }
+ .offset-md-5 {
+ margin-left: 41.66667%; }
+ .offset-md-6 {
+ margin-left: 50%; }
+ .offset-md-7 {
+ margin-left: 58.33333%; }
+ .offset-md-8 {
+ margin-left: 66.66667%; }
+ .offset-md-9 {
+ margin-left: 75%; }
+ .offset-md-10 {
+ margin-left: 83.33333%; }
+ .offset-md-11 {
+ margin-left: 91.66667%; } }
+
+@media (min-width: 992px) {
+ .col-lg {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%; }
+ .col-lg-auto {
+ flex: 0 0 auto;
+ width: auto; }
+ .col-lg-1 {
+ flex: 0 0 8.33333%;
+ max-width: 8.33333%; }
+ .col-lg-2 {
+ flex: 0 0 16.66667%;
+ max-width: 16.66667%; }
+ .col-lg-3 {
+ flex: 0 0 25%;
+ max-width: 25%; }
+ .col-lg-4 {
+ flex: 0 0 33.33333%;
+ max-width: 33.33333%; }
+ .col-lg-5 {
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%; }
+ .col-lg-6 {
+ flex: 0 0 50%;
+ max-width: 50%; }
+ .col-lg-7 {
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%; }
+ .col-lg-8 {
+ flex: 0 0 66.66667%;
+ max-width: 66.66667%; }
+ .col-lg-9 {
+ flex: 0 0 75%;
+ max-width: 75%; }
+ .col-lg-10 {
+ flex: 0 0 83.33333%;
+ max-width: 83.33333%; }
+ .col-lg-11 {
+ flex: 0 0 91.66667%;
+ max-width: 91.66667%; }
+ .col-lg-12 {
+ flex: 0 0 100%;
+ max-width: 100%; }
+ .pull-lg-0 {
+ right: auto; }
+ .pull-lg-1 {
+ right: 8.33333%; }
+ .pull-lg-2 {
+ right: 16.66667%; }
+ .pull-lg-3 {
+ right: 25%; }
+ .pull-lg-4 {
+ right: 33.33333%; }
+ .pull-lg-5 {
+ right: 41.66667%; }
+ .pull-lg-6 {
+ right: 50%; }
+ .pull-lg-7 {
+ right: 58.33333%; }
+ .pull-lg-8 {
+ right: 66.66667%; }
+ .pull-lg-9 {
+ right: 75%; }
+ .pull-lg-10 {
+ right: 83.33333%; }
+ .pull-lg-11 {
+ right: 91.66667%; }
+ .pull-lg-12 {
+ right: 100%; }
+ .push-lg-0 {
+ left: auto; }
+ .push-lg-1 {
+ left: 8.33333%; }
+ .push-lg-2 {
+ left: 16.66667%; }
+ .push-lg-3 {
+ left: 25%; }
+ .push-lg-4 {
+ left: 33.33333%; }
+ .push-lg-5 {
+ left: 41.66667%; }
+ .push-lg-6 {
+ left: 50%; }
+ .push-lg-7 {
+ left: 58.33333%; }
+ .push-lg-8 {
+ left: 66.66667%; }
+ .push-lg-9 {
+ left: 75%; }
+ .push-lg-10 {
+ left: 83.33333%; }
+ .push-lg-11 {
+ left: 91.66667%; }
+ .push-lg-12 {
+ left: 100%; }
+ .offset-lg-0 {
+ margin-left: 0%; }
+ .offset-lg-1 {
+ margin-left: 8.33333%; }
+ .offset-lg-2 {
+ margin-left: 16.66667%; }
+ .offset-lg-3 {
+ margin-left: 25%; }
+ .offset-lg-4 {
+ margin-left: 33.33333%; }
+ .offset-lg-5 {
+ margin-left: 41.66667%; }
+ .offset-lg-6 {
+ margin-left: 50%; }
+ .offset-lg-7 {
+ margin-left: 58.33333%; }
+ .offset-lg-8 {
+ margin-left: 66.66667%; }
+ .offset-lg-9 {
+ margin-left: 75%; }
+ .offset-lg-10 {
+ margin-left: 83.33333%; }
+ .offset-lg-11 {
+ margin-left: 91.66667%; } }
+
+@media (min-width: 1200px) {
+ .col-xl {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%; }
+ .col-xl-auto {
+ flex: 0 0 auto;
+ width: auto; }
+ .col-xl-1 {
+ flex: 0 0 8.33333%;
+ max-width: 8.33333%; }
+ .col-xl-2 {
+ flex: 0 0 16.66667%;
+ max-width: 16.66667%; }
+ .col-xl-3 {
+ flex: 0 0 25%;
+ max-width: 25%; }
+ .col-xl-4 {
+ flex: 0 0 33.33333%;
+ max-width: 33.33333%; }
+ .col-xl-5 {
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%; }
+ .col-xl-6 {
+ flex: 0 0 50%;
+ max-width: 50%; }
+ .col-xl-7 {
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%; }
+ .col-xl-8 {
+ flex: 0 0 66.66667%;
+ max-width: 66.66667%; }
+ .col-xl-9 {
+ flex: 0 0 75%;
+ max-width: 75%; }
+ .col-xl-10 {
+ flex: 0 0 83.33333%;
+ max-width: 83.33333%; }
+ .col-xl-11 {
+ flex: 0 0 91.66667%;
+ max-width: 91.66667%; }
+ .col-xl-12 {
+ flex: 0 0 100%;
+ max-width: 100%; }
+ .pull-xl-0 {
+ right: auto; }
+ .pull-xl-1 {
+ right: 8.33333%; }
+ .pull-xl-2 {
+ right: 16.66667%; }
+ .pull-xl-3 {
+ right: 25%; }
+ .pull-xl-4 {
+ right: 33.33333%; }
+ .pull-xl-5 {
+ right: 41.66667%; }
+ .pull-xl-6 {
+ right: 50%; }
+ .pull-xl-7 {
+ right: 58.33333%; }
+ .pull-xl-8 {
+ right: 66.66667%; }
+ .pull-xl-9 {
+ right: 75%; }
+ .pull-xl-10 {
+ right: 83.33333%; }
+ .pull-xl-11 {
+ right: 91.66667%; }
+ .pull-xl-12 {
+ right: 100%; }
+ .push-xl-0 {
+ left: auto; }
+ .push-xl-1 {
+ left: 8.33333%; }
+ .push-xl-2 {
+ left: 16.66667%; }
+ .push-xl-3 {
+ left: 25%; }
+ .push-xl-4 {
+ left: 33.33333%; }
+ .push-xl-5 {
+ left: 41.66667%; }
+ .push-xl-6 {
+ left: 50%; }
+ .push-xl-7 {
+ left: 58.33333%; }
+ .push-xl-8 {
+ left: 66.66667%; }
+ .push-xl-9 {
+ left: 75%; }
+ .push-xl-10 {
+ left: 83.33333%; }
+ .push-xl-11 {
+ left: 91.66667%; }
+ .push-xl-12 {
+ left: 100%; }
+ .offset-xl-0 {
+ margin-left: 0%; }
+ .offset-xl-1 {
+ margin-left: 8.33333%; }
+ .offset-xl-2 {
+ margin-left: 16.66667%; }
+ .offset-xl-3 {
+ margin-left: 25%; }
+ .offset-xl-4 {
+ margin-left: 33.33333%; }
+ .offset-xl-5 {
+ margin-left: 41.66667%; }
+ .offset-xl-6 {
+ margin-left: 50%; }
+ .offset-xl-7 {
+ margin-left: 58.33333%; }
+ .offset-xl-8 {
+ margin-left: 66.66667%; }
+ .offset-xl-9 {
+ margin-left: 75%; }
+ .offset-xl-10 {
+ margin-left: 83.33333%; }
+ .offset-xl-11 {
+ margin-left: 91.66667%; } }
+
+.table {
+ width: 100%;
+ max-width: 100%;
+ margin-bottom: 1rem; }
+ .table th,
+ .table td {
+ padding: 0.75rem;
+ vertical-align: top;
+ border-top: 1px solid #eceeef; }
+ .table thead th {
+ vertical-align: bottom;
+ border-bottom: 2px solid #eceeef; }
+ .table tbody + tbody {
+ border-top: 2px solid #eceeef; }
+ .table .table {
+ background-color: #F4F5F1; }
+
+.table-sm th,
+.table-sm td {
+ padding: 0.3rem; }
+
+.table-bordered {
+ border: 1px solid #eceeef; }
+ .table-bordered th,
+ .table-bordered td {
+ border: 1px solid #eceeef; }
+ .table-bordered thead th,
+ .table-bordered thead td {
+ border-bottom-width: 2px; }
+
+.table-striped tbody tr:nth-of-type(odd) {
+ background-color: rgba(0, 0, 0, 0.05); }
+
+.table-hover tbody tr:hover {
+ background-color: rgba(0, 0, 0, 0.075); }
+
+.table-active,
+.table-active > th,
+.table-active > td {
+ background-color: rgba(0, 0, 0, 0.075); }
+
+.table-hover .table-active:hover {
+ background-color: rgba(0, 0, 0, 0.075); }
+ .table-hover .table-active:hover > td,
+ .table-hover .table-active:hover > th {
+ background-color: rgba(0, 0, 0, 0.075); }
+
+.table-success,
+.table-success > th,
+.table-success > td {
+ background-color: #dff0d8; }
+
+.table-hover .table-success:hover {
+ background-color: #d0e9c6; }
+ .table-hover .table-success:hover > td,
+ .table-hover .table-success:hover > th {
+ background-color: #d0e9c6; }
+
+.table-info,
+.table-info > th,
+.table-info > td {
+ background-color: #d9edf7; }
+
+.table-hover .table-info:hover {
+ background-color: #c4e3f3; }
+ .table-hover .table-info:hover > td,
+ .table-hover .table-info:hover > th {
+ background-color: #c4e3f3; }
+
+.table-warning,
+.table-warning > th,
+.table-warning > td {
+ background-color: #fcf8e3; }
+
+.table-hover .table-warning:hover {
+ background-color: #faf2cc; }
+ .table-hover .table-warning:hover > td,
+ .table-hover .table-warning:hover > th {
+ background-color: #faf2cc; }
+
+.table-danger,
+.table-danger > th,
+.table-danger > td {
+ background-color: #f2dede; }
+
+.table-hover .table-danger:hover {
+ background-color: #ebcccc; }
+ .table-hover .table-danger:hover > td,
+ .table-hover .table-danger:hover > th {
+ background-color: #ebcccc; }
+
+.thead-inverse th {
+ color: #F4F5F1;
+ background-color: #292b2c; }
+
+.thead-default th {
+ color: #464a4c;
+ background-color: #eceeef; }
+
+.table-inverse {
+ color: #F4F5F1;
+ background-color: #292b2c; }
+ .table-inverse th,
+ .table-inverse td,
+ .table-inverse thead th {
+ border-color: #F4F5F1; }
+ .table-inverse.table-bordered {
+ border: 0; }
+
+.table-responsive {
+ display: block;
+ width: 100%;
+ overflow-x: auto;
+ -ms-overflow-style: -ms-autohiding-scrollbar; }
+ .table-responsive.table-bordered {
+ border: 0; }
+
+.form-control {
+ display: block;
+ width: 100%;
+ padding: 0.5rem 0.75rem;
+ font-size: 1rem;
+ line-height: 1.25;
+ color: #464a4c;
+ background-color: #D1ECFC;
+ background-image: none;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem;
+ transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; }
+ .form-control::-ms-expand {
+ background-color: transparent;
+ border: 0; }
+ .form-control:focus {
+ color: #464a4c;
+ background-color: #D1ECFC;
+ border-color: #2caffc;
+ outline: none; }
+ .form-control::placeholder {
+ color: #636c72;
+ opacity: 1; }
+ .form-control:disabled, .form-control[readonly] {
+ background-color: #eceeef;
+ opacity: 1; }
+ .form-control:disabled {
+ cursor: not-allowed; }
+
+select.form-control:not([size]):not([multiple]) {
+ height: calc(2.25rem + 2px); }
+
+select.form-control:focus::-ms-value {
+ color: #464a4c;
+ background-color: #D1ECFC; }
+
+.form-control-file,
+.form-control-range {
+ display: block; }
+
+.col-form-label {
+ padding-top: calc(0.5rem - 1px * 2);
+ padding-bottom: calc(0.5rem - 1px * 2);
+ margin-bottom: 0; }
+
+.col-form-label-lg {
+ padding-top: calc(0.75rem - 1px * 2);
+ padding-bottom: calc(0.75rem - 1px * 2);
+ font-size: 1.25rem; }
+
+.col-form-label-sm {
+ padding-top: calc(0.25rem - 1px * 2);
+ padding-bottom: calc(0.25rem - 1px * 2);
+ font-size: 0.875rem; }
+
+.col-form-legend {
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ margin-bottom: 0;
+ font-size: 1rem; }
+
+.form-control-static {
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ margin-bottom: 0;
+ line-height: 1.25;
+ border: solid transparent;
+ border-width: 1px 0; }
+ .form-control-static.form-control-sm, .input-group-sm > .form-control-static.form-control,
+ .input-group-sm > .form-control-static.input-group-addon,
+ .input-group-sm > .input-group-btn > .form-control-static.btn, .form-control-static.form-control-lg, .input-group-lg > .form-control-static.form-control,
+ .input-group-lg > .form-control-static.input-group-addon,
+ .input-group-lg > .input-group-btn > .form-control-static.btn {
+ padding-right: 0;
+ padding-left: 0; }
+
+.form-control-sm, .input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+ padding: 0.25rem 0.5rem;
+ font-size: 0.875rem;
+ border-radius: 0.2rem; }
+
+select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]),
+.input-group-sm > select.input-group-addon:not([size]):not([multiple]),
+.input-group-sm > .input-group-btn > select.btn:not([size]):not([multiple]) {
+ height: 1.8125rem; }
+
+.form-control-lg, .input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+ padding: 0.75rem 1.5rem;
+ font-size: 1.25rem;
+ border-radius: 0.3rem; }
+
+select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]),
+.input-group-lg > select.input-group-addon:not([size]):not([multiple]),
+.input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) {
+ height: 3.16667rem; }
+
+.form-group {
+ margin-bottom: 1rem; }
+
+.form-text {
+ display: block;
+ margin-top: 0.25rem; }
+
+.form-check {
+ position: relative;
+ display: block;
+ margin-bottom: 0.5rem; }
+ .form-check.disabled .form-check-label {
+ color: #636c72;
+ cursor: not-allowed; }
+
+.form-check-label {
+ padding-left: 1.25rem;
+ margin-bottom: 0;
+ cursor: pointer; }
+
+.form-check-input {
+ position: absolute;
+ margin-top: 0.25rem;
+ margin-left: -1.25rem; }
+ .form-check-input:only-child {
+ position: static; }
+
+.form-check-inline {
+ display: inline-block; }
+ .form-check-inline .form-check-label {
+ vertical-align: middle; }
+ .form-check-inline + .form-check-inline {
+ margin-left: 0.75rem; }
+
+.form-control-feedback {
+ margin-top: 0.25rem; }
+
+.form-control-success,
+.form-control-warning,
+.form-control-danger {
+ padding-right: 2.25rem;
+ background-repeat: no-repeat;
+ background-position: center right 0.5625rem;
+ background-size: 1.125rem 1.125rem; }
+
+.has-success .form-control-feedback,
+.has-success .form-control-label,
+.has-success .col-form-label,
+.has-success .form-check-label,
+.has-success .custom-control {
+ color: #91C500; }
+
+.has-success .form-control {
+ border-color: #91C500; }
+
+.has-success .input-group-addon {
+ color: #91C500;
+ border-color: #91C500;
+ background-color: #e2ff92; }
+
+.has-success .form-control-success {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2391C500' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E"); }
+
+.has-warning .form-control-feedback,
+.has-warning .form-control-label,
+.has-warning .col-form-label,
+.has-warning .form-check-label,
+.has-warning .custom-control {
+ color: #f0ad4e; }
+
+.has-warning .form-control {
+ border-color: #f0ad4e; }
+
+.has-warning .input-group-addon {
+ color: #f0ad4e;
+ border-color: #f0ad4e;
+ background-color: white; }
+
+.has-warning .form-control-warning {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E"); }
+
+.has-danger .form-control-feedback,
+.has-danger .form-control-label,
+.has-danger .col-form-label,
+.has-danger .form-check-label,
+.has-danger .custom-control {
+ color: #9804E9; }
+
+.has-danger .form-control {
+ border-color: #9804E9; }
+
+.has-danger .input-group-addon {
+ color: #9804E9;
+ border-color: #9804E9;
+ background-color: #e6bbfe; }
+
+.has-danger .form-control-danger {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%239804E9' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E"); }
+
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center; }
+ .form-inline .form-check {
+ width: 100%; }
+ @media (min-width: 576px) {
+ .form-inline label {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 0; }
+ .form-inline .form-group {
+ display: flex;
+ flex: 0 0 auto;
+ flex-flow: row wrap;
+ align-items: center;
+ margin-bottom: 0; }
+ .form-inline .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle; }
+ .form-inline .form-control-static {
+ display: inline-block; }
+ .form-inline .input-group {
+ width: auto; }
+ .form-inline .form-control-label {
+ margin-bottom: 0;
+ vertical-align: middle; }
+ .form-inline .form-check {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: auto;
+ margin-top: 0;
+ margin-bottom: 0; }
+ .form-inline .form-check-label {
+ padding-left: 0; }
+ .form-inline .form-check-input {
+ position: relative;
+ margin-top: 0;
+ margin-right: 0.25rem;
+ margin-left: 0; }
+ .form-inline .custom-control {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding-left: 0; }
+ .form-inline .custom-control-indicator {
+ position: static;
+ display: inline-block;
+ margin-right: 0.25rem;
+ vertical-align: text-bottom; }
+ .form-inline .has-feedback .form-control-feedback {
+ top: 0; } }
+
+.btn {
+ display: inline-block;
+ font-weight: normal;
+ line-height: 1.25;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: middle;
+ user-select: none;
+ border: 1px solid transparent;
+ padding: 0.5rem 1rem;
+ font-size: 1rem;
+ border-radius: 0.25rem;
+ transition: all 0.2s ease-in-out; }
+ .btn:focus, .btn:hover {
+ text-decoration: none; }
+ .btn:focus, .btn.focus {
+ outline: 0;
+ box-shadow: 0 0 0 2px rgba(2, 106, 167, 0.25); }
+ .btn.disabled, .btn:disabled {
+ cursor: not-allowed;
+ opacity: .65; }
+ .btn:active, .btn.active {
+ background-image: none; }
+
+a.btn.disabled,
+fieldset[disabled] a.btn {
+ pointer-events: none; }
+
+.btn-primary {
+ color: #fff;
+ background-color: #026AA7;
+ border-color: #026AA7; }
+ .btn-primary:hover {
+ color: #fff;
+ background-color: #014a75;
+ border-color: #01446b; }
+ .btn-primary:focus, .btn-primary.focus {
+ box-shadow: 0 0 0 2px rgba(2, 106, 167, 0.5); }
+ .btn-primary.disabled, .btn-primary:disabled {
+ background-color: #026AA7;
+ border-color: #026AA7; }
+ .btn-primary:active, .btn-primary.active,
+ .show > .btn-primary.dropdown-toggle {
+ color: #fff;
+ background-color: #014a75;
+ background-image: none;
+ border-color: #01446b; }
+
+.btn-secondary {
+ color: #292b2c;
+ background-color: #fff;
+ border-color: #ccc; }
+ .btn-secondary:hover {
+ color: #292b2c;
+ background-color: #e6e6e6;
+ border-color: #adadad; }
+ .btn-secondary:focus, .btn-secondary.focus {
+ box-shadow: 0 0 0 2px rgba(204, 204, 204, 0.5); }
+ .btn-secondary.disabled, .btn-secondary:disabled {
+ background-color: #fff;
+ border-color: #ccc; }
+ .btn-secondary:active, .btn-secondary.active,
+ .show > .btn-secondary.dropdown-toggle {
+ color: #292b2c;
+ background-color: #e6e6e6;
+ background-image: none;
+ border-color: #adadad; }
+
+.btn-info {
+ color: #fff;
+ background-color: #1E97DF;
+ border-color: #1E97DF; }
+ .btn-info:hover {
+ color: #fff;
+ background-color: #1879b2;
+ border-color: #1772a9; }
+ .btn-info:focus, .btn-info.focus {
+ box-shadow: 0 0 0 2px rgba(30, 151, 223, 0.5); }
+ .btn-info.disabled, .btn-info:disabled {
+ background-color: #1E97DF;
+ border-color: #1E97DF; }
+ .btn-info:active, .btn-info.active,
+ .show > .btn-info.dropdown-toggle {
+ color: #fff;
+ background-color: #1879b2;
+ background-image: none;
+ border-color: #1772a9; }
+
+.btn-success {
+ color: #fff;
+ background-color: #91C500;
+ border-color: #91C500; }
+ .btn-success:hover {
+ color: #fff;
+ background-color: #6b9200;
+ border-color: #648800; }
+ .btn-success:focus, .btn-success.focus {
+ box-shadow: 0 0 0 2px rgba(145, 197, 0, 0.5); }
+ .btn-success.disabled, .btn-success:disabled {
+ background-color: #91C500;
+ border-color: #91C500; }
+ .btn-success:active, .btn-success.active,
+ .show > .btn-success.dropdown-toggle {
+ color: #fff;
+ background-color: #6b9200;
+ background-image: none;
+ border-color: #648800; }
+
+.btn-warning {
+ color: #fff;
+ background-color: #f0ad4e;
+ border-color: #f0ad4e; }
+ .btn-warning:hover {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #eb9316; }
+ .btn-warning:focus, .btn-warning.focus {
+ box-shadow: 0 0 0 2px rgba(240, 173, 78, 0.5); }
+ .btn-warning.disabled, .btn-warning:disabled {
+ background-color: #f0ad4e;
+ border-color: #f0ad4e; }
+ .btn-warning:active, .btn-warning.active,
+ .show > .btn-warning.dropdown-toggle {
+ color: #fff;
+ background-color: #ec971f;
+ background-image: none;
+ border-color: #eb9316; }
+
+.btn-danger {
+ color: #fff;
+ background-color: #9804E9;
+ border-color: #9804E9; }
+ .btn-danger:hover {
+ color: #fff;
+ background-color: #7703b7;
+ border-color: #7103ad; }
+ .btn-danger:focus, .btn-danger.focus {
+ box-shadow: 0 0 0 2px rgba(152, 4, 233, 0.5); }
+ .btn-danger.disabled, .btn-danger:disabled {
+ background-color: #9804E9;
+ border-color: #9804E9; }
+ .btn-danger:active, .btn-danger.active,
+ .show > .btn-danger.dropdown-toggle {
+ color: #fff;
+ background-color: #7703b7;
+ background-image: none;
+ border-color: #7103ad; }
+
+.btn-outline-primary {
+ color: #026AA7;
+ background-image: none;
+ background-color: transparent;
+ border-color: #026AA7; }
+ .btn-outline-primary:hover {
+ color: #fff;
+ background-color: #026AA7;
+ border-color: #026AA7; }
+ .btn-outline-primary:focus, .btn-outline-primary.focus {
+ box-shadow: 0 0 0 2px rgba(2, 106, 167, 0.5); }
+ .btn-outline-primary.disabled, .btn-outline-primary:disabled {
+ color: #026AA7;
+ background-color: transparent; }
+ .btn-outline-primary:active, .btn-outline-primary.active,
+ .show > .btn-outline-primary.dropdown-toggle {
+ color: #fff;
+ background-color: #026AA7;
+ border-color: #026AA7; }
+
+.btn-outline-secondary {
+ color: #ccc;
+ background-image: none;
+ background-color: transparent;
+ border-color: #ccc; }
+ .btn-outline-secondary:hover {
+ color: #fff;
+ background-color: #ccc;
+ border-color: #ccc; }
+ .btn-outline-secondary:focus, .btn-outline-secondary.focus {
+ box-shadow: 0 0 0 2px rgba(204, 204, 204, 0.5); }
+ .btn-outline-secondary.disabled, .btn-outline-secondary:disabled {
+ color: #ccc;
+ background-color: transparent; }
+ .btn-outline-secondary:active, .btn-outline-secondary.active,
+ .show > .btn-outline-secondary.dropdown-toggle {
+ color: #fff;
+ background-color: #ccc;
+ border-color: #ccc; }
+
+.btn-outline-info {
+ color: #1E97DF;
+ background-image: none;
+ background-color: transparent;
+ border-color: #1E97DF; }
+ .btn-outline-info:hover {
+ color: #fff;
+ background-color: #1E97DF;
+ border-color: #1E97DF; }
+ .btn-outline-info:focus, .btn-outline-info.focus {
+ box-shadow: 0 0 0 2px rgba(30, 151, 223, 0.5); }
+ .btn-outline-info.disabled, .btn-outline-info:disabled {
+ color: #1E97DF;
+ background-color: transparent; }
+ .btn-outline-info:active, .btn-outline-info.active,
+ .show > .btn-outline-info.dropdown-toggle {
+ color: #fff;
+ background-color: #1E97DF;
+ border-color: #1E97DF; }
+
+.btn-outline-success {
+ color: #91C500;
+ background-image: none;
+ background-color: transparent;
+ border-color: #91C500; }
+ .btn-outline-success:hover {
+ color: #fff;
+ background-color: #91C500;
+ border-color: #91C500; }
+ .btn-outline-success:focus, .btn-outline-success.focus {
+ box-shadow: 0 0 0 2px rgba(145, 197, 0, 0.5); }
+ .btn-outline-success.disabled, .btn-outline-success:disabled {
+ color: #91C500;
+ background-color: transparent; }
+ .btn-outline-success:active, .btn-outline-success.active,
+ .show > .btn-outline-success.dropdown-toggle {
+ color: #fff;
+ background-color: #91C500;
+ border-color: #91C500; }
+
+.btn-outline-warning {
+ color: #f0ad4e;
+ background-image: none;
+ background-color: transparent;
+ border-color: #f0ad4e; }
+ .btn-outline-warning:hover {
+ color: #fff;
+ background-color: #f0ad4e;
+ border-color: #f0ad4e; }
+ .btn-outline-warning:focus, .btn-outline-warning.focus {
+ box-shadow: 0 0 0 2px rgba(240, 173, 78, 0.5); }
+ .btn-outline-warning.disabled, .btn-outline-warning:disabled {
+ color: #f0ad4e;
+ background-color: transparent; }
+ .btn-outline-warning:active, .btn-outline-warning.active,
+ .show > .btn-outline-warning.dropdown-toggle {
+ color: #fff;
+ background-color: #f0ad4e;
+ border-color: #f0ad4e; }
+
+.btn-outline-danger {
+ color: #9804E9;
+ background-image: none;
+ background-color: transparent;
+ border-color: #9804E9; }
+ .btn-outline-danger:hover {
+ color: #fff;
+ background-color: #9804E9;
+ border-color: #9804E9; }
+ .btn-outline-danger:focus, .btn-outline-danger.focus {
+ box-shadow: 0 0 0 2px rgba(152, 4, 233, 0.5); }
+ .btn-outline-danger.disabled, .btn-outline-danger:disabled {
+ color: #9804E9;
+ background-color: transparent; }
+ .btn-outline-danger:active, .btn-outline-danger.active,
+ .show > .btn-outline-danger.dropdown-toggle {
+ color: #fff;
+ background-color: #9804E9;
+ border-color: #9804E9; }
+
+.btn-link {
+ font-weight: normal;
+ color: #8633B3;
+ border-radius: 0; }
+ .btn-link, .btn-link:active, .btn-link.active, .btn-link:disabled {
+ background-color: transparent; }
+ .btn-link, .btn-link:focus, .btn-link:active {
+ border-color: transparent; }
+ .btn-link:hover {
+ border-color: transparent; }
+ .btn-link:focus, .btn-link:hover {
+ color: #592277;
+ text-decoration: underline;
+ background-color: transparent; }
+ .btn-link:disabled {
+ color: #636c72; }
+ .btn-link:disabled:focus, .btn-link:disabled:hover {
+ text-decoration: none; }
+
+.btn-lg, .btn-group-lg > .btn {
+ padding: 0.75rem 1.5rem;
+ font-size: 1.25rem;
+ border-radius: 0.3rem; }
+
+.btn-sm, .btn-group-sm > .btn {
+ padding: 0.25rem 0.5rem;
+ font-size: 0.875rem;
+ border-radius: 0.2rem; }
+
+.btn-block {
+ display: block;
+ width: 100%; }
+
+.btn-block + .btn-block {
+ margin-top: 0.5rem; }
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+ width: 100%; }
+
+.fade {
+ opacity: 0;
+ transition: opacity 0.15s linear; }
+ .fade.show {
+ opacity: 1; }
+
+.collapse {
+ display: none; }
+ .collapse.show {
+ display: block; }
+
+tr.collapse.show {
+ display: table-row; }
+
+tbody.collapse.show {
+ display: table-row-group; }
+
+.collapsing {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ transition: height 0.35s ease; }
+
+.dropup,
+.dropdown {
+ position: relative; }
+
+.dropdown-toggle::after {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-left: 0.3em;
+ vertical-align: middle;
+ content: "";
+ border-top: 0.3em solid;
+ border-right: 0.3em solid transparent;
+ border-left: 0.3em solid transparent; }
+
+.dropdown-toggle:focus {
+ outline: 0; }
+
+.dropup .dropdown-toggle::after {
+ border-top: 0;
+ border-bottom: 0.3em solid; }
+
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 10rem;
+ padding: 0.5rem 0;
+ margin: 0.125rem 0 0;
+ font-size: 1rem;
+ color: #292b2c;
+ text-align: left;
+ list-style: none;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem; }
+
+.dropdown-divider {
+ height: 1px;
+ margin: 0.5rem 0;
+ overflow: hidden;
+ background-color: #eceeef; }
+
+.dropdown-item {
+ display: block;
+ width: 100%;
+ padding: 3px 1.5rem;
+ clear: both;
+ font-weight: normal;
+ color: #292b2c;
+ text-align: inherit;
+ white-space: nowrap;
+ background: none;
+ border: 0; }
+ .dropdown-item:focus, .dropdown-item:hover {
+ color: #6FBCEA;
+ text-decoration: none;
+ background-color: #f7f7f9; }
+ .dropdown-item.active, .dropdown-item:active {
+ color: #fff;
+ text-decoration: none;
+ background-color: #6FBCEA; }
+ .dropdown-item.disabled, .dropdown-item:disabled {
+ color: #636c72;
+ cursor: not-allowed;
+ background-color: transparent; }
+
+.show > .dropdown-menu {
+ display: block; }
+
+.show > a {
+ outline: 0; }
+
+.dropdown-menu-right {
+ right: 0;
+ left: auto; }
+
+.dropdown-menu-left {
+ right: auto;
+ left: 0; }
+
+.dropdown-header {
+ display: block;
+ padding: 0.5rem 1.5rem;
+ margin-bottom: 0;
+ font-size: 0.875rem;
+ color: #636c72;
+ white-space: nowrap; }
+
+.dropdown-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 990; }
+
+.dropup .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 0.125rem; }
+
+.btn-group,
+.btn-group-vertical {
+ position: relative;
+ display: inline-flex;
+ vertical-align: middle; }
+ .btn-group > .btn,
+ .btn-group-vertical > .btn {
+ position: relative;
+ flex: 0 1 auto; }
+ .btn-group > .btn:hover,
+ .btn-group-vertical > .btn:hover {
+ z-index: 2; }
+ .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,
+ .btn-group-vertical > .btn:focus,
+ .btn-group-vertical > .btn:active,
+ .btn-group-vertical > .btn.active {
+ z-index: 2; }
+ .btn-group .btn + .btn,
+ .btn-group .btn + .btn-group,
+ .btn-group .btn-group + .btn,
+ .btn-group .btn-group + .btn-group,
+ .btn-group-vertical .btn + .btn,
+ .btn-group-vertical .btn + .btn-group,
+ .btn-group-vertical .btn-group + .btn,
+ .btn-group-vertical .btn-group + .btn-group {
+ margin-left: -1px; }
+
+.btn-toolbar {
+ display: flex;
+ justify-content: flex-start; }
+ .btn-toolbar .input-group {
+ width: auto; }
+
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+ border-radius: 0; }
+
+.btn-group > .btn:first-child {
+ margin-left: 0; }
+ .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0; }
+
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0; }
+
+.btn-group > .btn-group {
+ float: left; }
+
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0; }
+
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0; }
+
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0; }
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0; }
+
+.btn + .dropdown-toggle-split {
+ padding-right: 0.75rem;
+ padding-left: 0.75rem; }
+ .btn + .dropdown-toggle-split::after {
+ margin-left: 0; }
+
+.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {
+ padding-right: 0.375rem;
+ padding-left: 0.375rem; }
+
+.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {
+ padding-right: 1.125rem;
+ padding-left: 1.125rem; }
+
+.btn-group-vertical {
+ display: inline-flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: center; }
+ .btn-group-vertical .btn,
+ .btn-group-vertical .btn-group {
+ width: 100%; }
+ .btn-group-vertical > .btn + .btn,
+ .btn-group-vertical > .btn + .btn-group,
+ .btn-group-vertical > .btn-group + .btn,
+ .btn-group-vertical > .btn-group + .btn-group {
+ margin-top: -1px;
+ margin-left: 0; }
+
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+ border-radius: 0; }
+
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0; }
+
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0; }
+
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0; }
+
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0; }
+
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0; }
+
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+ position: absolute;
+ clip: rect(0, 0, 0, 0);
+ pointer-events: none; }
+
+.input-group {
+ position: relative;
+ display: flex;
+ width: 100%; }
+ .input-group .form-control {
+ position: relative;
+ z-index: 2;
+ flex: 1 1 auto;
+ width: 1%;
+ margin-bottom: 0; }
+ .input-group .form-control:focus, .input-group .form-control:active, .input-group .form-control:hover {
+ z-index: 3; }
+
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+ display: flex;
+ flex-direction: column;
+ justify-content: center; }
+ .input-group-addon:not(:first-child):not(:last-child),
+ .input-group-btn:not(:first-child):not(:last-child),
+ .input-group .form-control:not(:first-child):not(:last-child) {
+ border-radius: 0; }
+
+.input-group-addon,
+.input-group-btn {
+ white-space: nowrap;
+ vertical-align: middle; }
+
+.input-group-addon {
+ padding: 0.5rem 0.75rem;
+ margin-bottom: 0;
+ font-size: 1rem;
+ font-weight: normal;
+ line-height: 1.25;
+ color: #464a4c;
+ text-align: center;
+ background-color: #eceeef;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem; }
+ .input-group-addon.form-control-sm,
+ .input-group-sm > .input-group-addon,
+ .input-group-sm > .input-group-btn > .input-group-addon.btn {
+ padding: 0.25rem 0.5rem;
+ font-size: 0.875rem;
+ border-radius: 0.2rem; }
+ .input-group-addon.form-control-lg,
+ .input-group-lg > .input-group-addon,
+ .input-group-lg > .input-group-btn > .input-group-addon.btn {
+ padding: 0.75rem 1.5rem;
+ font-size: 1.25rem;
+ border-radius: 0.3rem; }
+ .input-group-addon input[type="radio"],
+ .input-group-addon input[type="checkbox"] {
+ margin-top: 0; }
+
+.input-group .form-control:not(:last-child),
+.input-group-addon:not(:last-child),
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group > .btn,
+.input-group-btn:not(:last-child) > .dropdown-toggle,
+.input-group-btn:not(:first-child) > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:not(:first-child) > .btn-group:not(:last-child) > .btn {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0; }
+
+.input-group-addon:not(:last-child) {
+ border-right: 0; }
+
+.input-group .form-control:not(:first-child),
+.input-group-addon:not(:first-child),
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group > .btn,
+.input-group-btn:not(:first-child) > .dropdown-toggle,
+.input-group-btn:not(:last-child) > .btn:not(:first-child),
+.input-group-btn:not(:last-child) > .btn-group:not(:first-child) > .btn {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0; }
+
+.form-control + .input-group-addon:not(:first-child) {
+ border-left: 0; }
+
+.input-group-btn {
+ position: relative;
+ font-size: 0;
+ white-space: nowrap; }
+ .input-group-btn > .btn {
+ position: relative;
+ flex: 1; }
+ .input-group-btn > .btn + .btn {
+ margin-left: -1px; }
+ .input-group-btn > .btn:focus, .input-group-btn > .btn:active, .input-group-btn > .btn:hover {
+ z-index: 3; }
+ .input-group-btn:not(:last-child) > .btn,
+ .input-group-btn:not(:last-child) > .btn-group {
+ margin-right: -1px; }
+ .input-group-btn:not(:first-child) > .btn,
+ .input-group-btn:not(:first-child) > .btn-group {
+ z-index: 2;
+ margin-left: -1px; }
+ .input-group-btn:not(:first-child) > .btn:focus, .input-group-btn:not(:first-child) > .btn:active, .input-group-btn:not(:first-child) > .btn:hover,
+ .input-group-btn:not(:first-child) > .btn-group:focus,
+ .input-group-btn:not(:first-child) > .btn-group:active,
+ .input-group-btn:not(:first-child) > .btn-group:hover {
+ z-index: 3; }
+
+.custom-control {
+ position: relative;
+ display: inline-flex;
+ min-height: 1.5rem;
+ padding-left: 1.5rem;
+ margin-right: 1rem;
+ cursor: pointer; }
+
+.custom-control-input {
+ position: absolute;
+ z-index: -1;
+ opacity: 0; }
+ .custom-control-input:checked ~ .custom-control-indicator {
+ color: #fff;
+ background-color: #026AA7; }
+ .custom-control-input:focus ~ .custom-control-indicator {
+ box-shadow: 0 0 0 1px #F4F5F1, 0 0 0 3px #026AA7; }
+ .custom-control-input:active ~ .custom-control-indicator {
+ color: #fff;
+ background-color: #5ec2fd; }
+ .custom-control-input:disabled ~ .custom-control-indicator {
+ cursor: not-allowed;
+ background-color: #eceeef; }
+ .custom-control-input:disabled ~ .custom-control-description {
+ color: #636c72;
+ cursor: not-allowed; }
+
+.custom-control-indicator {
+ position: absolute;
+ top: 0.25rem;
+ left: 0;
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ pointer-events: none;
+ user-select: none;
+ background-color: #ddd;
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-size: 50% 50%; }
+
+.custom-checkbox .custom-control-indicator {
+ border-radius: 0.25rem; }
+
+.custom-checkbox .custom-control-input:checked ~ .custom-control-indicator {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); }
+
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator {
+ background-color: #026AA7;
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E"); }
+
+.custom-radio .custom-control-indicator {
+ border-radius: 50%; }
+
+.custom-radio .custom-control-input:checked ~ .custom-control-indicator {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); }
+
+.custom-controls-stacked {
+ display: flex;
+ flex-direction: column; }
+ .custom-controls-stacked .custom-control {
+ margin-bottom: 0.25rem; }
+ .custom-controls-stacked .custom-control + .custom-control {
+ margin-left: 0; }
+
+.custom-select {
+ display: inline-block;
+ max-width: 100%;
+ height: calc(2.25rem + 2px);
+ padding: 0.375rem 1.75rem 0.375rem 0.75rem;
+ line-height: 1.25;
+ color: #464a4c;
+ vertical-align: middle;
+ background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center;
+ background-size: 8px 10px;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem;
+ -moz-appearance: none;
+ -webkit-appearance: none; }
+ .custom-select:focus {
+ border-color: #2caffc;
+ outline: none; }
+ .custom-select:focus::-ms-value {
+ color: #464a4c;
+ background-color: #D1ECFC; }
+ .custom-select:disabled {
+ color: #636c72;
+ cursor: not-allowed;
+ background-color: #eceeef; }
+ .custom-select::-ms-expand {
+ opacity: 0; }
+
+.custom-select-sm {
+ padding-top: 0.375rem;
+ padding-bottom: 0.375rem;
+ font-size: 75%; }
+
+.custom-file {
+ position: relative;
+ display: inline-block;
+ max-width: 100%;
+ height: 2.5rem;
+ margin-bottom: 0;
+ cursor: pointer; }
+
+.custom-file-input {
+ min-width: 14rem;
+ max-width: 100%;
+ height: 2.5rem;
+ margin: 0;
+ filter: alpha(opacity=0);
+ opacity: 0; }
+
+.custom-file-control {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: 5;
+ height: 2.5rem;
+ padding: 0.5rem 1rem;
+ line-height: 1.5;
+ color: #464a4c;
+ pointer-events: none;
+ user-select: none;
+ background-color: #fff;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem; }
+ .custom-file-control:lang(en)::after {
+ content: "Choose file..."; }
+ .custom-file-control::before {
+ position: absolute;
+ top: -1px;
+ right: -1px;
+ bottom: -1px;
+ z-index: 6;
+ display: block;
+ height: 2.5rem;
+ padding: 0.5rem 1rem;
+ line-height: 1.5;
+ color: #464a4c;
+ background-color: #eceeef;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0 0.25rem 0.25rem 0; }
+ .custom-file-control:lang(en)::before {
+ content: "Browse"; }
+
+.nav {
+ display: flex;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none; }
+
+.nav-link {
+ display: block;
+ padding: 0.5em 1em; }
+ .nav-link:focus, .nav-link:hover {
+ text-decoration: none; }
+ .nav-link.disabled {
+ color: #636c72;
+ cursor: not-allowed; }
+
+.nav-tabs {
+ border-bottom: 1px solid #ddd; }
+ .nav-tabs .nav-item {
+ margin-bottom: -1px; }
+ .nav-tabs .nav-link {
+ border: 1px solid transparent;
+ border-top-right-radius: 0.25rem;
+ border-top-left-radius: 0.25rem; }
+ .nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover {
+ border-color: #eceeef #eceeef #ddd; }
+ .nav-tabs .nav-link.disabled {
+ color: #636c72;
+ background-color: transparent;
+ border-color: transparent; }
+ .nav-tabs .nav-link.active,
+ .nav-tabs .nav-item.show .nav-link {
+ color: #464a4c;
+ background-color: #F4F5F1;
+ border-color: #ddd #ddd #F4F5F1; }
+ .nav-tabs .dropdown-menu {
+ margin-top: -1px;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0; }
+
+.nav-pills .nav-link {
+ border-radius: 0.25rem; }
+
+.nav-pills .nav-link.active,
+.nav-pills .nav-item.show .nav-link {
+ color: #fff;
+ cursor: default;
+ background-color: #026AA7; }
+
+.nav-fill .nav-item {
+ flex: 1 1 auto;
+ text-align: center; }
+
+.nav-justified .nav-item {
+ flex: 1 1 100%;
+ text-align: center; }
+
+.tab-content > .tab-pane {
+ display: none; }
+
+.tab-content > .active {
+ display: block; }
+
+.navbar {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ padding: 0.5rem 1rem; }
+
+.navbar-brand {
+ display: inline-block;
+ padding-top: .25rem;
+ padding-bottom: .25rem;
+ margin-right: 1rem;
+ font-size: 1.25rem;
+ line-height: inherit;
+ white-space: nowrap; }
+ .navbar-brand:focus, .navbar-brand:hover {
+ text-decoration: none; }
+
+.navbar-nav {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none; }
+ .navbar-nav .nav-link {
+ padding-right: 0;
+ padding-left: 0; }
+
+.navbar-text {
+ display: inline-block;
+ padding-top: .425rem;
+ padding-bottom: .425rem; }
+
+.navbar-toggler {
+ align-self: flex-start;
+ padding: 0.25rem 0.75rem;
+ font-size: 1.25rem;
+ line-height: 1;
+ background: transparent;
+ border: 1px solid transparent;
+ border-radius: 0.25rem; }
+ .navbar-toggler:focus, .navbar-toggler:hover {
+ text-decoration: none; }
+
+.navbar-toggler-icon {
+ display: inline-block;
+ width: 1.5em;
+ height: 1.5em;
+ vertical-align: middle;
+ content: "";
+ background: no-repeat center center;
+ background-size: 100% 100%; }
+
+.navbar-toggler-left {
+ position: absolute;
+ left: 1rem; }
+
+.navbar-toggler-right {
+ position: absolute;
+ right: 1rem; }
+
+@media (max-width: 575px) {
+ .navbar-toggleable .navbar-nav .dropdown-menu {
+ position: static;
+ float: none; }
+ .navbar-toggleable > .container {
+ padding-right: 0;
+ padding-left: 0; } }
+
+@media (min-width: 576px) {
+ .navbar-toggleable {
+ flex-direction: row;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable .navbar-nav {
+ flex-direction: row; }
+ .navbar-toggleable .navbar-nav .nav-link {
+ padding-right: .5rem;
+ padding-left: .5rem; }
+ .navbar-toggleable > .container {
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable .navbar-collapse {
+ display: flex !important;
+ width: 100%; }
+ .navbar-toggleable .navbar-toggler {
+ display: none; } }
+
+@media (max-width: 767px) {
+ .navbar-toggleable-sm .navbar-nav .dropdown-menu {
+ position: static;
+ float: none; }
+ .navbar-toggleable-sm > .container {
+ padding-right: 0;
+ padding-left: 0; } }
+
+@media (min-width: 768px) {
+ .navbar-toggleable-sm {
+ flex-direction: row;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable-sm .navbar-nav {
+ flex-direction: row; }
+ .navbar-toggleable-sm .navbar-nav .nav-link {
+ padding-right: .5rem;
+ padding-left: .5rem; }
+ .navbar-toggleable-sm > .container {
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable-sm .navbar-collapse {
+ display: flex !important;
+ width: 100%; }
+ .navbar-toggleable-sm .navbar-toggler {
+ display: none; } }
+
+@media (max-width: 991px) {
+ .navbar-toggleable-md .navbar-nav .dropdown-menu {
+ position: static;
+ float: none; }
+ .navbar-toggleable-md > .container {
+ padding-right: 0;
+ padding-left: 0; } }
+
+@media (min-width: 992px) {
+ .navbar-toggleable-md {
+ flex-direction: row;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable-md .navbar-nav {
+ flex-direction: row; }
+ .navbar-toggleable-md .navbar-nav .nav-link {
+ padding-right: .5rem;
+ padding-left: .5rem; }
+ .navbar-toggleable-md > .container {
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable-md .navbar-collapse {
+ display: flex !important;
+ width: 100%; }
+ .navbar-toggleable-md .navbar-toggler {
+ display: none; } }
+
+@media (max-width: 1199px) {
+ .navbar-toggleable-lg .navbar-nav .dropdown-menu {
+ position: static;
+ float: none; }
+ .navbar-toggleable-lg > .container {
+ padding-right: 0;
+ padding-left: 0; } }
+
+@media (min-width: 1200px) {
+ .navbar-toggleable-lg {
+ flex-direction: row;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable-lg .navbar-nav {
+ flex-direction: row; }
+ .navbar-toggleable-lg .navbar-nav .nav-link {
+ padding-right: .5rem;
+ padding-left: .5rem; }
+ .navbar-toggleable-lg > .container {
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable-lg .navbar-collapse {
+ display: flex !important;
+ width: 100%; }
+ .navbar-toggleable-lg .navbar-toggler {
+ display: none; } }
+
+.navbar-toggleable-xl {
+ flex-direction: row;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable-xl .navbar-nav .dropdown-menu {
+ position: static;
+ float: none; }
+ .navbar-toggleable-xl > .container {
+ padding-right: 0;
+ padding-left: 0; }
+ .navbar-toggleable-xl .navbar-nav {
+ flex-direction: row; }
+ .navbar-toggleable-xl .navbar-nav .nav-link {
+ padding-right: .5rem;
+ padding-left: .5rem; }
+ .navbar-toggleable-xl > .container {
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: center; }
+ .navbar-toggleable-xl .navbar-collapse {
+ display: flex !important;
+ width: 100%; }
+ .navbar-toggleable-xl .navbar-toggler {
+ display: none; }
+
+.navbar-light .navbar-brand,
+.navbar-light .navbar-toggler {
+ color: rgba(0, 0, 0, 0.9); }
+ .navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover,
+ .navbar-light .navbar-toggler:focus,
+ .navbar-light .navbar-toggler:hover {
+ color: rgba(0, 0, 0, 0.9); }
+
+.navbar-light .navbar-nav .nav-link {
+ color: rgba(0, 0, 0, 0.5); }
+ .navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover {
+ color: rgba(0, 0, 0, 0.7); }
+ .navbar-light .navbar-nav .nav-link.disabled {
+ color: rgba(0, 0, 0, 0.3); }
+
+.navbar-light .navbar-nav .open > .nav-link,
+.navbar-light .navbar-nav .active > .nav-link,
+.navbar-light .navbar-nav .nav-link.open,
+.navbar-light .navbar-nav .nav-link.active {
+ color: rgba(0, 0, 0, 0.9); }
+
+.navbar-light .navbar-toggler {
+ border-color: rgba(0, 0, 0, 0.1); }
+
+.navbar-light .navbar-toggler-icon {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E"); }
+
+.navbar-light .navbar-text {
+ color: rgba(0, 0, 0, 0.5); }
+
+.navbar-inverse .navbar-brand,
+.navbar-inverse .navbar-toggler {
+ color: white; }
+ .navbar-inverse .navbar-brand:focus, .navbar-inverse .navbar-brand:hover,
+ .navbar-inverse .navbar-toggler:focus,
+ .navbar-inverse .navbar-toggler:hover {
+ color: white; }
+
+.navbar-inverse .navbar-nav .nav-link {
+ color: rgba(255, 255, 255, 0.5); }
+ .navbar-inverse .navbar-nav .nav-link:focus, .navbar-inverse .navbar-nav .nav-link:hover {
+ color: rgba(255, 255, 255, 0.75); }
+ .navbar-inverse .navbar-nav .nav-link.disabled {
+ color: rgba(255, 255, 255, 0.25); }
+
+.navbar-inverse .navbar-nav .open > .nav-link,
+.navbar-inverse .navbar-nav .active > .nav-link,
+.navbar-inverse .navbar-nav .nav-link.open,
+.navbar-inverse .navbar-nav .nav-link.active {
+ color: white; }
+
+.navbar-inverse .navbar-toggler {
+ border-color: rgba(255, 255, 255, 0.1); }
+
+.navbar-inverse .navbar-toggler-icon {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E"); }
+
+.navbar-inverse .navbar-text {
+ color: rgba(255, 255, 255, 0.5); }
+
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ background-color: #fff;
+ border: 1px solid rgba(0, 0, 0, 0.125);
+ border-radius: 0.25rem; }
+
+.card-block {
+ flex: 1 1 auto;
+ padding: 1.25rem; }
+
+.card-title {
+ margin-bottom: 0.75rem; }
+
+.card-subtitle {
+ margin-top: -0.375rem;
+ margin-bottom: 0; }
+
+.card-text:last-child {
+ margin-bottom: 0; }
+
+.card-link:hover {
+ text-decoration: none; }
+
+.card-link + .card-link {
+ margin-left: 1.25rem; }
+
+.card > .list-group:first-child .list-group-item:first-child {
+ border-top-right-radius: 0.25rem;
+ border-top-left-radius: 0.25rem; }
+
+.card > .list-group:last-child .list-group-item:last-child {
+ border-bottom-right-radius: 0.25rem;
+ border-bottom-left-radius: 0.25rem; }
+
+.card-header {
+ padding: 0.75rem 1.25rem;
+ margin-bottom: 0;
+ background-color: #f7f7f9;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.125); }
+ .card-header:first-child {
+ border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; }
+
+.card-footer {
+ padding: 0.75rem 1.25rem;
+ background-color: #f7f7f9;
+ border-top: 1px solid rgba(0, 0, 0, 0.125); }
+ .card-footer:last-child {
+ border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); }
+
+.card-header-tabs {
+ margin-right: -0.625rem;
+ margin-bottom: -0.75rem;
+ margin-left: -0.625rem;
+ border-bottom: 0; }
+
+.card-header-pills {
+ margin-right: -0.625rem;
+ margin-left: -0.625rem; }
+
+.card-primary {
+ background-color: #026AA7;
+ border-color: #026AA7; }
+ .card-primary .card-header,
+ .card-primary .card-footer {
+ background-color: transparent; }
+
+.card-success {
+ background-color: #91C500;
+ border-color: #91C500; }
+ .card-success .card-header,
+ .card-success .card-footer {
+ background-color: transparent; }
+
+.card-info {
+ background-color: #1E97DF;
+ border-color: #1E97DF; }
+ .card-info .card-header,
+ .card-info .card-footer {
+ background-color: transparent; }
+
+.card-warning {
+ background-color: #f0ad4e;
+ border-color: #f0ad4e; }
+ .card-warning .card-header,
+ .card-warning .card-footer {
+ background-color: transparent; }
+
+.card-danger {
+ background-color: #9804E9;
+ border-color: #9804E9; }
+ .card-danger .card-header,
+ .card-danger .card-footer {
+ background-color: transparent; }
+
+.card-outline-primary {
+ background-color: transparent;
+ border-color: #026AA7; }
+
+.card-outline-secondary {
+ background-color: transparent;
+ border-color: #ccc; }
+
+.card-outline-info {
+ background-color: transparent;
+ border-color: #1E97DF; }
+
+.card-outline-success {
+ background-color: transparent;
+ border-color: #91C500; }
+
+.card-outline-warning {
+ background-color: transparent;
+ border-color: #f0ad4e; }
+
+.card-outline-danger {
+ background-color: transparent;
+ border-color: #9804E9; }
+
+.card-inverse {
+ color: rgba(255, 255, 255, 0.65); }
+ .card-inverse .card-header,
+ .card-inverse .card-footer {
+ background-color: transparent;
+ border-color: rgba(255, 255, 255, 0.2); }
+ .card-inverse .card-header,
+ .card-inverse .card-footer,
+ .card-inverse .card-title,
+ .card-inverse .card-blockquote {
+ color: #fff; }
+ .card-inverse .card-link,
+ .card-inverse .card-text,
+ .card-inverse .card-subtitle,
+ .card-inverse .card-blockquote .blockquote-footer {
+ color: rgba(255, 255, 255, 0.65); }
+ .card-inverse .card-link:focus, .card-inverse .card-link:hover {
+ color: #fff; }
+
+.card-blockquote {
+ padding: 0;
+ margin-bottom: 0;
+ border-left: 0; }
+
+.card-img {
+ border-radius: calc(0.25rem - 1px); }
+
+.card-img-overlay {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: 1.25rem; }
+
+.card-img-top {
+ border-top-right-radius: calc(0.25rem - 1px);
+ border-top-left-radius: calc(0.25rem - 1px); }
+
+.card-img-bottom {
+ border-bottom-right-radius: calc(0.25rem - 1px);
+ border-bottom-left-radius: calc(0.25rem - 1px); }
+
+@media (min-width: 576px) {
+ .card-deck {
+ display: flex;
+ flex-flow: row wrap; }
+ .card-deck .card {
+ display: flex;
+ flex: 1 0 0;
+ flex-direction: column; }
+ .card-deck .card:not(:first-child) {
+ margin-left: 15px; }
+ .card-deck .card:not(:last-child) {
+ margin-right: 15px; } }
+
+@media (min-width: 576px) {
+ .card-group {
+ display: flex;
+ flex-flow: row wrap; }
+ .card-group .card {
+ flex: 1 0 0; }
+ .card-group .card + .card {
+ margin-left: 0;
+ border-left: 0; }
+ .card-group .card:first-child {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0; }
+ .card-group .card:first-child .card-img-top {
+ border-top-right-radius: 0; }
+ .card-group .card:first-child .card-img-bottom {
+ border-bottom-right-radius: 0; }
+ .card-group .card:last-child {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0; }
+ .card-group .card:last-child .card-img-top {
+ border-top-left-radius: 0; }
+ .card-group .card:last-child .card-img-bottom {
+ border-bottom-left-radius: 0; }
+ .card-group .card:not(:first-child):not(:last-child) {
+ border-radius: 0; }
+ .card-group .card:not(:first-child):not(:last-child) .card-img-top,
+ .card-group .card:not(:first-child):not(:last-child) .card-img-bottom {
+ border-radius: 0; } }
+
+@media (min-width: 576px) {
+ .card-columns {
+ column-count: 3;
+ column-gap: 1.25rem; }
+ .card-columns .card {
+ display: inline-block;
+ width: 100%;
+ margin-bottom: 0.75rem; } }
+
+.breadcrumb {
+ padding: 0.75rem 1rem;
+ margin-bottom: 1rem;
+ list-style: none;
+ background-color: #eceeef;
+ border-radius: 0.25rem; }
+ .breadcrumb::after {
+ display: block;
+ content: "";
+ clear: both; }
+
+.breadcrumb-item {
+ float: left; }
+ .breadcrumb-item + .breadcrumb-item::before {
+ display: inline-block;
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+ color: #636c72;
+ content: "/"; }
+ .breadcrumb-item + .breadcrumb-item:hover::before {
+ text-decoration: underline; }
+ .breadcrumb-item + .breadcrumb-item:hover::before {
+ text-decoration: none; }
+ .breadcrumb-item.active {
+ color: #636c72; }
+
+.pagination {
+ display: flex;
+ padding-left: 0;
+ list-style: none;
+ border-radius: 0.25rem; }
+
+.page-item:first-child .page-link {
+ margin-left: 0;
+ border-bottom-left-radius: 0.25rem;
+ border-top-left-radius: 0.25rem; }
+
+.page-item:last-child .page-link {
+ border-bottom-right-radius: 0.25rem;
+ border-top-right-radius: 0.25rem; }
+
+.page-item.active .page-link {
+ z-index: 2;
+ color: #fff;
+ background-color: #026AA7;
+ border-color: #026AA7; }
+
+.page-item.disabled .page-link {
+ color: #636c72;
+ pointer-events: none;
+ cursor: not-allowed;
+ background-color: #fff;
+ border-color: #ddd; }
+
+.page-link {
+ position: relative;
+ display: block;
+ padding: 0.5rem 0.75rem;
+ margin-left: -1px;
+ line-height: 1.25;
+ color: #8633B3;
+ background-color: #fff;
+ border: 1px solid #ddd; }
+ .page-link:focus, .page-link:hover {
+ color: #592277;
+ text-decoration: none;
+ background-color: #eceeef;
+ border-color: #ddd; }
+
+.pagination-lg .page-link {
+ padding: 0.75rem 1.5rem;
+ font-size: 1.25rem; }
+
+.pagination-lg .page-item:first-child .page-link {
+ border-bottom-left-radius: 0.3rem;
+ border-top-left-radius: 0.3rem; }
+
+.pagination-lg .page-item:last-child .page-link {
+ border-bottom-right-radius: 0.3rem;
+ border-top-right-radius: 0.3rem; }
+
+.pagination-sm .page-link {
+ padding: 0.25rem 0.5rem;
+ font-size: 0.875rem; }
+
+.pagination-sm .page-item:first-child .page-link {
+ border-bottom-left-radius: 0.2rem;
+ border-top-left-radius: 0.2rem; }
+
+.pagination-sm .page-item:last-child .page-link {
+ border-bottom-right-radius: 0.2rem;
+ border-top-right-radius: 0.2rem; }
+
+.badge {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ font-size: 75%;
+ font-weight: bold;
+ line-height: 1;
+ color: #fff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: 0.25rem; }
+ .badge:empty {
+ display: none; }
+
+.btn .badge {
+ position: relative;
+ top: -1px; }
+
+a.badge:focus, a.badge:hover {
+ color: #fff;
+ text-decoration: none;
+ cursor: pointer; }
+
+.badge-pill {
+ padding-right: 0.6em;
+ padding-left: 0.6em;
+ border-radius: 10rem; }
+
+.badge-default {
+ background-color: #636c72; }
+ .badge-default[href]:focus, .badge-default[href]:hover {
+ background-color: #4b5257; }
+
+.badge-primary {
+ background-color: #026AA7; }
+ .badge-primary[href]:focus, .badge-primary[href]:hover {
+ background-color: #014a75; }
+
+.badge-success {
+ background-color: #91C500; }
+ .badge-success[href]:focus, .badge-success[href]:hover {
+ background-color: #6b9200; }
+
+.badge-info {
+ background-color: #1E97DF; }
+ .badge-info[href]:focus, .badge-info[href]:hover {
+ background-color: #1879b2; }
+
+.badge-warning {
+ background-color: #f0ad4e; }
+ .badge-warning[href]:focus, .badge-warning[href]:hover {
+ background-color: #ec971f; }
+
+.badge-danger {
+ background-color: #9804E9; }
+ .badge-danger[href]:focus, .badge-danger[href]:hover {
+ background-color: #7703b7; }
+
+.jumbotron {
+ padding: 2rem 1rem;
+ margin-bottom: 2rem;
+ background-color: #eceeef;
+ border-radius: 0.3rem; }
+ @media (min-width: 576px) {
+ .jumbotron {
+ padding: 4rem 2rem; } }
+
+.jumbotron-hr {
+ border-top-color: #d0d5d8; }
+
+.jumbotron-fluid {
+ padding-right: 0;
+ padding-left: 0;
+ border-radius: 0; }
+
+.alert {
+ padding: 0.75rem 1.25rem;
+ margin-bottom: 1rem;
+ border: 1px solid transparent;
+ border-radius: 0.25rem; }
+
+.alert-heading {
+ color: inherit; }
+
+.alert-link {
+ font-weight: bold; }
+
+.alert-dismissible .close {
+ position: relative;
+ top: -0.75rem;
+ right: -1.25rem;
+ padding: 0.75rem 1.25rem;
+ color: inherit; }
+
+.alert-success {
+ background-color: #dff0d8;
+ border-color: #d0e9c6;
+ color: #3c763d; }
+ .alert-success hr {
+ border-top-color: #c1e2b3; }
+ .alert-success .alert-link {
+ color: #2b542c; }
+
+.alert-info {
+ background-color: #d9edf7;
+ border-color: #bcdff1;
+ color: #31708f; }
+ .alert-info hr {
+ border-top-color: #a6d5ec; }
+ .alert-info .alert-link {
+ color: #245269; }
+
+.alert-warning {
+ background-color: #fcf8e3;
+ border-color: #faf2cc;
+ color: #8a6d3b; }
+ .alert-warning hr {
+ border-top-color: #f7ecb5; }
+ .alert-warning .alert-link {
+ color: #66512c; }
+
+.alert-danger {
+ background-color: #f2dede;
+ border-color: #ebcccc;
+ color: #a94442; }
+ .alert-danger hr {
+ border-top-color: #e4b9b9; }
+ .alert-danger .alert-link {
+ color: #843534; }
+
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 1rem 0; }
+ to {
+ background-position: 0 0; } }
+
+.progress {
+ display: flex;
+ overflow: hidden;
+ font-size: 0.75rem;
+ line-height: 1rem;
+ text-align: center;
+ background-color: #eceeef;
+ border-radius: 0.25rem; }
+
+.progress-bar {
+ height: 1rem;
+ color: #fff;
+ background-color: #026AA7; }
+
+.progress-bar-striped {
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-size: 1rem 1rem; }
+
+.progress-bar-animated {
+ animation: progress-bar-stripes 1s linear infinite; }
+
+.media {
+ display: flex;
+ align-items: flex-start; }
+
+.media-body {
+ flex: 1; }
+
+.list-group {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0; }
+
+.list-group-item-action {
+ width: 100%;
+ color: #464a4c;
+ text-align: inherit; }
+ .list-group-item-action .list-group-item-heading {
+ color: #292b2c; }
+ .list-group-item-action:focus, .list-group-item-action:hover {
+ color: #464a4c;
+ text-decoration: none;
+ background-color: #f7f7f9; }
+ .list-group-item-action:active {
+ color: #292b2c;
+ background-color: #eceeef; }
+
+.list-group-item {
+ position: relative;
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+ padding: 0.75rem 1.25rem;
+ margin-bottom: -1px;
+ background-color: #fff;
+ border: 1px solid rgba(0, 0, 0, 0.125); }
+ .list-group-item:first-child {
+ border-top-right-radius: 0.25rem;
+ border-top-left-radius: 0.25rem; }
+ .list-group-item:last-child {
+ margin-bottom: 0;
+ border-bottom-right-radius: 0.25rem;
+ border-bottom-left-radius: 0.25rem; }
+ .list-group-item:focus, .list-group-item:hover {
+ text-decoration: none; }
+ .list-group-item.disabled, .list-group-item:disabled {
+ color: #636c72;
+ cursor: not-allowed;
+ background-color: #fff; }
+ .list-group-item.disabled .list-group-item-heading, .list-group-item:disabled .list-group-item-heading {
+ color: inherit; }
+ .list-group-item.disabled .list-group-item-text, .list-group-item:disabled .list-group-item-text {
+ color: #636c72; }
+ .list-group-item.active {
+ z-index: 2;
+ color: #fff;
+ background-color: #026AA7;
+ border-color: #026AA7; }
+ .list-group-item.active .list-group-item-heading,
+ .list-group-item.active .list-group-item-heading > small,
+ .list-group-item.active .list-group-item-heading > .small {
+ color: inherit; }
+ .list-group-item.active .list-group-item-text {
+ color: #aadffe; }
+
+.list-group-flush .list-group-item {
+ border-right: 0;
+ border-left: 0;
+ border-radius: 0; }
+
+.list-group-flush:first-child .list-group-item:first-child {
+ border-top: 0; }
+
+.list-group-flush:last-child .list-group-item:last-child {
+ border-bottom: 0; }
+
+.list-group-item-success {
+ color: #3c763d;
+ background-color: #dff0d8; }
+
+a.list-group-item-success,
+button.list-group-item-success {
+ color: #3c763d; }
+ a.list-group-item-success .list-group-item-heading,
+ button.list-group-item-success .list-group-item-heading {
+ color: inherit; }
+ a.list-group-item-success:focus, a.list-group-item-success:hover,
+ button.list-group-item-success:focus,
+ button.list-group-item-success:hover {
+ color: #3c763d;
+ background-color: #d0e9c6; }
+ a.list-group-item-success.active,
+ button.list-group-item-success.active {
+ color: #fff;
+ background-color: #3c763d;
+ border-color: #3c763d; }
+
+.list-group-item-info {
+ color: #31708f;
+ background-color: #d9edf7; }
+
+a.list-group-item-info,
+button.list-group-item-info {
+ color: #31708f; }
+ a.list-group-item-info .list-group-item-heading,
+ button.list-group-item-info .list-group-item-heading {
+ color: inherit; }
+ a.list-group-item-info:focus, a.list-group-item-info:hover,
+ button.list-group-item-info:focus,
+ button.list-group-item-info:hover {
+ color: #31708f;
+ background-color: #c4e3f3; }
+ a.list-group-item-info.active,
+ button.list-group-item-info.active {
+ color: #fff;
+ background-color: #31708f;
+ border-color: #31708f; }
+
+.list-group-item-warning {
+ color: #8a6d3b;
+ background-color: #fcf8e3; }
+
+a.list-group-item-warning,
+button.list-group-item-warning {
+ color: #8a6d3b; }
+ a.list-group-item-warning .list-group-item-heading,
+ button.list-group-item-warning .list-group-item-heading {
+ color: inherit; }
+ a.list-group-item-warning:focus, a.list-group-item-warning:hover,
+ button.list-group-item-warning:focus,
+ button.list-group-item-warning:hover {
+ color: #8a6d3b;
+ background-color: #faf2cc; }
+ a.list-group-item-warning.active,
+ button.list-group-item-warning.active {
+ color: #fff;
+ background-color: #8a6d3b;
+ border-color: #8a6d3b; }
+
+.list-group-item-danger {
+ color: #a94442;
+ background-color: #f2dede; }
+
+a.list-group-item-danger,
+button.list-group-item-danger {
+ color: #a94442; }
+ a.list-group-item-danger .list-group-item-heading,
+ button.list-group-item-danger .list-group-item-heading {
+ color: inherit; }
+ a.list-group-item-danger:focus, a.list-group-item-danger:hover,
+ button.list-group-item-danger:focus,
+ button.list-group-item-danger:hover {
+ color: #a94442;
+ background-color: #ebcccc; }
+ a.list-group-item-danger.active,
+ button.list-group-item-danger.active {
+ color: #fff;
+ background-color: #a94442;
+ border-color: #a94442; }
+
+.embed-responsive {
+ position: relative;
+ display: block;
+ width: 100%;
+ padding: 0;
+ overflow: hidden; }
+ .embed-responsive::before {
+ display: block;
+ content: ""; }
+ .embed-responsive .embed-responsive-item,
+ .embed-responsive iframe,
+ .embed-responsive embed,
+ .embed-responsive object,
+ .embed-responsive video {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: 0; }
+
+.embed-responsive-21by9::before {
+ padding-top: 42.85714%; }
+
+.embed-responsive-16by9::before {
+ padding-top: 56.25%; }
+
+.embed-responsive-4by3::before {
+ padding-top: 75%; }
+
+.embed-responsive-1by1::before {
+ padding-top: 100%; }
+
+.close {
+ float: right;
+ font-size: 1.5rem;
+ font-weight: bold;
+ line-height: 1;
+ color: #000;
+ text-shadow: 0 1px 0 #fff;
+ opacity: .5; }
+ .close:focus, .close:hover {
+ color: #000;
+ text-decoration: none;
+ cursor: pointer;
+ opacity: .75; }
+
+button.close {
+ padding: 0;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+ -webkit-appearance: none; }
+
+.modal-open {
+ overflow: hidden; }
+
+.modal {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1050;
+ display: none;
+ overflow: hidden;
+ outline: 0; }
+ .modal.fade .modal-dialog {
+ transition: transform 0.3s ease-out;
+ transform: translate(0, -25%); }
+ .modal.show .modal-dialog {
+ transform: translate(0, 0); }
+
+.modal-open .modal {
+ overflow-x: hidden;
+ overflow-y: auto; }
+
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 10px; }
+
+.modal-content {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 0.3rem;
+ outline: 0; }
+
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1040;
+ background-color: #000; }
+ .modal-backdrop.fade {
+ opacity: 0; }
+ .modal-backdrop.show {
+ opacity: 0.5; }
+
+.modal-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 15px;
+ border-bottom: 1px solid #eceeef; }
+
+.modal-title {
+ margin-bottom: 0;
+ line-height: 1.5; }
+
+.modal-body {
+ position: relative;
+ flex: 1 1 auto;
+ padding: 15px; }
+
+.modal-footer {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ padding: 15px;
+ border-top: 1px solid #eceeef; }
+ .modal-footer > :not(:first-child) {
+ margin-left: .25rem; }
+ .modal-footer > :not(:last-child) {
+ margin-right: .25rem; }
+
+.modal-scrollbar-measure {
+ position: absolute;
+ top: -9999px;
+ width: 50px;
+ height: 50px;
+ overflow: scroll; }
+
+@media (min-width: 576px) {
+ .modal-dialog {
+ max-width: 600px;
+ margin: 30px auto; }
+ .modal-sm {
+ max-width: 300px; } }
+
+@media (min-width: 992px) {
+ .modal-lg {
+ max-width: 800px; } }
+
+.tooltip {
+ position: absolute;
+ z-index: 1070;
+ display: block;
+ font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+ font-style: normal;
+ font-weight: normal;
+ letter-spacing: normal;
+ line-break: auto;
+ line-height: 1.5;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ white-space: normal;
+ word-break: normal;
+ word-spacing: normal;
+ font-size: 0.875rem;
+ word-wrap: break-word;
+ opacity: 0; }
+ .tooltip.show {
+ opacity: 0.9; }
+ .tooltip.tooltip-top, .tooltip.bs-tether-element-attached-bottom {
+ padding: 5px 0;
+ margin-top: -3px; }
+ .tooltip.tooltip-top .tooltip-inner::before, .tooltip.bs-tether-element-attached-bottom .tooltip-inner::before {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ content: "";
+ border-width: 5px 5px 0;
+ border-top-color: #000; }
+ .tooltip.tooltip-right, .tooltip.bs-tether-element-attached-left {
+ padding: 0 5px;
+ margin-left: 3px; }
+ .tooltip.tooltip-right .tooltip-inner::before, .tooltip.bs-tether-element-attached-left .tooltip-inner::before {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ content: "";
+ border-width: 5px 5px 5px 0;
+ border-right-color: #000; }
+ .tooltip.tooltip-bottom, .tooltip.bs-tether-element-attached-top {
+ padding: 5px 0;
+ margin-top: 3px; }
+ .tooltip.tooltip-bottom .tooltip-inner::before, .tooltip.bs-tether-element-attached-top .tooltip-inner::before {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ content: "";
+ border-width: 0 5px 5px;
+ border-bottom-color: #000; }
+ .tooltip.tooltip-left, .tooltip.bs-tether-element-attached-right {
+ padding: 0 5px;
+ margin-left: -3px; }
+ .tooltip.tooltip-left .tooltip-inner::before, .tooltip.bs-tether-element-attached-right .tooltip-inner::before {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ content: "";
+ border-width: 5px 0 5px 5px;
+ border-left-color: #000; }
+
+.tooltip-inner {
+ max-width: 200px;
+ padding: 3px 8px;
+ color: #fff;
+ text-align: center;
+ background-color: #000;
+ border-radius: 0.25rem; }
+ .tooltip-inner::before {
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid; }
+
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1060;
+ display: block;
+ max-width: 276px;
+ padding: 1px;
+ font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+ font-style: normal;
+ font-weight: normal;
+ letter-spacing: normal;
+ line-break: auto;
+ line-height: 1.5;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ white-space: normal;
+ word-break: normal;
+ word-spacing: normal;
+ font-size: 0.875rem;
+ word-wrap: break-word;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 0.3rem; }
+ .popover.popover-top, .popover.bs-tether-element-attached-bottom {
+ margin-top: -10px; }
+ .popover.popover-top::before, .popover.popover-top::after, .popover.bs-tether-element-attached-bottom::before, .popover.bs-tether-element-attached-bottom::after {
+ left: 50%;
+ border-bottom-width: 0; }
+ .popover.popover-top::before, .popover.bs-tether-element-attached-bottom::before {
+ bottom: -11px;
+ margin-left: -11px;
+ border-top-color: rgba(0, 0, 0, 0.25); }
+ .popover.popover-top::after, .popover.bs-tether-element-attached-bottom::after {
+ bottom: -10px;
+ margin-left: -10px;
+ border-top-color: #fff; }
+ .popover.popover-right, .popover.bs-tether-element-attached-left {
+ margin-left: 10px; }
+ .popover.popover-right::before, .popover.popover-right::after, .popover.bs-tether-element-attached-left::before, .popover.bs-tether-element-attached-left::after {
+ top: 50%;
+ border-left-width: 0; }
+ .popover.popover-right::before, .popover.bs-tether-element-attached-left::before {
+ left: -11px;
+ margin-top: -11px;
+ border-right-color: rgba(0, 0, 0, 0.25); }
+ .popover.popover-right::after, .popover.bs-tether-element-attached-left::after {
+ left: -10px;
+ margin-top: -10px;
+ border-right-color: #fff; }
+ .popover.popover-bottom, .popover.bs-tether-element-attached-top {
+ margin-top: 10px; }
+ .popover.popover-bottom::before, .popover.popover-bottom::after, .popover.bs-tether-element-attached-top::before, .popover.bs-tether-element-attached-top::after {
+ left: 50%;
+ border-top-width: 0; }
+ .popover.popover-bottom::before, .popover.bs-tether-element-attached-top::before {
+ top: -11px;
+ margin-left: -11px;
+ border-bottom-color: rgba(0, 0, 0, 0.25); }
+ .popover.popover-bottom::after, .popover.bs-tether-element-attached-top::after {
+ top: -10px;
+ margin-left: -10px;
+ border-bottom-color: #f7f7f7; }
+ .popover.popover-bottom .popover-title::before, .popover.bs-tether-element-attached-top .popover-title::before {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ display: block;
+ width: 20px;
+ margin-left: -10px;
+ content: "";
+ border-bottom: 1px solid #f7f7f7; }
+ .popover.popover-left, .popover.bs-tether-element-attached-right {
+ margin-left: -10px; }
+ .popover.popover-left::before, .popover.popover-left::after, .popover.bs-tether-element-attached-right::before, .popover.bs-tether-element-attached-right::after {
+ top: 50%;
+ border-right-width: 0; }
+ .popover.popover-left::before, .popover.bs-tether-element-attached-right::before {
+ right: -11px;
+ margin-top: -11px;
+ border-left-color: rgba(0, 0, 0, 0.25); }
+ .popover.popover-left::after, .popover.bs-tether-element-attached-right::after {
+ right: -10px;
+ margin-top: -10px;
+ border-left-color: #fff; }
+
+.popover-title {
+ padding: 8px 14px;
+ margin-bottom: 0;
+ font-size: 1rem;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ border-top-right-radius: calc(0.3rem - 1px);
+ border-top-left-radius: calc(0.3rem - 1px); }
+ .popover-title:empty {
+ display: none; }
+
+.popover-content {
+ padding: 9px 14px; }
+
+.popover::before,
+.popover::after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid; }
+
+.popover::before {
+ content: "";
+ border-width: 11px; }
+
+.popover::after {
+ content: "";
+ border-width: 10px; }
+
+.carousel {
+ position: relative; }
+
+.carousel-inner {
+ position: relative;
+ width: 100%;
+ overflow: hidden; }
+
+.carousel-item {
+ position: relative;
+ display: none;
+ width: 100%; }
+ @media (-webkit-transform-3d) {
+ .carousel-item {
+ transition: transform 0.6s ease-in-out;
+ backface-visibility: hidden;
+ perspective: 1000px; } }
+ @supports (transform: translate3d(0, 0, 0)) {
+ .carousel-item {
+ transition: transform 0.6s ease-in-out;
+ backface-visibility: hidden;
+ perspective: 1000px; } }
+
+.carousel-item.active,
+.carousel-item-next,
+.carousel-item-prev {
+ display: flex; }
+
+.carousel-item-next,
+.carousel-item-prev {
+ position: absolute;
+ top: 0; }
+
+@media (-webkit-transform-3d) {
+ .carousel-item-next.carousel-item-left,
+ .carousel-item-prev.carousel-item-right {
+ transform: translate3d(0, 0, 0); }
+ .carousel-item-next,
+ .active.carousel-item-right {
+ transform: translate3d(100%, 0, 0); }
+ .carousel-item-prev,
+ .active.carousel-item-left {
+ transform: translate3d(-100%, 0, 0); } }
+
+@supports (transform: translate3d(0, 0, 0)) {
+ .carousel-item-next.carousel-item-left,
+ .carousel-item-prev.carousel-item-right {
+ transform: translate3d(0, 0, 0); }
+ .carousel-item-next,
+ .active.carousel-item-right {
+ transform: translate3d(100%, 0, 0); }
+ .carousel-item-prev,
+ .active.carousel-item-left {
+ transform: translate3d(-100%, 0, 0); } }
+
+.carousel-control-prev,
+.carousel-control-next {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 15%;
+ color: #fff;
+ text-align: center;
+ opacity: 0.5; }
+ .carousel-control-prev:focus, .carousel-control-prev:hover,
+ .carousel-control-next:focus,
+ .carousel-control-next:hover {
+ color: #fff;
+ text-decoration: none;
+ outline: 0;
+ opacity: .9; }
+
+.carousel-control-prev {
+ left: 0; }
+
+.carousel-control-next {
+ right: 0; }
+
+.carousel-control-prev-icon,
+.carousel-control-next-icon {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ background: transparent no-repeat center center;
+ background-size: 100% 100%; }
+
+.carousel-control-prev-icon {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M4 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); }
+
+.carousel-control-next-icon {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M1.5 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); }
+
+.carousel-indicators {
+ position: absolute;
+ right: 0;
+ bottom: 10px;
+ left: 0;
+ z-index: 15;
+ display: flex;
+ justify-content: center;
+ padding-left: 0;
+ margin-right: 15%;
+ margin-left: 15%;
+ list-style: none; }
+ .carousel-indicators li {
+ position: relative;
+ flex: 1 0 auto;
+ max-width: 30px;
+ height: 3px;
+ margin-right: 3px;
+ margin-left: 3px;
+ text-indent: -999px;
+ cursor: pointer;
+ background-color: rgba(255, 255, 255, 0.5); }
+ .carousel-indicators li::before {
+ position: absolute;
+ top: -10px;
+ left: 0;
+ display: inline-block;
+ width: 100%;
+ height: 10px;
+ content: ""; }
+ .carousel-indicators li::after {
+ position: absolute;
+ bottom: -10px;
+ left: 0;
+ display: inline-block;
+ width: 100%;
+ height: 10px;
+ content: ""; }
+ .carousel-indicators .active {
+ background-color: #fff; }
+
+.carousel-caption {
+ position: absolute;
+ right: 15%;
+ bottom: 20px;
+ left: 15%;
+ z-index: 10;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ color: #fff;
+ text-align: center; }
+
+.align-baseline {
+ vertical-align: baseline !important; }
+
+.align-top {
+ vertical-align: top !important; }
+
+.align-middle {
+ vertical-align: middle !important; }
+
+.align-bottom {
+ vertical-align: bottom !important; }
+
+.align-text-bottom {
+ vertical-align: text-bottom !important; }
+
+.align-text-top {
+ vertical-align: text-top !important; }
+
+.bg-faded {
+ background-color: #edefe8; }
+
+.bg-primary {
+ background-color: #026AA7 !important; }
+
+a.bg-primary:focus, a.bg-primary:hover {
+ background-color: #014a75 !important; }
+
+.bg-success {
+ background-color: #91C500 !important; }
+
+a.bg-success:focus, a.bg-success:hover {
+ background-color: #6b9200 !important; }
+
+.bg-info {
+ background-color: #1E97DF !important; }
+
+a.bg-info:focus, a.bg-info:hover {
+ background-color: #1879b2 !important; }
+
+.bg-warning {
+ background-color: #f0ad4e !important; }
+
+a.bg-warning:focus, a.bg-warning:hover {
+ background-color: #ec971f !important; }
+
+.bg-danger {
+ background-color: #9804E9 !important; }
+
+a.bg-danger:focus, a.bg-danger:hover {
+ background-color: #7703b7 !important; }
+
+.bg-inverse {
+ background-color: #292b2c !important; }
+
+a.bg-inverse:focus, a.bg-inverse:hover {
+ background-color: #101112 !important; }
+
+.border-0 {
+ border: 0 !important; }
+
+.border-top-0 {
+ border-top: 0 !important; }
+
+.border-right-0 {
+ border-right: 0 !important; }
+
+.border-bottom-0 {
+ border-bottom: 0 !important; }
+
+.border-left-0 {
+ border-left: 0 !important; }
+
+.rounded {
+ border-radius: 0.25rem; }
+
+.rounded-top {
+ border-top-right-radius: 0.25rem;
+ border-top-left-radius: 0.25rem; }
+
+.rounded-right {
+ border-bottom-right-radius: 0.25rem;
+ border-top-right-radius: 0.25rem; }
+
+.rounded-bottom {
+ border-bottom-right-radius: 0.25rem;
+ border-bottom-left-radius: 0.25rem; }
+
+.rounded-left {
+ border-bottom-left-radius: 0.25rem;
+ border-top-left-radius: 0.25rem; }
+
+.rounded-circle {
+ border-radius: 50%; }
+
+.rounded-0 {
+ border-radius: 0; }
+
+.clearfix::after {
+ display: block;
+ content: "";
+ clear: both; }
+
+.d-none {
+ display: none !important; }
+
+.d-inline {
+ display: inline !important; }
+
+.d-inline-block {
+ display: inline-block !important; }
+
+.d-block {
+ display: block !important; }
+
+.d-table {
+ display: table !important; }
+
+.d-table-cell {
+ display: table-cell !important; }
+
+.d-flex {
+ display: flex !important; }
+
+.d-inline-flex {
+ display: inline-flex !important; }
+
+@media (min-width: 576px) {
+ .d-sm-none {
+ display: none !important; }
+ .d-sm-inline {
+ display: inline !important; }
+ .d-sm-inline-block {
+ display: inline-block !important; }
+ .d-sm-block {
+ display: block !important; }
+ .d-sm-table {
+ display: table !important; }
+ .d-sm-table-cell {
+ display: table-cell !important; }
+ .d-sm-flex {
+ display: flex !important; }
+ .d-sm-inline-flex {
+ display: inline-flex !important; } }
+
+@media (min-width: 768px) {
+ .d-md-none {
+ display: none !important; }
+ .d-md-inline {
+ display: inline !important; }
+ .d-md-inline-block {
+ display: inline-block !important; }
+ .d-md-block {
+ display: block !important; }
+ .d-md-table {
+ display: table !important; }
+ .d-md-table-cell {
+ display: table-cell !important; }
+ .d-md-flex {
+ display: flex !important; }
+ .d-md-inline-flex {
+ display: inline-flex !important; } }
+
+@media (min-width: 992px) {
+ .d-lg-none {
+ display: none !important; }
+ .d-lg-inline {
+ display: inline !important; }
+ .d-lg-inline-block {
+ display: inline-block !important; }
+ .d-lg-block {
+ display: block !important; }
+ .d-lg-table {
+ display: table !important; }
+ .d-lg-table-cell {
+ display: table-cell !important; }
+ .d-lg-flex {
+ display: flex !important; }
+ .d-lg-inline-flex {
+ display: inline-flex !important; } }
+
+@media (min-width: 1200px) {
+ .d-xl-none {
+ display: none !important; }
+ .d-xl-inline {
+ display: inline !important; }
+ .d-xl-inline-block {
+ display: inline-block !important; }
+ .d-xl-block {
+ display: block !important; }
+ .d-xl-table {
+ display: table !important; }
+ .d-xl-table-cell {
+ display: table-cell !important; }
+ .d-xl-flex {
+ display: flex !important; }
+ .d-xl-inline-flex {
+ display: inline-flex !important; } }
+
+.flex-first {
+ order: -1; }
+
+.flex-last {
+ order: 1; }
+
+.flex-unordered {
+ order: 0; }
+
+.flex-row {
+ flex-direction: row !important; }
+
+.flex-column {
+ flex-direction: column !important; }
+
+.flex-row-reverse {
+ flex-direction: row-reverse !important; }
+
+.flex-column-reverse {
+ flex-direction: column-reverse !important; }
+
+.flex-wrap {
+ flex-wrap: wrap !important; }
+
+.flex-nowrap {
+ flex-wrap: nowrap !important; }
+
+.flex-wrap-reverse {
+ flex-wrap: wrap-reverse !important; }
+
+.justify-content-start {
+ justify-content: flex-start !important; }
+
+.justify-content-end {
+ justify-content: flex-end !important; }
+
+.justify-content-center {
+ justify-content: center !important; }
+
+.justify-content-between {
+ justify-content: space-between !important; }
+
+.justify-content-around {
+ justify-content: space-around !important; }
+
+.align-items-start {
+ align-items: flex-start !important; }
+
+.align-items-end {
+ align-items: flex-end !important; }
+
+.align-items-center {
+ align-items: center !important; }
+
+.align-items-baseline {
+ align-items: baseline !important; }
+
+.align-items-stretch {
+ align-items: stretch !important; }
+
+.align-content-start {
+ align-content: flex-start !important; }
+
+.align-content-end {
+ align-content: flex-end !important; }
+
+.align-content-center {
+ align-content: center !important; }
+
+.align-content-between {
+ align-content: space-between !important; }
+
+.align-content-around {
+ align-content: space-around !important; }
+
+.align-content-stretch {
+ align-content: stretch !important; }
+
+.align-self-auto {
+ align-self: auto !important; }
+
+.align-self-start {
+ align-self: flex-start !important; }
+
+.align-self-end {
+ align-self: flex-end !important; }
+
+.align-self-center {
+ align-self: center !important; }
+
+.align-self-baseline {
+ align-self: baseline !important; }
+
+.align-self-stretch {
+ align-self: stretch !important; }
+
+@media (min-width: 576px) {
+ .flex-sm-first {
+ order: -1; }
+ .flex-sm-last {
+ order: 1; }
+ .flex-sm-unordered {
+ order: 0; }
+ .flex-sm-row {
+ flex-direction: row !important; }
+ .flex-sm-column {
+ flex-direction: column !important; }
+ .flex-sm-row-reverse {
+ flex-direction: row-reverse !important; }
+ .flex-sm-column-reverse {
+ flex-direction: column-reverse !important; }
+ .flex-sm-wrap {
+ flex-wrap: wrap !important; }
+ .flex-sm-nowrap {
+ flex-wrap: nowrap !important; }
+ .flex-sm-wrap-reverse {
+ flex-wrap: wrap-reverse !important; }
+ .justify-content-sm-start {
+ justify-content: flex-start !important; }
+ .justify-content-sm-end {
+ justify-content: flex-end !important; }
+ .justify-content-sm-center {
+ justify-content: center !important; }
+ .justify-content-sm-between {
+ justify-content: space-between !important; }
+ .justify-content-sm-around {
+ justify-content: space-around !important; }
+ .align-items-sm-start {
+ align-items: flex-start !important; }
+ .align-items-sm-end {
+ align-items: flex-end !important; }
+ .align-items-sm-center {
+ align-items: center !important; }
+ .align-items-sm-baseline {
+ align-items: baseline !important; }
+ .align-items-sm-stretch {
+ align-items: stretch !important; }
+ .align-content-sm-start {
+ align-content: flex-start !important; }
+ .align-content-sm-end {
+ align-content: flex-end !important; }
+ .align-content-sm-center {
+ align-content: center !important; }
+ .align-content-sm-between {
+ align-content: space-between !important; }
+ .align-content-sm-around {
+ align-content: space-around !important; }
+ .align-content-sm-stretch {
+ align-content: stretch !important; }
+ .align-self-sm-auto {
+ align-self: auto !important; }
+ .align-self-sm-start {
+ align-self: flex-start !important; }
+ .align-self-sm-end {
+ align-self: flex-end !important; }
+ .align-self-sm-center {
+ align-self: center !important; }
+ .align-self-sm-baseline {
+ align-self: baseline !important; }
+ .align-self-sm-stretch {
+ align-self: stretch !important; } }
+
+@media (min-width: 768px) {
+ .flex-md-first {
+ order: -1; }
+ .flex-md-last {
+ order: 1; }
+ .flex-md-unordered {
+ order: 0; }
+ .flex-md-row {
+ flex-direction: row !important; }
+ .flex-md-column {
+ flex-direction: column !important; }
+ .flex-md-row-reverse {
+ flex-direction: row-reverse !important; }
+ .flex-md-column-reverse {
+ flex-direction: column-reverse !important; }
+ .flex-md-wrap {
+ flex-wrap: wrap !important; }
+ .flex-md-nowrap {
+ flex-wrap: nowrap !important; }
+ .flex-md-wrap-reverse {
+ flex-wrap: wrap-reverse !important; }
+ .justify-content-md-start {
+ justify-content: flex-start !important; }
+ .justify-content-md-end {
+ justify-content: flex-end !important; }
+ .justify-content-md-center {
+ justify-content: center !important; }
+ .justify-content-md-between {
+ justify-content: space-between !important; }
+ .justify-content-md-around {
+ justify-content: space-around !important; }
+ .align-items-md-start {
+ align-items: flex-start !important; }
+ .align-items-md-end {
+ align-items: flex-end !important; }
+ .align-items-md-center {
+ align-items: center !important; }
+ .align-items-md-baseline {
+ align-items: baseline !important; }
+ .align-items-md-stretch {
+ align-items: stretch !important; }
+ .align-content-md-start {
+ align-content: flex-start !important; }
+ .align-content-md-end {
+ align-content: flex-end !important; }
+ .align-content-md-center {
+ align-content: center !important; }
+ .align-content-md-between {
+ align-content: space-between !important; }
+ .align-content-md-around {
+ align-content: space-around !important; }
+ .align-content-md-stretch {
+ align-content: stretch !important; }
+ .align-self-md-auto {
+ align-self: auto !important; }
+ .align-self-md-start {
+ align-self: flex-start !important; }
+ .align-self-md-end {
+ align-self: flex-end !important; }
+ .align-self-md-center {
+ align-self: center !important; }
+ .align-self-md-baseline {
+ align-self: baseline !important; }
+ .align-self-md-stretch {
+ align-self: stretch !important; } }
+
+@media (min-width: 992px) {
+ .flex-lg-first {
+ order: -1; }
+ .flex-lg-last {
+ order: 1; }
+ .flex-lg-unordered {
+ order: 0; }
+ .flex-lg-row {
+ flex-direction: row !important; }
+ .flex-lg-column {
+ flex-direction: column !important; }
+ .flex-lg-row-reverse {
+ flex-direction: row-reverse !important; }
+ .flex-lg-column-reverse {
+ flex-direction: column-reverse !important; }
+ .flex-lg-wrap {
+ flex-wrap: wrap !important; }
+ .flex-lg-nowrap {
+ flex-wrap: nowrap !important; }
+ .flex-lg-wrap-reverse {
+ flex-wrap: wrap-reverse !important; }
+ .justify-content-lg-start {
+ justify-content: flex-start !important; }
+ .justify-content-lg-end {
+ justify-content: flex-end !important; }
+ .justify-content-lg-center {
+ justify-content: center !important; }
+ .justify-content-lg-between {
+ justify-content: space-between !important; }
+ .justify-content-lg-around {
+ justify-content: space-around !important; }
+ .align-items-lg-start {
+ align-items: flex-start !important; }
+ .align-items-lg-end {
+ align-items: flex-end !important; }
+ .align-items-lg-center {
+ align-items: center !important; }
+ .align-items-lg-baseline {
+ align-items: baseline !important; }
+ .align-items-lg-stretch {
+ align-items: stretch !important; }
+ .align-content-lg-start {
+ align-content: flex-start !important; }
+ .align-content-lg-end {
+ align-content: flex-end !important; }
+ .align-content-lg-center {
+ align-content: center !important; }
+ .align-content-lg-between {
+ align-content: space-between !important; }
+ .align-content-lg-around {
+ align-content: space-around !important; }
+ .align-content-lg-stretch {
+ align-content: stretch !important; }
+ .align-self-lg-auto {
+ align-self: auto !important; }
+ .align-self-lg-start {
+ align-self: flex-start !important; }
+ .align-self-lg-end {
+ align-self: flex-end !important; }
+ .align-self-lg-center {
+ align-self: center !important; }
+ .align-self-lg-baseline {
+ align-self: baseline !important; }
+ .align-self-lg-stretch {
+ align-self: stretch !important; } }
+
+@media (min-width: 1200px) {
+ .flex-xl-first {
+ order: -1; }
+ .flex-xl-last {
+ order: 1; }
+ .flex-xl-unordered {
+ order: 0; }
+ .flex-xl-row {
+ flex-direction: row !important; }
+ .flex-xl-column {
+ flex-direction: column !important; }
+ .flex-xl-row-reverse {
+ flex-direction: row-reverse !important; }
+ .flex-xl-column-reverse {
+ flex-direction: column-reverse !important; }
+ .flex-xl-wrap {
+ flex-wrap: wrap !important; }
+ .flex-xl-nowrap {
+ flex-wrap: nowrap !important; }
+ .flex-xl-wrap-reverse {
+ flex-wrap: wrap-reverse !important; }
+ .justify-content-xl-start {
+ justify-content: flex-start !important; }
+ .justify-content-xl-end {
+ justify-content: flex-end !important; }
+ .justify-content-xl-center {
+ justify-content: center !important; }
+ .justify-content-xl-between {
+ justify-content: space-between !important; }
+ .justify-content-xl-around {
+ justify-content: space-around !important; }
+ .align-items-xl-start {
+ align-items: flex-start !important; }
+ .align-items-xl-end {
+ align-items: flex-end !important; }
+ .align-items-xl-center {
+ align-items: center !important; }
+ .align-items-xl-baseline {
+ align-items: baseline !important; }
+ .align-items-xl-stretch {
+ align-items: stretch !important; }
+ .align-content-xl-start {
+ align-content: flex-start !important; }
+ .align-content-xl-end {
+ align-content: flex-end !important; }
+ .align-content-xl-center {
+ align-content: center !important; }
+ .align-content-xl-between {
+ align-content: space-between !important; }
+ .align-content-xl-around {
+ align-content: space-around !important; }
+ .align-content-xl-stretch {
+ align-content: stretch !important; }
+ .align-self-xl-auto {
+ align-self: auto !important; }
+ .align-self-xl-start {
+ align-self: flex-start !important; }
+ .align-self-xl-end {
+ align-self: flex-end !important; }
+ .align-self-xl-center {
+ align-self: center !important; }
+ .align-self-xl-baseline {
+ align-self: baseline !important; }
+ .align-self-xl-stretch {
+ align-self: stretch !important; } }
+
+.float-left {
+ float: left !important; }
+
+.float-right {
+ float: right !important; }
+
+.float-none {
+ float: none !important; }
+
+@media (min-width: 576px) {
+ .float-sm-left {
+ float: left !important; }
+ .float-sm-right {
+ float: right !important; }
+ .float-sm-none {
+ float: none !important; } }
+
+@media (min-width: 768px) {
+ .float-md-left {
+ float: left !important; }
+ .float-md-right {
+ float: right !important; }
+ .float-md-none {
+ float: none !important; } }
+
+@media (min-width: 992px) {
+ .float-lg-left {
+ float: left !important; }
+ .float-lg-right {
+ float: right !important; }
+ .float-lg-none {
+ float: none !important; } }
+
+@media (min-width: 1200px) {
+ .float-xl-left {
+ float: left !important; }
+ .float-xl-right {
+ float: right !important; }
+ .float-xl-none {
+ float: none !important; } }
+
+.fixed-top {
+ position: fixed;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: 1030; }
+
+.fixed-bottom {
+ position: fixed;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1030; }
+
+.sticky-top {
+ position: sticky;
+ top: 0;
+ z-index: 1030; }
+
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0; }
+
+.sr-only-focusable:active, .sr-only-focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ clip: auto; }
+
+.w-25 {
+ width: 25% !important; }
+
+.w-50 {
+ width: 50% !important; }
+
+.w-75 {
+ width: 75% !important; }
+
+.w-100 {
+ width: 100% !important; }
+
+.h-25 {
+ height: 25% !important; }
+
+.h-50 {
+ height: 50% !important; }
+
+.h-75 {
+ height: 75% !important; }
+
+.h-100 {
+ height: 100% !important; }
+
+.mw-100 {
+ max-width: 100% !important; }
+
+.mh-100 {
+ max-height: 100% !important; }
+
+.m-0 {
+ margin: 0 0 !important; }
+
+.mt-0 {
+ margin-top: 0 !important; }
+
+.mr-0 {
+ margin-right: 0 !important; }
+
+.mb-0 {
+ margin-bottom: 0 !important; }
+
+.ml-0 {
+ margin-left: 0 !important; }
+
+.mx-0 {
+ margin-right: 0 !important;
+ margin-left: 0 !important; }
+
+.my-0 {
+ margin-top: 0 !important;
+ margin-bottom: 0 !important; }
+
+.m-1 {
+ margin: 0.25rem 0.25rem !important; }
+
+.mt-1 {
+ margin-top: 0.25rem !important; }
+
+.mr-1 {
+ margin-right: 0.25rem !important; }
+
+.mb-1 {
+ margin-bottom: 0.25rem !important; }
+
+.ml-1 {
+ margin-left: 0.25rem !important; }
+
+.mx-1 {
+ margin-right: 0.25rem !important;
+ margin-left: 0.25rem !important; }
+
+.my-1 {
+ margin-top: 0.25rem !important;
+ margin-bottom: 0.25rem !important; }
+
+.m-2 {
+ margin: 0.5rem 0.5rem !important; }
+
+.mt-2 {
+ margin-top: 0.5rem !important; }
+
+.mr-2 {
+ margin-right: 0.5rem !important; }
+
+.mb-2 {
+ margin-bottom: 0.5rem !important; }
+
+.ml-2 {
+ margin-left: 0.5rem !important; }
+
+.mx-2 {
+ margin-right: 0.5rem !important;
+ margin-left: 0.5rem !important; }
+
+.my-2 {
+ margin-top: 0.5rem !important;
+ margin-bottom: 0.5rem !important; }
+
+.m-3 {
+ margin: 1rem 1rem !important; }
+
+.mt-3 {
+ margin-top: 1rem !important; }
+
+.mr-3 {
+ margin-right: 1rem !important; }
+
+.mb-3 {
+ margin-bottom: 1rem !important; }
+
+.ml-3 {
+ margin-left: 1rem !important; }
+
+.mx-3 {
+ margin-right: 1rem !important;
+ margin-left: 1rem !important; }
+
+.my-3 {
+ margin-top: 1rem !important;
+ margin-bottom: 1rem !important; }
+
+.m-4 {
+ margin: 1.5rem 1.5rem !important; }
+
+.mt-4 {
+ margin-top: 1.5rem !important; }
+
+.mr-4 {
+ margin-right: 1.5rem !important; }
+
+.mb-4 {
+ margin-bottom: 1.5rem !important; }
+
+.ml-4 {
+ margin-left: 1.5rem !important; }
+
+.mx-4 {
+ margin-right: 1.5rem !important;
+ margin-left: 1.5rem !important; }
+
+.my-4 {
+ margin-top: 1.5rem !important;
+ margin-bottom: 1.5rem !important; }
+
+.m-5 {
+ margin: 3rem 3rem !important; }
+
+.mt-5 {
+ margin-top: 3rem !important; }
+
+.mr-5 {
+ margin-right: 3rem !important; }
+
+.mb-5 {
+ margin-bottom: 3rem !important; }
+
+.ml-5 {
+ margin-left: 3rem !important; }
+
+.mx-5 {
+ margin-right: 3rem !important;
+ margin-left: 3rem !important; }
+
+.my-5 {
+ margin-top: 3rem !important;
+ margin-bottom: 3rem !important; }
+
+.p-0 {
+ padding: 0 0 !important; }
+
+.pt-0 {
+ padding-top: 0 !important; }
+
+.pr-0 {
+ padding-right: 0 !important; }
+
+.pb-0 {
+ padding-bottom: 0 !important; }
+
+.pl-0 {
+ padding-left: 0 !important; }
+
+.px-0 {
+ padding-right: 0 !important;
+ padding-left: 0 !important; }
+
+.py-0 {
+ padding-top: 0 !important;
+ padding-bottom: 0 !important; }
+
+.p-1 {
+ padding: 0.25rem 0.25rem !important; }
+
+.pt-1 {
+ padding-top: 0.25rem !important; }
+
+.pr-1 {
+ padding-right: 0.25rem !important; }
+
+.pb-1 {
+ padding-bottom: 0.25rem !important; }
+
+.pl-1 {
+ padding-left: 0.25rem !important; }
+
+.px-1 {
+ padding-right: 0.25rem !important;
+ padding-left: 0.25rem !important; }
+
+.py-1 {
+ padding-top: 0.25rem !important;
+ padding-bottom: 0.25rem !important; }
+
+.p-2 {
+ padding: 0.5rem 0.5rem !important; }
+
+.pt-2 {
+ padding-top: 0.5rem !important; }
+
+.pr-2 {
+ padding-right: 0.5rem !important; }
+
+.pb-2 {
+ padding-bottom: 0.5rem !important; }
+
+.pl-2 {
+ padding-left: 0.5rem !important; }
+
+.px-2 {
+ padding-right: 0.5rem !important;
+ padding-left: 0.5rem !important; }
+
+.py-2 {
+ padding-top: 0.5rem !important;
+ padding-bottom: 0.5rem !important; }
+
+.p-3 {
+ padding: 1rem 1rem !important; }
+
+.pt-3 {
+ padding-top: 1rem !important; }
+
+.pr-3 {
+ padding-right: 1rem !important; }
+
+.pb-3 {
+ padding-bottom: 1rem !important; }
+
+.pl-3 {
+ padding-left: 1rem !important; }
+
+.px-3 {
+ padding-right: 1rem !important;
+ padding-left: 1rem !important; }
+
+.py-3 {
+ padding-top: 1rem !important;
+ padding-bottom: 1rem !important; }
+
+.p-4 {
+ padding: 1.5rem 1.5rem !important; }
+
+.pt-4 {
+ padding-top: 1.5rem !important; }
+
+.pr-4 {
+ padding-right: 1.5rem !important; }
+
+.pb-4 {
+ padding-bottom: 1.5rem !important; }
+
+.pl-4 {
+ padding-left: 1.5rem !important; }
+
+.px-4 {
+ padding-right: 1.5rem !important;
+ padding-left: 1.5rem !important; }
+
+.py-4 {
+ padding-top: 1.5rem !important;
+ padding-bottom: 1.5rem !important; }
+
+.p-5 {
+ padding: 3rem 3rem !important; }
+
+.pt-5 {
+ padding-top: 3rem !important; }
+
+.pr-5 {
+ padding-right: 3rem !important; }
+
+.pb-5 {
+ padding-bottom: 3rem !important; }
+
+.pl-5 {
+ padding-left: 3rem !important; }
+
+.px-5 {
+ padding-right: 3rem !important;
+ padding-left: 3rem !important; }
+
+.py-5 {
+ padding-top: 3rem !important;
+ padding-bottom: 3rem !important; }
+
+.m-auto {
+ margin: auto !important; }
+
+.mt-auto {
+ margin-top: auto !important; }
+
+.mr-auto {
+ margin-right: auto !important; }
+
+.mb-auto {
+ margin-bottom: auto !important; }
+
+.ml-auto {
+ margin-left: auto !important; }
+
+.mx-auto {
+ margin-right: auto !important;
+ margin-left: auto !important; }
+
+.my-auto {
+ margin-top: auto !important;
+ margin-bottom: auto !important; }
+
+@media (min-width: 576px) {
+ .m-sm-0 {
+ margin: 0 0 !important; }
+ .mt-sm-0 {
+ margin-top: 0 !important; }
+ .mr-sm-0 {
+ margin-right: 0 !important; }
+ .mb-sm-0 {
+ margin-bottom: 0 !important; }
+ .ml-sm-0 {
+ margin-left: 0 !important; }
+ .mx-sm-0 {
+ margin-right: 0 !important;
+ margin-left: 0 !important; }
+ .my-sm-0 {
+ margin-top: 0 !important;
+ margin-bottom: 0 !important; }
+ .m-sm-1 {
+ margin: 0.25rem 0.25rem !important; }
+ .mt-sm-1 {
+ margin-top: 0.25rem !important; }
+ .mr-sm-1 {
+ margin-right: 0.25rem !important; }
+ .mb-sm-1 {
+ margin-bottom: 0.25rem !important; }
+ .ml-sm-1 {
+ margin-left: 0.25rem !important; }
+ .mx-sm-1 {
+ margin-right: 0.25rem !important;
+ margin-left: 0.25rem !important; }
+ .my-sm-1 {
+ margin-top: 0.25rem !important;
+ margin-bottom: 0.25rem !important; }
+ .m-sm-2 {
+ margin: 0.5rem 0.5rem !important; }
+ .mt-sm-2 {
+ margin-top: 0.5rem !important; }
+ .mr-sm-2 {
+ margin-right: 0.5rem !important; }
+ .mb-sm-2 {
+ margin-bottom: 0.5rem !important; }
+ .ml-sm-2 {
+ margin-left: 0.5rem !important; }
+ .mx-sm-2 {
+ margin-right: 0.5rem !important;
+ margin-left: 0.5rem !important; }
+ .my-sm-2 {
+ margin-top: 0.5rem !important;
+ margin-bottom: 0.5rem !important; }
+ .m-sm-3 {
+ margin: 1rem 1rem !important; }
+ .mt-sm-3 {
+ margin-top: 1rem !important; }
+ .mr-sm-3 {
+ margin-right: 1rem !important; }
+ .mb-sm-3 {
+ margin-bottom: 1rem !important; }
+ .ml-sm-3 {
+ margin-left: 1rem !important; }
+ .mx-sm-3 {
+ margin-right: 1rem !important;
+ margin-left: 1rem !important; }
+ .my-sm-3 {
+ margin-top: 1rem !important;
+ margin-bottom: 1rem !important; }
+ .m-sm-4 {
+ margin: 1.5rem 1.5rem !important; }
+ .mt-sm-4 {
+ margin-top: 1.5rem !important; }
+ .mr-sm-4 {
+ margin-right: 1.5rem !important; }
+ .mb-sm-4 {
+ margin-bottom: 1.5rem !important; }
+ .ml-sm-4 {
+ margin-left: 1.5rem !important; }
+ .mx-sm-4 {
+ margin-right: 1.5rem !important;
+ margin-left: 1.5rem !important; }
+ .my-sm-4 {
+ margin-top: 1.5rem !important;
+ margin-bottom: 1.5rem !important; }
+ .m-sm-5 {
+ margin: 3rem 3rem !important; }
+ .mt-sm-5 {
+ margin-top: 3rem !important; }
+ .mr-sm-5 {
+ margin-right: 3rem !important; }
+ .mb-sm-5 {
+ margin-bottom: 3rem !important; }
+ .ml-sm-5 {
+ margin-left: 3rem !important; }
+ .mx-sm-5 {
+ margin-right: 3rem !important;
+ margin-left: 3rem !important; }
+ .my-sm-5 {
+ margin-top: 3rem !important;
+ margin-bottom: 3rem !important; }
+ .p-sm-0 {
+ padding: 0 0 !important; }
+ .pt-sm-0 {
+ padding-top: 0 !important; }
+ .pr-sm-0 {
+ padding-right: 0 !important; }
+ .pb-sm-0 {
+ padding-bottom: 0 !important; }
+ .pl-sm-0 {
+ padding-left: 0 !important; }
+ .px-sm-0 {
+ padding-right: 0 !important;
+ padding-left: 0 !important; }
+ .py-sm-0 {
+ padding-top: 0 !important;
+ padding-bottom: 0 !important; }
+ .p-sm-1 {
+ padding: 0.25rem 0.25rem !important; }
+ .pt-sm-1 {
+ padding-top: 0.25rem !important; }
+ .pr-sm-1 {
+ padding-right: 0.25rem !important; }
+ .pb-sm-1 {
+ padding-bottom: 0.25rem !important; }
+ .pl-sm-1 {
+ padding-left: 0.25rem !important; }
+ .px-sm-1 {
+ padding-right: 0.25rem !important;
+ padding-left: 0.25rem !important; }
+ .py-sm-1 {
+ padding-top: 0.25rem !important;
+ padding-bottom: 0.25rem !important; }
+ .p-sm-2 {
+ padding: 0.5rem 0.5rem !important; }
+ .pt-sm-2 {
+ padding-top: 0.5rem !important; }
+ .pr-sm-2 {
+ padding-right: 0.5rem !important; }
+ .pb-sm-2 {
+ padding-bottom: 0.5rem !important; }
+ .pl-sm-2 {
+ padding-left: 0.5rem !important; }
+ .px-sm-2 {
+ padding-right: 0.5rem !important;
+ padding-left: 0.5rem !important; }
+ .py-sm-2 {
+ padding-top: 0.5rem !important;
+ padding-bottom: 0.5rem !important; }
+ .p-sm-3 {
+ padding: 1rem 1rem !important; }
+ .pt-sm-3 {
+ padding-top: 1rem !important; }
+ .pr-sm-3 {
+ padding-right: 1rem !important; }
+ .pb-sm-3 {
+ padding-bottom: 1rem !important; }
+ .pl-sm-3 {
+ padding-left: 1rem !important; }
+ .px-sm-3 {
+ padding-right: 1rem !important;
+ padding-left: 1rem !important; }
+ .py-sm-3 {
+ padding-top: 1rem !important;
+ padding-bottom: 1rem !important; }
+ .p-sm-4 {
+ padding: 1.5rem 1.5rem !important; }
+ .pt-sm-4 {
+ padding-top: 1.5rem !important; }
+ .pr-sm-4 {
+ padding-right: 1.5rem !important; }
+ .pb-sm-4 {
+ padding-bottom: 1.5rem !important; }
+ .pl-sm-4 {
+ padding-left: 1.5rem !important; }
+ .px-sm-4 {
+ padding-right: 1.5rem !important;
+ padding-left: 1.5rem !important; }
+ .py-sm-4 {
+ padding-top: 1.5rem !important;
+ padding-bottom: 1.5rem !important; }
+ .p-sm-5 {
+ padding: 3rem 3rem !important; }
+ .pt-sm-5 {
+ padding-top: 3rem !important; }
+ .pr-sm-5 {
+ padding-right: 3rem !important; }
+ .pb-sm-5 {
+ padding-bottom: 3rem !important; }
+ .pl-sm-5 {
+ padding-left: 3rem !important; }
+ .px-sm-5 {
+ padding-right: 3rem !important;
+ padding-left: 3rem !important; }
+ .py-sm-5 {
+ padding-top: 3rem !important;
+ padding-bottom: 3rem !important; }
+ .m-sm-auto {
+ margin: auto !important; }
+ .mt-sm-auto {
+ margin-top: auto !important; }
+ .mr-sm-auto {
+ margin-right: auto !important; }
+ .mb-sm-auto {
+ margin-bottom: auto !important; }
+ .ml-sm-auto {
+ margin-left: auto !important; }
+ .mx-sm-auto {
+ margin-right: auto !important;
+ margin-left: auto !important; }
+ .my-sm-auto {
+ margin-top: auto !important;
+ margin-bottom: auto !important; } }
+
+@media (min-width: 768px) {
+ .m-md-0 {
+ margin: 0 0 !important; }
+ .mt-md-0 {
+ margin-top: 0 !important; }
+ .mr-md-0 {
+ margin-right: 0 !important; }
+ .mb-md-0 {
+ margin-bottom: 0 !important; }
+ .ml-md-0 {
+ margin-left: 0 !important; }
+ .mx-md-0 {
+ margin-right: 0 !important;
+ margin-left: 0 !important; }
+ .my-md-0 {
+ margin-top: 0 !important;
+ margin-bottom: 0 !important; }
+ .m-md-1 {
+ margin: 0.25rem 0.25rem !important; }
+ .mt-md-1 {
+ margin-top: 0.25rem !important; }
+ .mr-md-1 {
+ margin-right: 0.25rem !important; }
+ .mb-md-1 {
+ margin-bottom: 0.25rem !important; }
+ .ml-md-1 {
+ margin-left: 0.25rem !important; }
+ .mx-md-1 {
+ margin-right: 0.25rem !important;
+ margin-left: 0.25rem !important; }
+ .my-md-1 {
+ margin-top: 0.25rem !important;
+ margin-bottom: 0.25rem !important; }
+ .m-md-2 {
+ margin: 0.5rem 0.5rem !important; }
+ .mt-md-2 {
+ margin-top: 0.5rem !important; }
+ .mr-md-2 {
+ margin-right: 0.5rem !important; }
+ .mb-md-2 {
+ margin-bottom: 0.5rem !important; }
+ .ml-md-2 {
+ margin-left: 0.5rem !important; }
+ .mx-md-2 {
+ margin-right: 0.5rem !important;
+ margin-left: 0.5rem !important; }
+ .my-md-2 {
+ margin-top: 0.5rem !important;
+ margin-bottom: 0.5rem !important; }
+ .m-md-3 {
+ margin: 1rem 1rem !important; }
+ .mt-md-3 {
+ margin-top: 1rem !important; }
+ .mr-md-3 {
+ margin-right: 1rem !important; }
+ .mb-md-3 {
+ margin-bottom: 1rem !important; }
+ .ml-md-3 {
+ margin-left: 1rem !important; }
+ .mx-md-3 {
+ margin-right: 1rem !important;
+ margin-left: 1rem !important; }
+ .my-md-3 {
+ margin-top: 1rem !important;
+ margin-bottom: 1rem !important; }
+ .m-md-4 {
+ margin: 1.5rem 1.5rem !important; }
+ .mt-md-4 {
+ margin-top: 1.5rem !important; }
+ .mr-md-4 {
+ margin-right: 1.5rem !important; }
+ .mb-md-4 {
+ margin-bottom: 1.5rem !important; }
+ .ml-md-4 {
+ margin-left: 1.5rem !important; }
+ .mx-md-4 {
+ margin-right: 1.5rem !important;
+ margin-left: 1.5rem !important; }
+ .my-md-4 {
+ margin-top: 1.5rem !important;
+ margin-bottom: 1.5rem !important; }
+ .m-md-5 {
+ margin: 3rem 3rem !important; }
+ .mt-md-5 {
+ margin-top: 3rem !important; }
+ .mr-md-5 {
+ margin-right: 3rem !important; }
+ .mb-md-5 {
+ margin-bottom: 3rem !important; }
+ .ml-md-5 {
+ margin-left: 3rem !important; }
+ .mx-md-5 {
+ margin-right: 3rem !important;
+ margin-left: 3rem !important; }
+ .my-md-5 {
+ margin-top: 3rem !important;
+ margin-bottom: 3rem !important; }
+ .p-md-0 {
+ padding: 0 0 !important; }
+ .pt-md-0 {
+ padding-top: 0 !important; }
+ .pr-md-0 {
+ padding-right: 0 !important; }
+ .pb-md-0 {
+ padding-bottom: 0 !important; }
+ .pl-md-0 {
+ padding-left: 0 !important; }
+ .px-md-0 {
+ padding-right: 0 !important;
+ padding-left: 0 !important; }
+ .py-md-0 {
+ padding-top: 0 !important;
+ padding-bottom: 0 !important; }
+ .p-md-1 {
+ padding: 0.25rem 0.25rem !important; }
+ .pt-md-1 {
+ padding-top: 0.25rem !important; }
+ .pr-md-1 {
+ padding-right: 0.25rem !important; }
+ .pb-md-1 {
+ padding-bottom: 0.25rem !important; }
+ .pl-md-1 {
+ padding-left: 0.25rem !important; }
+ .px-md-1 {
+ padding-right: 0.25rem !important;
+ padding-left: 0.25rem !important; }
+ .py-md-1 {
+ padding-top: 0.25rem !important;
+ padding-bottom: 0.25rem !important; }
+ .p-md-2 {
+ padding: 0.5rem 0.5rem !important; }
+ .pt-md-2 {
+ padding-top: 0.5rem !important; }
+ .pr-md-2 {
+ padding-right: 0.5rem !important; }
+ .pb-md-2 {
+ padding-bottom: 0.5rem !important; }
+ .pl-md-2 {
+ padding-left: 0.5rem !important; }
+ .px-md-2 {
+ padding-right: 0.5rem !important;
+ padding-left: 0.5rem !important; }
+ .py-md-2 {
+ padding-top: 0.5rem !important;
+ padding-bottom: 0.5rem !important; }
+ .p-md-3 {
+ padding: 1rem 1rem !important; }
+ .pt-md-3 {
+ padding-top: 1rem !important; }
+ .pr-md-3 {
+ padding-right: 1rem !important; }
+ .pb-md-3 {
+ padding-bottom: 1rem !important; }
+ .pl-md-3 {
+ padding-left: 1rem !important; }
+ .px-md-3 {
+ padding-right: 1rem !important;
+ padding-left: 1rem !important; }
+ .py-md-3 {
+ padding-top: 1rem !important;
+ padding-bottom: 1rem !important; }
+ .p-md-4 {
+ padding: 1.5rem 1.5rem !important; }
+ .pt-md-4 {
+ padding-top: 1.5rem !important; }
+ .pr-md-4 {
+ padding-right: 1.5rem !important; }
+ .pb-md-4 {
+ padding-bottom: 1.5rem !important; }
+ .pl-md-4 {
+ padding-left: 1.5rem !important; }
+ .px-md-4 {
+ padding-right: 1.5rem !important;
+ padding-left: 1.5rem !important; }
+ .py-md-4 {
+ padding-top: 1.5rem !important;
+ padding-bottom: 1.5rem !important; }
+ .p-md-5 {
+ padding: 3rem 3rem !important; }
+ .pt-md-5 {
+ padding-top: 3rem !important; }
+ .pr-md-5 {
+ padding-right: 3rem !important; }
+ .pb-md-5 {
+ padding-bottom: 3rem !important; }
+ .pl-md-5 {
+ padding-left: 3rem !important; }
+ .px-md-5 {
+ padding-right: 3rem !important;
+ padding-left: 3rem !important; }
+ .py-md-5 {
+ padding-top: 3rem !important;
+ padding-bottom: 3rem !important; }
+ .m-md-auto {
+ margin: auto !important; }
+ .mt-md-auto {
+ margin-top: auto !important; }
+ .mr-md-auto {
+ margin-right: auto !important; }
+ .mb-md-auto {
+ margin-bottom: auto !important; }
+ .ml-md-auto {
+ margin-left: auto !important; }
+ .mx-md-auto {
+ margin-right: auto !important;
+ margin-left: auto !important; }
+ .my-md-auto {
+ margin-top: auto !important;
+ margin-bottom: auto !important; } }
+
+@media (min-width: 992px) {
+ .m-lg-0 {
+ margin: 0 0 !important; }
+ .mt-lg-0 {
+ margin-top: 0 !important; }
+ .mr-lg-0 {
+ margin-right: 0 !important; }
+ .mb-lg-0 {
+ margin-bottom: 0 !important; }
+ .ml-lg-0 {
+ margin-left: 0 !important; }
+ .mx-lg-0 {
+ margin-right: 0 !important;
+ margin-left: 0 !important; }
+ .my-lg-0 {
+ margin-top: 0 !important;
+ margin-bottom: 0 !important; }
+ .m-lg-1 {
+ margin: 0.25rem 0.25rem !important; }
+ .mt-lg-1 {
+ margin-top: 0.25rem !important; }
+ .mr-lg-1 {
+ margin-right: 0.25rem !important; }
+ .mb-lg-1 {
+ margin-bottom: 0.25rem !important; }
+ .ml-lg-1 {
+ margin-left: 0.25rem !important; }
+ .mx-lg-1 {
+ margin-right: 0.25rem !important;
+ margin-left: 0.25rem !important; }
+ .my-lg-1 {
+ margin-top: 0.25rem !important;
+ margin-bottom: 0.25rem !important; }
+ .m-lg-2 {
+ margin: 0.5rem 0.5rem !important; }
+ .mt-lg-2 {
+ margin-top: 0.5rem !important; }
+ .mr-lg-2 {
+ margin-right: 0.5rem !important; }
+ .mb-lg-2 {
+ margin-bottom: 0.5rem !important; }
+ .ml-lg-2 {
+ margin-left: 0.5rem !important; }
+ .mx-lg-2 {
+ margin-right: 0.5rem !important;
+ margin-left: 0.5rem !important; }
+ .my-lg-2 {
+ margin-top: 0.5rem !important;
+ margin-bottom: 0.5rem !important; }
+ .m-lg-3 {
+ margin: 1rem 1rem !important; }
+ .mt-lg-3 {
+ margin-top: 1rem !important; }
+ .mr-lg-3 {
+ margin-right: 1rem !important; }
+ .mb-lg-3 {
+ margin-bottom: 1rem !important; }
+ .ml-lg-3 {
+ margin-left: 1rem !important; }
+ .mx-lg-3 {
+ margin-right: 1rem !important;
+ margin-left: 1rem !important; }
+ .my-lg-3 {
+ margin-top: 1rem !important;
+ margin-bottom: 1rem !important; }
+ .m-lg-4 {
+ margin: 1.5rem 1.5rem !important; }
+ .mt-lg-4 {
+ margin-top: 1.5rem !important; }
+ .mr-lg-4 {
+ margin-right: 1.5rem !important; }
+ .mb-lg-4 {
+ margin-bottom: 1.5rem !important; }
+ .ml-lg-4 {
+ margin-left: 1.5rem !important; }
+ .mx-lg-4 {
+ margin-right: 1.5rem !important;
+ margin-left: 1.5rem !important; }
+ .my-lg-4 {
+ margin-top: 1.5rem !important;
+ margin-bottom: 1.5rem !important; }
+ .m-lg-5 {
+ margin: 3rem 3rem !important; }
+ .mt-lg-5 {
+ margin-top: 3rem !important; }
+ .mr-lg-5 {
+ margin-right: 3rem !important; }
+ .mb-lg-5 {
+ margin-bottom: 3rem !important; }
+ .ml-lg-5 {
+ margin-left: 3rem !important; }
+ .mx-lg-5 {
+ margin-right: 3rem !important;
+ margin-left: 3rem !important; }
+ .my-lg-5 {
+ margin-top: 3rem !important;
+ margin-bottom: 3rem !important; }
+ .p-lg-0 {
+ padding: 0 0 !important; }
+ .pt-lg-0 {
+ padding-top: 0 !important; }
+ .pr-lg-0 {
+ padding-right: 0 !important; }
+ .pb-lg-0 {
+ padding-bottom: 0 !important; }
+ .pl-lg-0 {
+ padding-left: 0 !important; }
+ .px-lg-0 {
+ padding-right: 0 !important;
+ padding-left: 0 !important; }
+ .py-lg-0 {
+ padding-top: 0 !important;
+ padding-bottom: 0 !important; }
+ .p-lg-1 {
+ padding: 0.25rem 0.25rem !important; }
+ .pt-lg-1 {
+ padding-top: 0.25rem !important; }
+ .pr-lg-1 {
+ padding-right: 0.25rem !important; }
+ .pb-lg-1 {
+ padding-bottom: 0.25rem !important; }
+ .pl-lg-1 {
+ padding-left: 0.25rem !important; }
+ .px-lg-1 {
+ padding-right: 0.25rem !important;
+ padding-left: 0.25rem !important; }
+ .py-lg-1 {
+ padding-top: 0.25rem !important;
+ padding-bottom: 0.25rem !important; }
+ .p-lg-2 {
+ padding: 0.5rem 0.5rem !important; }
+ .pt-lg-2 {
+ padding-top: 0.5rem !important; }
+ .pr-lg-2 {
+ padding-right: 0.5rem !important; }
+ .pb-lg-2 {
+ padding-bottom: 0.5rem !important; }
+ .pl-lg-2 {
+ padding-left: 0.5rem !important; }
+ .px-lg-2 {
+ padding-right: 0.5rem !important;
+ padding-left: 0.5rem !important; }
+ .py-lg-2 {
+ padding-top: 0.5rem !important;
+ padding-bottom: 0.5rem !important; }
+ .p-lg-3 {
+ padding: 1rem 1rem !important; }
+ .pt-lg-3 {
+ padding-top: 1rem !important; }
+ .pr-lg-3 {
+ padding-right: 1rem !important; }
+ .pb-lg-3 {
+ padding-bottom: 1rem !important; }
+ .pl-lg-3 {
+ padding-left: 1rem !important; }
+ .px-lg-3 {
+ padding-right: 1rem !important;
+ padding-left: 1rem !important; }
+ .py-lg-3 {
+ padding-top: 1rem !important;
+ padding-bottom: 1rem !important; }
+ .p-lg-4 {
+ padding: 1.5rem 1.5rem !important; }
+ .pt-lg-4 {
+ padding-top: 1.5rem !important; }
+ .pr-lg-4 {
+ padding-right: 1.5rem !important; }
+ .pb-lg-4 {
+ padding-bottom: 1.5rem !important; }
+ .pl-lg-4 {
+ padding-left: 1.5rem !important; }
+ .px-lg-4 {
+ padding-right: 1.5rem !important;
+ padding-left: 1.5rem !important; }
+ .py-lg-4 {
+ padding-top: 1.5rem !important;
+ padding-bottom: 1.5rem !important; }
+ .p-lg-5 {
+ padding: 3rem 3rem !important; }
+ .pt-lg-5 {
+ padding-top: 3rem !important; }
+ .pr-lg-5 {
+ padding-right: 3rem !important; }
+ .pb-lg-5 {
+ padding-bottom: 3rem !important; }
+ .pl-lg-5 {
+ padding-left: 3rem !important; }
+ .px-lg-5 {
+ padding-right: 3rem !important;
+ padding-left: 3rem !important; }
+ .py-lg-5 {
+ padding-top: 3rem !important;
+ padding-bottom: 3rem !important; }
+ .m-lg-auto {
+ margin: auto !important; }
+ .mt-lg-auto {
+ margin-top: auto !important; }
+ .mr-lg-auto {
+ margin-right: auto !important; }
+ .mb-lg-auto {
+ margin-bottom: auto !important; }
+ .ml-lg-auto {
+ margin-left: auto !important; }
+ .mx-lg-auto {
+ margin-right: auto !important;
+ margin-left: auto !important; }
+ .my-lg-auto {
+ margin-top: auto !important;
+ margin-bottom: auto !important; } }
+
+@media (min-width: 1200px) {
+ .m-xl-0 {
+ margin: 0 0 !important; }
+ .mt-xl-0 {
+ margin-top: 0 !important; }
+ .mr-xl-0 {
+ margin-right: 0 !important; }
+ .mb-xl-0 {
+ margin-bottom: 0 !important; }
+ .ml-xl-0 {
+ margin-left: 0 !important; }
+ .mx-xl-0 {
+ margin-right: 0 !important;
+ margin-left: 0 !important; }
+ .my-xl-0 {
+ margin-top: 0 !important;
+ margin-bottom: 0 !important; }
+ .m-xl-1 {
+ margin: 0.25rem 0.25rem !important; }
+ .mt-xl-1 {
+ margin-top: 0.25rem !important; }
+ .mr-xl-1 {
+ margin-right: 0.25rem !important; }
+ .mb-xl-1 {
+ margin-bottom: 0.25rem !important; }
+ .ml-xl-1 {
+ margin-left: 0.25rem !important; }
+ .mx-xl-1 {
+ margin-right: 0.25rem !important;
+ margin-left: 0.25rem !important; }
+ .my-xl-1 {
+ margin-top: 0.25rem !important;
+ margin-bottom: 0.25rem !important; }
+ .m-xl-2 {
+ margin: 0.5rem 0.5rem !important; }
+ .mt-xl-2 {
+ margin-top: 0.5rem !important; }
+ .mr-xl-2 {
+ margin-right: 0.5rem !important; }
+ .mb-xl-2 {
+ margin-bottom: 0.5rem !important; }
+ .ml-xl-2 {
+ margin-left: 0.5rem !important; }
+ .mx-xl-2 {
+ margin-right: 0.5rem !important;
+ margin-left: 0.5rem !important; }
+ .my-xl-2 {
+ margin-top: 0.5rem !important;
+ margin-bottom: 0.5rem !important; }
+ .m-xl-3 {
+ margin: 1rem 1rem !important; }
+ .mt-xl-3 {
+ margin-top: 1rem !important; }
+ .mr-xl-3 {
+ margin-right: 1rem !important; }
+ .mb-xl-3 {
+ margin-bottom: 1rem !important; }
+ .ml-xl-3 {
+ margin-left: 1rem !important; }
+ .mx-xl-3 {
+ margin-right: 1rem !important;
+ margin-left: 1rem !important; }
+ .my-xl-3 {
+ margin-top: 1rem !important;
+ margin-bottom: 1rem !important; }
+ .m-xl-4 {
+ margin: 1.5rem 1.5rem !important; }
+ .mt-xl-4 {
+ margin-top: 1.5rem !important; }
+ .mr-xl-4 {
+ margin-right: 1.5rem !important; }
+ .mb-xl-4 {
+ margin-bottom: 1.5rem !important; }
+ .ml-xl-4 {
+ margin-left: 1.5rem !important; }
+ .mx-xl-4 {
+ margin-right: 1.5rem !important;
+ margin-left: 1.5rem !important; }
+ .my-xl-4 {
+ margin-top: 1.5rem !important;
+ margin-bottom: 1.5rem !important; }
+ .m-xl-5 {
+ margin: 3rem 3rem !important; }
+ .mt-xl-5 {
+ margin-top: 3rem !important; }
+ .mr-xl-5 {
+ margin-right: 3rem !important; }
+ .mb-xl-5 {
+ margin-bottom: 3rem !important; }
+ .ml-xl-5 {
+ margin-left: 3rem !important; }
+ .mx-xl-5 {
+ margin-right: 3rem !important;
+ margin-left: 3rem !important; }
+ .my-xl-5 {
+ margin-top: 3rem !important;
+ margin-bottom: 3rem !important; }
+ .p-xl-0 {
+ padding: 0 0 !important; }
+ .pt-xl-0 {
+ padding-top: 0 !important; }
+ .pr-xl-0 {
+ padding-right: 0 !important; }
+ .pb-xl-0 {
+ padding-bottom: 0 !important; }
+ .pl-xl-0 {
+ padding-left: 0 !important; }
+ .px-xl-0 {
+ padding-right: 0 !important;
+ padding-left: 0 !important; }
+ .py-xl-0 {
+ padding-top: 0 !important;
+ padding-bottom: 0 !important; }
+ .p-xl-1 {
+ padding: 0.25rem 0.25rem !important; }
+ .pt-xl-1 {
+ padding-top: 0.25rem !important; }
+ .pr-xl-1 {
+ padding-right: 0.25rem !important; }
+ .pb-xl-1 {
+ padding-bottom: 0.25rem !important; }
+ .pl-xl-1 {
+ padding-left: 0.25rem !important; }
+ .px-xl-1 {
+ padding-right: 0.25rem !important;
+ padding-left: 0.25rem !important; }
+ .py-xl-1 {
+ padding-top: 0.25rem !important;
+ padding-bottom: 0.25rem !important; }
+ .p-xl-2 {
+ padding: 0.5rem 0.5rem !important; }
+ .pt-xl-2 {
+ padding-top: 0.5rem !important; }
+ .pr-xl-2 {
+ padding-right: 0.5rem !important; }
+ .pb-xl-2 {
+ padding-bottom: 0.5rem !important; }
+ .pl-xl-2 {
+ padding-left: 0.5rem !important; }
+ .px-xl-2 {
+ padding-right: 0.5rem !important;
+ padding-left: 0.5rem !important; }
+ .py-xl-2 {
+ padding-top: 0.5rem !important;
+ padding-bottom: 0.5rem !important; }
+ .p-xl-3 {
+ padding: 1rem 1rem !important; }
+ .pt-xl-3 {
+ padding-top: 1rem !important; }
+ .pr-xl-3 {
+ padding-right: 1rem !important; }
+ .pb-xl-3 {
+ padding-bottom: 1rem !important; }
+ .pl-xl-3 {
+ padding-left: 1rem !important; }
+ .px-xl-3 {
+ padding-right: 1rem !important;
+ padding-left: 1rem !important; }
+ .py-xl-3 {
+ padding-top: 1rem !important;
+ padding-bottom: 1rem !important; }
+ .p-xl-4 {
+ padding: 1.5rem 1.5rem !important; }
+ .pt-xl-4 {
+ padding-top: 1.5rem !important; }
+ .pr-xl-4 {
+ padding-right: 1.5rem !important; }
+ .pb-xl-4 {
+ padding-bottom: 1.5rem !important; }
+ .pl-xl-4 {
+ padding-left: 1.5rem !important; }
+ .px-xl-4 {
+ padding-right: 1.5rem !important;
+ padding-left: 1.5rem !important; }
+ .py-xl-4 {
+ padding-top: 1.5rem !important;
+ padding-bottom: 1.5rem !important; }
+ .p-xl-5 {
+ padding: 3rem 3rem !important; }
+ .pt-xl-5 {
+ padding-top: 3rem !important; }
+ .pr-xl-5 {
+ padding-right: 3rem !important; }
+ .pb-xl-5 {
+ padding-bottom: 3rem !important; }
+ .pl-xl-5 {
+ padding-left: 3rem !important; }
+ .px-xl-5 {
+ padding-right: 3rem !important;
+ padding-left: 3rem !important; }
+ .py-xl-5 {
+ padding-top: 3rem !important;
+ padding-bottom: 3rem !important; }
+ .m-xl-auto {
+ margin: auto !important; }
+ .mt-xl-auto {
+ margin-top: auto !important; }
+ .mr-xl-auto {
+ margin-right: auto !important; }
+ .mb-xl-auto {
+ margin-bottom: auto !important; }
+ .ml-xl-auto {
+ margin-left: auto !important; }
+ .mx-xl-auto {
+ margin-right: auto !important;
+ margin-left: auto !important; }
+ .my-xl-auto {
+ margin-top: auto !important;
+ margin-bottom: auto !important; } }
+
+.text-justify {
+ text-align: justify !important; }
+
+.text-nowrap {
+ white-space: nowrap !important; }
+
+.text-truncate {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap; }
+
+.text-left {
+ text-align: left !important; }
+
+.text-right {
+ text-align: right !important; }
+
+.text-center {
+ text-align: center !important; }
+
+@media (min-width: 576px) {
+ .text-sm-left {
+ text-align: left !important; }
+ .text-sm-right {
+ text-align: right !important; }
+ .text-sm-center {
+ text-align: center !important; } }
+
+@media (min-width: 768px) {
+ .text-md-left {
+ text-align: left !important; }
+ .text-md-right {
+ text-align: right !important; }
+ .text-md-center {
+ text-align: center !important; } }
+
+@media (min-width: 992px) {
+ .text-lg-left {
+ text-align: left !important; }
+ .text-lg-right {
+ text-align: right !important; }
+ .text-lg-center {
+ text-align: center !important; } }
+
+@media (min-width: 1200px) {
+ .text-xl-left {
+ text-align: left !important; }
+ .text-xl-right {
+ text-align: right !important; }
+ .text-xl-center {
+ text-align: center !important; } }
+
+.text-lowercase {
+ text-transform: lowercase !important; }
+
+.text-uppercase {
+ text-transform: uppercase !important; }
+
+.text-capitalize {
+ text-transform: capitalize !important; }
+
+.font-weight-normal {
+ font-weight: normal; }
+
+.font-weight-bold {
+ font-weight: bold; }
+
+.font-italic {
+ font-style: italic; }
+
+.text-white {
+ color: #fff !important; }
+
+.text-muted {
+ color: #636c72 !important; }
+
+a.text-muted:focus, a.text-muted:hover {
+ color: #4b5257 !important; }
+
+.text-primary {
+ color: #026AA7 !important; }
+
+a.text-primary:focus, a.text-primary:hover {
+ color: #014a75 !important; }
+
+.text-success {
+ color: #91C500 !important; }
+
+a.text-success:focus, a.text-success:hover {
+ color: #6b9200 !important; }
+
+.text-info {
+ color: #1E97DF !important; }
+
+a.text-info:focus, a.text-info:hover {
+ color: #1879b2 !important; }
+
+.text-warning {
+ color: #f0ad4e !important; }
+
+a.text-warning:focus, a.text-warning:hover {
+ color: #ec971f !important; }
+
+.text-danger {
+ color: #9804E9 !important; }
+
+a.text-danger:focus, a.text-danger:hover {
+ color: #7703b7 !important; }
+
+.text-gray-dark {
+ color: #292b2c !important; }
+
+a.text-gray-dark:focus, a.text-gray-dark:hover {
+ color: #101112 !important; }
+
+.text-hide {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0; }
+
+.invisible {
+ visibility: hidden !important; }
+
+.hidden-xs-up {
+ display: none !important; }
+
+@media (max-width: 575px) {
+ .hidden-xs-down {
+ display: none !important; } }
+
+@media (min-width: 576px) {
+ .hidden-sm-up {
+ display: none !important; } }
+
+@media (max-width: 767px) {
+ .hidden-sm-down {
+ display: none !important; } }
+
+@media (min-width: 768px) {
+ .hidden-md-up {
+ display: none !important; } }
+
+@media (max-width: 991px) {
+ .hidden-md-down {
+ display: none !important; } }
+
+@media (min-width: 992px) {
+ .hidden-lg-up {
+ display: none !important; } }
+
+@media (max-width: 1199px) {
+ .hidden-lg-down {
+ display: none !important; } }
+
+@media (min-width: 1200px) {
+ .hidden-xl-up {
+ display: none !important; } }
+
+.hidden-xl-down {
+ display: none !important; }
+
+.visible-print-block {
+ display: none !important; }
+ @media print {
+ .visible-print-block {
+ display: block !important; } }
+
+.visible-print-inline {
+ display: none !important; }
+ @media print {
+ .visible-print-inline {
+ display: inline !important; } }
+
+.visible-print-inline-block {
+ display: none !important; }
+ @media print {
+ .visible-print-inline-block {
+ display: inline-block !important; } }
+
+@media print {
+ .hidden-print {
+ display: none !important; } }
diff --git a/client/src/index.js b/client/src/index.js
new file mode 100644
index 00000000..8488bcec
--- /dev/null
+++ b/client/src/index.js
@@ -0,0 +1,25 @@
+import React from "react";
+import { render } from "react-dom";
+import { createStore, applyMiddleware } from "redux";
+import { Provider } from "react-redux";
+import App from "./containers/App";
+import djelloApp from "./reducers/index";
+import thunkMiddleware from "redux-thunk";
+
+import "./index.css";
+
+let createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore);
+
+let store = createStoreWithMiddleware(
+ djelloApp,
+ window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
+);
+
+let rootElement = document.getElementById("root");
+
+render(
+
+
+ ,
+ rootElement
+);
diff --git a/client/src/index.scss b/client/src/index.scss
new file mode 100644
index 00000000..94ce0b6b
--- /dev/null
+++ b/client/src/index.scss
@@ -0,0 +1,2 @@
+@import './_variables.scss';
+@import '../node_modules/bootstrap/scss/bootstrap.scss';
diff --git a/client/src/reducers/authReducer.js b/client/src/reducers/authReducer.js
new file mode 100644
index 00000000..38e05e6d
--- /dev/null
+++ b/client/src/reducers/authReducer.js
@@ -0,0 +1,47 @@
+import {
+ LOGIN_REQUEST,
+ LOGIN_SUCCESS,
+ LOGIN_FAILURE,
+ LOGOUT_SUCCESS
+} from "../actions/auth";
+
+// The auth reducer. The starting state sets authentication
+// based on a token being in local storage. In a real app,
+// we would also want a util to check if the token is expired.
+export default function auth(
+ state = {
+ isFetching: false,
+ isAuthenticated: false,
+ user: null
+ },
+ action
+) {
+ switch (action.type) {
+ case LOGIN_REQUEST:
+ return Object.assign({}, state, {
+ isFetching: true,
+ isAuthenticated: false,
+ user: action.creds
+ });
+ case LOGIN_SUCCESS:
+ return Object.assign({}, state, {
+ isFetching: false,
+ isAuthenticated: true,
+ errorMessage: "",
+ user: { userEmail: action.userEmail, userId: action.userId }
+ });
+ case LOGIN_FAILURE:
+ return Object.assign({}, state, {
+ isFetching: false,
+ isAuthenticated: false,
+ errorMessage: action.message
+ });
+ case LOGOUT_SUCCESS:
+ return Object.assign({}, state, {
+ isFetching: false,
+ isAuthenticated: false
+ });
+ default:
+ return state;
+ }
+}
diff --git a/client/src/reducers/boardsReducer.js b/client/src/reducers/boardsReducer.js
new file mode 100644
index 00000000..7e96e5a7
--- /dev/null
+++ b/client/src/reducers/boardsReducer.js
@@ -0,0 +1,78 @@
+import {
+ GET_BOARDS_SUCCESS,
+ GET_REQUEST,
+ GET_FAILURE,
+ CHANGE_CURRENT_BOARD,
+ CREATE_NEW_BOARD_SUCCESS,
+ DELETE_BOARD_SUCCESS
+} from "../actions/boards";
+
+export default function boards(
+ state = { data: {}, currentBoard: {}, error: null, isFetching: false },
+ action
+) {
+ switch (action.type) {
+ case GET_REQUEST:
+ return {
+ ...state,
+ isFetching: true,
+ error: null
+ };
+ case GET_FAILURE:
+ return {
+ ...state,
+ isFetching: false,
+ error: action.error
+ };
+ case GET_BOARDS_SUCCESS:
+ let currentBoard;
+ if (action.data.boardId) {
+ currentBoard = action.data.json.boards.find(
+ board => board.id === +action.data.boardId
+ );
+ } else {
+ currentBoard = state.currentBoard.name
+ ? state.currentBoard
+ : action.data.json.boards ? action.data.json.boards[0] : {};
+ }
+ return {
+ ...state,
+ isFetching: false,
+ error: null,
+ data: action.data.json,
+ currentBoard
+ };
+ case CHANGE_CURRENT_BOARD:
+ return {
+ ...state,
+ currentBoard: state.data.boards.find(board => board.id === +action.data)
+ };
+ case CREATE_NEW_BOARD_SUCCESS:
+ return {
+ ...state,
+ isFetching: false,
+ data: { ...state.data, boards: [...state.data.boards, action.data] },
+ currentBoard: action.data.board
+ };
+ case DELETE_BOARD_SUCCESS:
+ let currentBoardAfterDelete;
+ if (state.data.boards.length > 1) {
+ currentBoardAfterDelete = state.data.boards.filter(
+ board => board.id !== +action.data
+ )[0];
+ } else {
+ currentBoardAfterDelete = {};
+ }
+ return {
+ ...state,
+ isFetching: false,
+ data: {
+ ...state.data,
+ boards: state.data.boards.filter(board => board.id !== +action.data)
+ },
+ currentBoard: currentBoardAfterDelete
+ };
+ default:
+ return state;
+ }
+}
diff --git a/client/src/reducers/index.js b/client/src/reducers/index.js
new file mode 100644
index 00000000..13ff2d08
--- /dev/null
+++ b/client/src/reducers/index.js
@@ -0,0 +1,13 @@
+import { combineReducers } from "redux";
+import auth from "./authReducer";
+import boards from "./boardsReducer";
+import users from "./usersReducer";
+// We combine the reducers here so that they
+// can be left split apart above
+const djelloApp = combineReducers({
+ auth,
+ boards,
+ users
+});
+
+export default djelloApp;
diff --git a/client/src/reducers/usersReducer.js b/client/src/reducers/usersReducer.js
new file mode 100644
index 00000000..ab52ee9d
--- /dev/null
+++ b/client/src/reducers/usersReducer.js
@@ -0,0 +1,34 @@
+import {
+ GET_USERS_SUCCESS,
+ GET_USERS_REQUEST,
+ GET_USERS_FAILURE
+} from "../actions/users";
+
+export default function users(
+ state = { data: [], isFetching: false, error: null },
+ action
+) {
+ switch (action.type) {
+ case GET_USERS_REQUEST:
+ return {
+ ...state,
+ isFetching: true,
+ error: null
+ };
+ case GET_USERS_FAILURE:
+ return {
+ ...state,
+ isFetching: false,
+ error: action.error
+ };
+ case GET_USERS_SUCCESS:
+ return {
+ ...state,
+ isFetching: false,
+ error: null,
+ data: action.data.users
+ };
+ default:
+ return state;
+ }
+}
diff --git a/client/static.json b/client/static.json
new file mode 100644
index 00000000..5bdee054
--- /dev/null
+++ b/client/static.json
@@ -0,0 +1,11 @@
+{
+ "root": "build/",
+ "routes": {
+ "/**": "index.html"
+ },
+ "headers": {
+ "/**": {
+ "Access-Control-Allow-Origin": "*"
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/.gitignore b/server/.gitignore
new file mode 100644
index 00000000..7af7f047
--- /dev/null
+++ b/server/.gitignore
@@ -0,0 +1,2 @@
+/node_modules
+.env
\ No newline at end of file
diff --git a/server/Procfile b/server/Procfile
new file mode 100644
index 00000000..6f86b16c
--- /dev/null
+++ b/server/Procfile
@@ -0,0 +1 @@
+web: node server.js
\ No newline at end of file
diff --git a/server/auth.js b/server/auth.js
new file mode 100644
index 00000000..87bbaf9f
--- /dev/null
+++ b/server/auth.js
@@ -0,0 +1,34 @@
+var passport = require("passport");
+var passportJWT = require("passport-jwt");
+var ExtractJwt = passportJWT.ExtractJwt;
+var Strategy = passportJWT.Strategy;
+var params = {
+ secretOrKey: process.env.JWT_SECRET,
+ jwtFromRequest: ExtractJwt.fromUrlQueryParameter("token")
+};
+const models = require("./models");
+const User = models.User;
+const sequelize = models.sequelize;
+
+module.exports = function() {
+ var strategy = new Strategy(params, function(payload, done) {
+ User.findById(payload.id).then(user => {
+ if (user) {
+ return done(null, {
+ id: user.id
+ });
+ } else {
+ return done(new Error("User not found"), null);
+ }
+ });
+ });
+ passport.use(strategy);
+ return {
+ initialize: function() {
+ return passport.initialize();
+ },
+ authenticate: function() {
+ return passport.authenticate("jwt", { session: false });
+ }
+ };
+};
diff --git a/server/config/config.json b/server/config/config.json
new file mode 100644
index 00000000..9713f639
--- /dev/null
+++ b/server/config/config.json
@@ -0,0 +1,20 @@
+{
+ "development": {
+ "username": "egle",
+ "password": null,
+ "database": "djello_development",
+ "host": "127.0.0.1",
+ "dialect": "postgres"
+ },
+ "test": {
+ "username": "egle",
+ "password": null,
+ "database": "djello_test",
+ "host": "127.0.0.1",
+ "dialect": "postgres"
+ },
+ "production": {
+ "use_env_variable": "DATABASE_URL",
+ "dialect": "postgres"
+}
+}
\ No newline at end of file
diff --git a/server/db-routes.js b/server/db-routes.js
new file mode 100644
index 00000000..271cf57c
--- /dev/null
+++ b/server/db-routes.js
@@ -0,0 +1,232 @@
+const express = require("express");
+const models = require("./models");
+const User = models.User;
+const Board = models.Board;
+const UsersBoards = models.UsersBoards;
+const UsersCards = models.UsersCards;
+const List = models.List;
+const Card = models.Card;
+const Activity = models.Activity;
+const sequelize = models.sequelize;
+const app = (module.exports = express.Router());
+
+app.get("/boards/:userId", (req, res, next) => {
+ Board.findAll({
+ include: [
+ {
+ model: UsersBoards,
+ where: {
+ userId: req.params.userId
+ },
+
+ include: { model: User, attributes: ["email"] }
+ },
+
+ { model: User, as: "Owner", attributes: ["email"] },
+ {
+ model: List,
+ include: [
+ {
+ model: Card,
+ include: [
+ {
+ model: Activity,
+ include: [{ model: User, as: "Author", attributes: ["email"] }]
+ },
+ {
+ model: UsersCards,
+ include: [{ model: User, attributes: ["email"] }]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ order: [
+ ["name"],
+ [List, "createdAt"],
+ [List, Card, "createdAt"],
+ [List, Card, Activity, "createdAt", "DESC"]
+ ]
+ })
+ .then(boards => {
+ res.send({ boards });
+ })
+ .catch(next);
+});
+
+app.post("/boards/new", (req, res, next) => {
+ let currBoard;
+ Board.create({
+ name: req.body.name,
+ ownerId: +req.body.ownerId
+ })
+ .then(board => {
+ currBoard = board;
+ UsersBoards.create({
+ fixId: +new Date(),
+ userId: currBoard.ownerId,
+ boardId: currBoard.id
+ }).then(board => {
+ res.send({ boardId: currBoard.id });
+ });
+ })
+ .catch(next);
+});
+
+app.delete("/boards/delete/:boardId", (req, res, next) => {
+ Board.destroy({ where: { id: +req.params.boardId }, limit: 1 })
+ .then(() => res.send({ boardId: req.params.boardId }))
+ .catch(next);
+});
+
+app.post("/lists/new", (req, res, next) => {
+ List.create({
+ title: req.body.title,
+ boardId: +req.body.boardId,
+ description: req.body.description === "undefined"
+ ? ""
+ : req.body.description
+ })
+ .then(list => {
+ res.send({ list });
+ })
+ .catch(next);
+});
+
+app.delete("/lists/delete/:listId", (req, res, next) => {
+ List.destroy({ where: { id: +req.params.listId }, limit: 1 })
+ .then(() => res.send({}))
+ .catch(next);
+});
+
+app.put("/lists/update/:listId", (req, res, next) => {
+ List.update(
+ { title: req.body.title, description: req.body.description },
+ { where: { id: +req.params.listId }, limit: 1 }
+ )
+ .then(list => {
+ res.send({});
+ })
+ .catch(next);
+});
+
+app.post("/cards/new", (req, res, next) => {
+ Card.create({
+ title: req.body.title,
+ description: req.body.description,
+ listId: req.body.listId
+ })
+ .then(card => {
+ Activity.create({
+ authorId: req.user.id,
+ cardId: card.id,
+ description: `created this card`
+ });
+ })
+ .then(() => {
+ res.send({});
+ })
+ .catch(next);
+});
+
+app.put("/cards/update/:cardId", (req, res, next) => {
+ Card.update(
+ { title: req.body.title, description: req.body.description },
+ { where: { id: +req.params.cardId }, limit: 1 }
+ )
+ .then(card => {
+ Activity.create({
+ authorId: req.user.id,
+ cardId: +req.params.cardId,
+ description: req.body.name === "title"
+ ? `changed title of this card to "${req.body.title}"`
+ : `changed description of this card to "${req.body.description}"`
+ });
+ })
+ .then(() => {
+ res.send({});
+ })
+ .catch(next);
+});
+
+app.delete("/cards/delete/:cardId", (req, res, next) => {
+ Card.destroy({ where: { id: +req.params.cardId }, limit: 1 })
+ .then(() => res.send({}))
+ .catch(next);
+});
+
+app.get("/users", (req, res, next) => {
+ User.findAll({ attributes: ["email"] })
+ .then(users => {
+ users = users.map(user => user.email);
+ res.send({ users });
+ })
+ .catch(next);
+});
+
+app.post("/cards/member/add/:cardId", (req, res, next) => {
+ let userId;
+ User.findOne({ where: { email: req.body.email } })
+ .then(user => {
+ userId = user.id;
+ UsersCards.create({
+ fixId: +new Date(),
+ memberId: userId,
+ cardId: +req.params.cardId
+ }).then(() => {
+ UsersBoards.findOne({
+ where: { userId: userId, boardId: +req.body.boardId }
+ })
+ .then(usersboard => {
+ if (!usersboard) {
+ UsersBoards.create({
+ fixId: +new Date(),
+ userId: userId,
+ boardId: +req.body.boardId
+ });
+ }
+ })
+ .then(() => {
+ Activity.create({
+ authorId: req.user.id,
+ cardId: +req.params.cardId,
+ description: `added ${req.body.email} to members' list `
+ });
+ })
+ .then(() => {
+ res.send({});
+ });
+ });
+ })
+ .catch(next);
+});
+
+app.delete("/cards/member/delete/:cardId", (req, res, next) => {
+ User.findOne({ where: { email: req.body.email } }).then(user => {
+ UsersCards.destroy({
+ where: { memberId: user.id, cardId: +req.params.cardId },
+ limit: 1
+ })
+ .then(() => {
+ Activity.create({
+ authorId: req.user.id,
+ cardId: +req.params.cardId,
+ description: `removed ${req.body.email} from members' list `
+ });
+ })
+ .then(() => res.send({}))
+ .catch(next);
+ });
+});
+
+// app.get("/test", (req, res) => {
+// Card.findAll({
+// where: { listId: [1, 2] },
+// include: [
+// { model: UsersCards, include: [{ model: User, attributes: ["email"] }] }
+// ]
+// }).then(cards => {
+// res.send({ cards });
+// });
+// });
diff --git a/server/migrations/20170524040301-create-user.js b/server/migrations/20170524040301-create-user.js
new file mode 100644
index 00000000..d507a657
--- /dev/null
+++ b/server/migrations/20170524040301-create-user.js
@@ -0,0 +1,32 @@
+"use strict";
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ return queryInterface.createTable("Users", {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ email: {
+ type: Sequelize.STRING
+ },
+ password: {
+ type: Sequelize.STRING
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ }
+ });
+ },
+ down: function(queryInterface, Sequelize) {
+ return queryInterface.dropTable("Users");
+ }
+};
diff --git a/server/migrations/20170524040314-create-board.js b/server/migrations/20170524040314-create-board.js
new file mode 100644
index 00000000..8635eab6
--- /dev/null
+++ b/server/migrations/20170524040314-create-board.js
@@ -0,0 +1,32 @@
+"use strict";
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ return queryInterface.createTable("Boards", {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ name: {
+ type: Sequelize.STRING
+ },
+ ownerId: {
+ type: Sequelize.INTEGER
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ }
+ });
+ },
+ down: function(queryInterface, Sequelize) {
+ return queryInterface.dropTable("Boards");
+ }
+};
diff --git a/server/migrations/20170524040319-create-users-boards.js b/server/migrations/20170524040319-create-users-boards.js
new file mode 100644
index 00000000..83f793f9
--- /dev/null
+++ b/server/migrations/20170524040319-create-users-boards.js
@@ -0,0 +1,37 @@
+"use strict";
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ return queryInterface.createTable("UsersBoards", {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ type: Sequelize.INTEGER
+ },
+ fixId: {
+ primaryKey: true,
+ type: Sequelize.BIGINT
+ },
+ userId: {
+ type: Sequelize.INTEGER,
+ unique: false
+ },
+ boardId: {
+ type: Sequelize.INTEGER,
+ unique: false
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ }
+ });
+ },
+ down: function(queryInterface, Sequelize) {
+ return queryInterface.dropTable("UsersBoards");
+ }
+};
diff --git a/server/migrations/20170524040323-create-list.js b/server/migrations/20170524040323-create-list.js
new file mode 100644
index 00000000..46028188
--- /dev/null
+++ b/server/migrations/20170524040323-create-list.js
@@ -0,0 +1,35 @@
+"use strict";
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ return queryInterface.createTable("Lists", {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ boardId: {
+ type: Sequelize.INTEGER
+ },
+ title: {
+ type: Sequelize.STRING
+ },
+ description: {
+ type: Sequelize.STRING
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ }
+ });
+ },
+ down: function(queryInterface, Sequelize) {
+ return queryInterface.dropTable("Lists");
+ }
+};
diff --git a/server/migrations/20170524040327-create-card.js b/server/migrations/20170524040327-create-card.js
new file mode 100644
index 00000000..1dd6f6a8
--- /dev/null
+++ b/server/migrations/20170524040327-create-card.js
@@ -0,0 +1,35 @@
+"use strict";
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ return queryInterface.createTable("Cards", {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ listId: {
+ type: Sequelize.INTEGER
+ },
+ title: {
+ type: Sequelize.STRING
+ },
+ description: {
+ type: Sequelize.STRING
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ }
+ });
+ },
+ down: function(queryInterface, Sequelize) {
+ return queryInterface.dropTable("Cards");
+ }
+};
diff --git a/server/migrations/20170524040332-create-users-cards.js b/server/migrations/20170524040332-create-users-cards.js
new file mode 100644
index 00000000..b53b3aa1
--- /dev/null
+++ b/server/migrations/20170524040332-create-users-cards.js
@@ -0,0 +1,37 @@
+"use strict";
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ return queryInterface.createTable("UsersCards", {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ type: Sequelize.INTEGER
+ },
+ fixId: {
+ primaryKey: true,
+ type: Sequelize.BIGINT
+ },
+ memberId: {
+ type: Sequelize.INTEGER,
+ unique: false
+ },
+ cardId: {
+ type: Sequelize.INTEGER,
+ unique: false
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ }
+ });
+ },
+ down: function(queryInterface, Sequelize) {
+ return queryInterface.dropTable("UsersCards");
+ }
+};
diff --git a/server/migrations/20170524040337-create-activity.js b/server/migrations/20170524040337-create-activity.js
new file mode 100644
index 00000000..a22252f9
--- /dev/null
+++ b/server/migrations/20170524040337-create-activity.js
@@ -0,0 +1,35 @@
+"use strict";
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ return queryInterface.createTable("Activities", {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ authorId: {
+ type: Sequelize.INTEGER
+ },
+ cardId: {
+ type: Sequelize.INTEGER
+ },
+ description: {
+ type: Sequelize.STRING
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.fn("NOW")
+ }
+ });
+ },
+ down: function(queryInterface, Sequelize) {
+ return queryInterface.dropTable("Activities");
+ }
+};
diff --git a/server/models/activity.js b/server/models/activity.js
new file mode 100644
index 00000000..9c0fa415
--- /dev/null
+++ b/server/models/activity.js
@@ -0,0 +1,26 @@
+"use strict";
+module.exports = function(sequelize, DataTypes) {
+ var Activity = sequelize.define(
+ "Activity",
+ {
+ authorId: DataTypes.INTEGER,
+ cardId: DataTypes.INTEGER,
+ description: DataTypes.STRING
+ },
+ {
+ classMethods: {
+ associate: function(models) {
+ // associations can be defined here
+ Activity.belongsTo(models.Card, {
+ foreignKey: "cardId"
+ });
+ Activity.belongsTo(models.User, {
+ foreignKey: "authorId",
+ as: "Author"
+ });
+ }
+ }
+ }
+ );
+ return Activity;
+};
diff --git a/server/models/board.js b/server/models/board.js
new file mode 100644
index 00000000..3fb046aa
--- /dev/null
+++ b/server/models/board.js
@@ -0,0 +1,33 @@
+"use strict";
+module.exports = function(sequelize, DataTypes) {
+ var Board = sequelize.define(
+ "Board",
+ {
+ name: DataTypes.STRING,
+ ownerId: DataTypes.INTEGER
+ },
+ {
+ classMethods: {
+ associate: function(models) {
+ // associations can be defined here
+ Board.hasMany(models.UsersBoards, {
+ foreignKey: "boardId"
+ });
+ Board.belongsToMany(models.User, {
+ through: models.UsersBoards,
+ unique: false,
+ as: "MemberOfBoard",
+ constraints: false,
+ foreignKey: "boardId"
+ });
+ Board.belongsTo(models.User, {
+ foreignKey: "ownerId",
+ as: "Owner"
+ });
+ Board.hasMany(models.List, { foreignKey: "boardId" });
+ }
+ }
+ }
+ );
+ return Board;
+};
diff --git a/server/models/card.js b/server/models/card.js
new file mode 100644
index 00000000..3918d89b
--- /dev/null
+++ b/server/models/card.js
@@ -0,0 +1,34 @@
+"use strict";
+module.exports = function(sequelize, DataTypes) {
+ var Card = sequelize.define(
+ "Card",
+ {
+ listId: DataTypes.INTEGER,
+ title: DataTypes.STRING,
+ description: DataTypes.STRING
+ },
+ {
+ classMethods: {
+ associate: function(models) {
+ // associations can be defined here
+ Card.belongsTo(models.List, {
+ foreignKey: "listId"
+ });
+ Card.hasMany(models.Activity, {
+ foreignKey: "cardId"
+ });
+ Card.hasMany(models.UsersCards, {
+ foreignKey: "cardId"
+ });
+ Card.belongsToMany(models.User, {
+ through: models.UsersCards,
+ foreignKey: "cardId",
+ constraints: false,
+ unique: false
+ });
+ }
+ }
+ }
+ );
+ return Card;
+};
diff --git a/server/models/index.js b/server/models/index.js
new file mode 100644
index 00000000..7540dba8
--- /dev/null
+++ b/server/models/index.js
@@ -0,0 +1,36 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+var Sequelize = require('sequelize');
+var basename = path.basename(module.filename);
+var env = process.env.NODE_ENV || 'development';
+var config = require(__dirname + '/../config/config.json')[env];
+var db = {};
+
+if (config.use_env_variable) {
+ var sequelize = new Sequelize(process.env[config.use_env_variable]);
+} else {
+ var sequelize = new Sequelize(config.database, config.username, config.password, config);
+}
+
+fs
+ .readdirSync(__dirname)
+ .filter(function(file) {
+ return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
+ })
+ .forEach(function(file) {
+ var model = sequelize['import'](path.join(__dirname, file));
+ db[model.name] = model;
+ });
+
+Object.keys(db).forEach(function(modelName) {
+ if (db[modelName].associate) {
+ db[modelName].associate(db);
+ }
+});
+
+db.sequelize = sequelize;
+db.Sequelize = Sequelize;
+
+module.exports = db;
diff --git a/server/models/list.js b/server/models/list.js
new file mode 100644
index 00000000..667a26ea
--- /dev/null
+++ b/server/models/list.js
@@ -0,0 +1,25 @@
+"use strict";
+module.exports = function(sequelize, DataTypes) {
+ var List = sequelize.define(
+ "List",
+ {
+ boardId: DataTypes.INTEGER,
+ title: DataTypes.STRING,
+ description: DataTypes.STRING
+ },
+ {
+ classMethods: {
+ associate: function(models) {
+ // associations can be defined here
+ List.belongsTo(models.Board, {
+ foreignKey: "boardId"
+ });
+ List.hasMany(models.Card, {
+ foreignKey: "listId"
+ });
+ }
+ }
+ }
+ );
+ return List;
+};
diff --git a/server/models/user.js b/server/models/user.js
new file mode 100644
index 00000000..be26bca3
--- /dev/null
+++ b/server/models/user.js
@@ -0,0 +1,49 @@
+"use strict";
+const bcrypt = require("bcrypt");
+module.exports = function(sequelize, DataTypes) {
+ var User = sequelize.define(
+ "User",
+ {
+ email: DataTypes.STRING,
+ password: DataTypes.STRING
+ },
+ {
+ classMethods: {
+ associate: function(models) {
+ // associations can be defined here
+ User.hasMany(models.UsersBoards, {
+ foreignKey: "userId"
+ });
+ User.belongsToMany(models.Board, {
+ through: models.UsersBoards,
+ as: "BoardsBelongsTo",
+ unique: false,
+ constraints: false,
+ foreignKey: "userId"
+ });
+ User.hasMany(models.Board, {
+ foreignKey: "ownerId"
+ });
+ User.hasMany(models.UsersCards, {
+ foreignKey: "memberId"
+ });
+ User.belongsToMany(models.Card, {
+ through: models.UsersCards,
+ foreignKey: "memberId",
+ unique: false,
+ constraints: false
+ });
+ User.hasMany(models.Activity, {
+ foreignKey: "authorId"
+ });
+ }
+ }
+ }
+ );
+ // User.beforeCreate((user, options) => {
+ // return bcrypt.hashSync(user.password, 8).then(hashedPw => {
+ // user.password = hashedPw;
+ // });
+ // });
+ return User;
+};
diff --git a/server/models/usersboards.js b/server/models/usersboards.js
new file mode 100644
index 00000000..ff5d85fa
--- /dev/null
+++ b/server/models/usersboards.js
@@ -0,0 +1,28 @@
+"use strict";
+module.exports = function(sequelize, DataTypes) {
+ var UsersBoards = sequelize.define(
+ "UsersBoards",
+ {
+ fixId: {
+ type: DataTypes.BIGINT,
+ primaryKey: true
+ },
+ userId: DataTypes.INTEGER,
+ boardId: { type: DataTypes.INTEGER, unique: false }
+ },
+ {
+ classMethods: {
+ associate: function(models) {
+ // associations can be defined here
+ UsersBoards.belongsTo(models.Board, {
+ foreignKey: "boardId"
+ });
+ UsersBoards.belongsTo(models.User, {
+ foreignKey: "userId"
+ });
+ }
+ }
+ }
+ );
+ return UsersBoards;
+};
diff --git a/server/models/userscards.js b/server/models/userscards.js
new file mode 100644
index 00000000..ae798d8f
--- /dev/null
+++ b/server/models/userscards.js
@@ -0,0 +1,28 @@
+"use strict";
+module.exports = function(sequelize, DataTypes) {
+ var UsersCards = sequelize.define(
+ "UsersCards",
+ {
+ fixId: {
+ type: DataTypes.BIGINT,
+ primaryKey: true
+ },
+ memberId: DataTypes.INTEGER,
+ cardId: { type: DataTypes.INTEGER, unique: false }
+ },
+ {
+ classMethods: {
+ associate: function(models) {
+ // associations can be defined here
+ UsersCards.belongsTo(models.Card, {
+ foreignKey: "cardId"
+ });
+ UsersCards.belongsTo(models.User, {
+ foreignKey: "memberId"
+ });
+ }
+ }
+ }
+ );
+ return UsersCards;
+};
diff --git a/server/package.json b/server/package.json
new file mode 100644
index 00000000..74445bc5
--- /dev/null
+++ b/server/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "project_djello",
+ "version": "1.0.0",
+ "description": "Project management with that great wobbly taste.",
+ "main": "server.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "seed": "sequelize db:migrate:undo:all && sequelize db:migrate && sequelize db:seed:all",
+ "c": "node repl.js",
+ "sql": "node_modules/sequelize-cli/bin/sequelize"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/eglital/project_djello.git"
+ },
+ "author": "",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/eglital/project_djello/issues"
+ },
+ "homepage": "https://github.com/eglital/project_djello#readme",
+ "dependencies": {
+ "bcrypt": "^1.0.2",
+ "body-parser": "^1.17.2",
+ "cookie-session": "^2.0.0-beta.1",
+ "cors": "^2.8.3",
+ "crypto": "0.0.3",
+ "dotenv": "^4.0.0",
+ "errorhandler": "^1.5.0",
+ "express": "^4.15.3",
+ "express-flash-messages": "^0.1.1",
+ "express-handlebars": "^3.0.0",
+ "express-jwt": "^5.3.0",
+ "jsonwebtoken": "^7.4.1",
+ "jwt-simple": "^0.5.1",
+ "morgan": "^1.8.2",
+ "passport": "^0.3.2",
+ "passport-jwt": "^2.2.1",
+ "passport-local": "^1.0.0",
+ "pg": "^6.2.2",
+ "pg-hstore": "^2.3.2",
+ "sequelize": "^3.30.4",
+ "sequelize-cli": "^2.7.0"
+ }
+}
diff --git a/server/repl.js b/server/repl.js
new file mode 100644
index 00000000..2cba1306
--- /dev/null
+++ b/server/repl.js
@@ -0,0 +1,32 @@
+// Require the REPL module
+// and models
+var repl = require("repl").start({});
+var models = require("./models");
+
+// Make the `models` object
+// a global variable in the
+// REPL
+repl.context.models = models;
+
+// Make each model a global
+// object in the REPL
+Object.keys(models).forEach(modelName => {
+ repl.context[modelName] = models[modelName];
+});
+
+// Provide a convenience function `lg`
+// to pass to `then()` and `catch()`
+// to output less verbose values for
+// sequelize model query results
+repl.context.lg = data => {
+ if (Array.isArray(data)) {
+ if (data.length && data[0].dataValues) {
+ data = data.map(item => item.dataValues);
+ }
+ } else {
+ if (data.dataValues) {
+ data = data.dataValues;
+ }
+ }
+ console.log(data);
+};
diff --git a/server/seeders/20170524042627-users.js b/server/seeders/20170524042627-users.js
new file mode 100644
index 00000000..c5411195
--- /dev/null
+++ b/server/seeders/20170524042627-users.js
@@ -0,0 +1,40 @@
+"use strict";
+const models = require("./../models");
+const bcrypt = require("bcrypt");
+
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ /*
+ Add altering commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkInsert('Person', [{
+ name: 'John Doe',
+ isBetaMember: false
+ }], {});
+ */
+ var users = [];
+ users.push(
+ {
+ email: "egle@gmail.com",
+ password: bcrypt.hashSync("123456", 8)
+ },
+ { email: "test@gmail.com", password: bcrypt.hashSync("123456", 8) },
+ { email: "test1@gmail.com", password: bcrypt.hashSync("123456", 8) }
+ );
+
+ return queryInterface.bulkInsert("Users", users);
+ },
+
+ down: function(queryInterface, Sequelize) {
+ /*
+ Add reverting commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkDelete('Person', null, {});
+ */
+ return queryInterface.bulkDelete("Users", null, {}, models.User);
+ }
+};
diff --git a/server/seeders/20170525182140-boards.js b/server/seeders/20170525182140-boards.js
new file mode 100644
index 00000000..50f8f333
--- /dev/null
+++ b/server/seeders/20170525182140-boards.js
@@ -0,0 +1,31 @@
+"use strict";
+const models = require("./../models");
+
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ /*
+ Add altering commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkInsert('Person', [{
+ name: 'John Doe',
+ isBetaMember: false
+ }], {});
+ */
+ var boards = [];
+ boards.push({ name: "Board1", ownerId: 1 }, { name: "Board2", ownerId: 1 });
+ return queryInterface.bulkInsert("Boards", boards);
+ },
+
+ down: function(queryInterface, Sequelize) {
+ /*
+ Add reverting commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkDelete('Person', null, {});
+ */
+ return queryInterface.bulkDelete("Boards", null, {}, models.Board);
+ }
+};
diff --git a/server/seeders/20170525195830-usersboards.js b/server/seeders/20170525195830-usersboards.js
new file mode 100644
index 00000000..10fb6a1b
--- /dev/null
+++ b/server/seeders/20170525195830-usersboards.js
@@ -0,0 +1,40 @@
+"use strict";
+const models = require("./../models");
+
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ /*
+ Add altering commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkInsert('Person', [{
+ name: 'John Doe',
+ isBetaMember: false
+ }], {});
+ */
+ var usersboards = [];
+ usersboards.push(
+ { fixId: 2, userId: 1, boardId: 1 },
+ { fixId: 3, userId: 2, boardId: 1 },
+ { fixId: 4, userId: 1, boardId: 2 }
+ );
+ return queryInterface.bulkInsert("UsersBoards", usersboards);
+ },
+
+ down: function(queryInterface, Sequelize) {
+ /*
+ Add reverting commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkDelete('Person', null, {});
+ */
+ return queryInterface.bulkDelete(
+ "UsersBoards",
+ null,
+ {},
+ models.UsersBoards
+ );
+ }
+};
diff --git a/server/seeders/20170525204526-lists.js b/server/seeders/20170525204526-lists.js
new file mode 100644
index 00000000..baec2069
--- /dev/null
+++ b/server/seeders/20170525204526-lists.js
@@ -0,0 +1,41 @@
+"use strict";
+const models = require("./../models");
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ /*
+ Add altering commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkInsert('Person', [{
+ name: 'John Doe',
+ isBetaMember: false
+ }], {});
+ */
+ var lists = [];
+ lists.push(
+ {
+ boardId: 1,
+ title: "List1",
+ description: "This is a description of list 1"
+ },
+ {
+ boardId: 1,
+ title: "List2",
+ description: "This is a description of list 2"
+ }
+ );
+ return queryInterface.bulkInsert("Lists", lists);
+ },
+
+ down: function(queryInterface, Sequelize) {
+ /*
+ Add reverting commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkDelete('Person', null, {});
+ */
+ return queryInterface.bulkDelete("Boards", null, {}, models.List);
+ }
+};
diff --git a/server/seeders/20170525204530-cards.js b/server/seeders/20170525204530-cards.js
new file mode 100644
index 00000000..78b437b3
--- /dev/null
+++ b/server/seeders/20170525204530-cards.js
@@ -0,0 +1,42 @@
+"use strict";
+const models = require("./../models");
+
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ /*
+ Add altering commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkInsert('Person', [{
+ name: 'John Doe',
+ isBetaMember: false
+ }], {});
+ */
+ var cards = [];
+ cards.push(
+ {
+ listId: 1,
+ title: "Card1",
+ description: "This is a description of card 1"
+ },
+ {
+ listId: 1,
+ title: "Card2",
+ description: "This is a description of card 2"
+ }
+ );
+ return queryInterface.bulkInsert("Cards", cards);
+ },
+
+ down: function(queryInterface, Sequelize) {
+ /*
+ Add reverting commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkDelete('Person', null, {});
+ */
+ return queryInterface.bulkDelete("Boards", null, {}, models.Card);
+ }
+};
diff --git a/server/seeders/20170525204538-activities.js b/server/seeders/20170525204538-activities.js
new file mode 100644
index 00000000..2d10d26d
--- /dev/null
+++ b/server/seeders/20170525204538-activities.js
@@ -0,0 +1,33 @@
+"use strict";
+const models = require("./../models");
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ /*
+ Add altering commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkInsert('Person', [{
+ name: 'John Doe',
+ isBetaMember: false
+ }], {});
+ */
+ var activities = [];
+ activities.push(
+ { authorId: 1, cardId: 1, description: "created this card" },
+ { authorId: 1, cardId: 2, description: "created this card" }
+ );
+ return queryInterface.bulkInsert("Activities", activities);
+ },
+
+ down: function(queryInterface, Sequelize) {
+ /*
+ Add reverting commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkDelete('Person', null, {});
+ */
+ return queryInterface.bulkDelete("Activities", null, {}, models.Activity);
+ }
+};
diff --git a/server/seeders/20170525204556-userscards.js b/server/seeders/20170525204556-userscards.js
new file mode 100644
index 00000000..a0371f06
--- /dev/null
+++ b/server/seeders/20170525204556-userscards.js
@@ -0,0 +1,34 @@
+"use strict";
+const models = require("./../models");
+
+module.exports = {
+ up: function(queryInterface, Sequelize) {
+ /*
+ Add altering commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkInsert('Person', [{
+ name: 'John Doe',
+ isBetaMember: false
+ }], {});
+ */
+ var userscards = [];
+ userscards.push(
+ { fixId: 2, memberId: 1, cardId: 1 },
+ { fixId: 3, memberId: 2, cardId: 1 }
+ );
+ return queryInterface.bulkInsert("UsersCards", userscards);
+ },
+
+ down: function(queryInterface, Sequelize) {
+ /*
+ Add reverting commands here.
+ Return a promise to correctly handle asynchronicity.
+
+ Example:
+ return queryInterface.bulkDelete('Person', null, {});
+ */
+ return queryInterface.bulkDelete("UsersCards", null, {}, models.UsersCards);
+ }
+};
diff --git a/server/server.js b/server/server.js
new file mode 100644
index 00000000..1adc211f
--- /dev/null
+++ b/server/server.js
@@ -0,0 +1,64 @@
+if (process.env.NODE_ENV !== "production") {
+ require("dotenv").config();
+}
+var express = require("express");
+
+var app = express();
+
+var logger = require("morgan"),
+ cors = require("cors"),
+ bodyParser = require("body-parser");
+
+app.set("port", process.env.PORT || 3001);
+
+var auth = require("./auth.js")();
+// Parsers
+// old version of line
+// app.use(bodyParser.urlencoded());
+// new version of line
+app.use(bodyParser.urlencoded({ extended: true }));
+app.use(bodyParser.json());
+
+//---------------------------------------
+//Set response headers for CORS
+//---------------------------------------
+app.use(function(req, res, next) {
+ res.header("Access-Control-Allow-Origin", "*");
+ res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
+ res.header(
+ "Access-Control-Allow-Headers",
+ "Origin, X-Requested-With, Content-Type, Accept, Authorization, Access-Control-Allow-Credentials"
+ );
+ res.header("Access-Control-Allow-Credentials", "true");
+ next();
+});
+app.use(cors());
+
+app.get("/", function(req, res) {
+ res.json({
+ status: "My API is alive!"
+ });
+});
+app.use(auth.initialize());
+
+app.use(require("./user-routes"));
+app.use("*", auth.authenticate(), function(req, res, next) {
+ next();
+});
+app.use(require("./db-routes"));
+
+// Defines next action for errors
+function errorHandler(err, req, res, next) {
+ console.error(`Error: ${err.stack}`);
+ res.status(err.response ? err.response.status : 500);
+ res.json({
+ error: err.message
+ });
+}
+
+// Tell the app to use the errorHandler middleware
+app.use(errorHandler);
+
+app.listen(app.get("port"), function() {
+ console.log("My API is running...");
+});
diff --git a/server/user-routes.js b/server/user-routes.js
new file mode 100644
index 00000000..3a0d20d7
--- /dev/null
+++ b/server/user-routes.js
@@ -0,0 +1,32 @@
+var express = require("express"), _ = require("lodash");
+var jwt = require("jwt-simple");
+const models = require("./models");
+const User = models.User;
+const sequelize = models.sequelize;
+const bcrypt = require("bcrypt");
+
+var app = (module.exports = express.Router());
+
+app.post("/sessions/create", function(req, res) {
+ if (req.body.email && req.body.password) {
+ var email = req.body.email;
+ var password = req.body.password;
+ User.findOne({ where: { email: req.body.email } }).then(user => {
+ if (user && bcrypt.compareSync(password, user.password)) {
+ var payload = {
+ id: user.id
+ };
+ var token = jwt.encode(payload, process.env.JWT_SECRET);
+ res.status(201).send({
+ token: token,
+ userId: user.id,
+ userEmail: user.email
+ });
+ } else {
+ res.status(401).send({ error: "The email or password don't match" });
+ }
+ });
+ } else {
+ res.status(401).send({ error: "The email or password don't match" });
+ }
+});