diff --git a/.gitmodules b/.gitmodules index def214c9f..87ddbfce6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "frontend"] - path = frontend - url = git@github.com:gradido/gradido_vue_wallet.git [submodule "gn"] path = gn url = https://github.com/gradido/gn.git diff --git a/docker-compose.yml b/docker-compose.yml index aa44a9168..b72655d8e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -97,36 +97,6 @@ services: - internal-net volumes: - ./community_server/config/php-fpm/php-ini-overrides.ini:/etc/php/7.4/fpm/conf.d/99-overrides.ini - - #backend: - # image: ocelotsocialnetwork/backend:latest - # build: - # context: ./backend - # target: production - # networks: - # - external-net - # - internal-net - # depends_on: - # - neo4j - # ports: - # - 4000:4000 - # volumes: - # - backend_uploads:/app/public/uploads - # environment: - # # Envs used in Dockerfile - # # - DOCKER_WORKDIR="/app" - # # - PORT="4000" - # - BUILD_DATE - # - BUILD_VERSION - # - BUILD_COMMIT - # - NODE_ENV="production" - # # Application only envs - # - DEBUG=false - # - NEO4J_URI=bolt://neo4j:7687 - # - GRAPHQL_URI=http://backend:4000 - # - CLIENT_URI=http://webapp:3000 - # env_file: - # - ./backend/.env networks: external-net: diff --git a/docu/cookie.drawio b/docu/cookie.drawio new file mode 100644 index 000000000..a545b3d9d --- /dev/null +++ b/docu/cookie.drawio @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend b/frontend deleted file mode 160000 index 2e0b9d9aa..000000000 --- a/frontend +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2e0b9d9aaabdf4bc9de3929d71b0902b7a32008a diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 000000000..88249539f --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,3 @@ +node_modules +.git +.gitignore \ No newline at end of file diff --git a/frontend/.editorconfig b/frontend/.editorconfig new file mode 100644 index 000000000..9d08a1a82 --- /dev/null +++ b/frontend/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js new file mode 100644 index 000000000..fe2660bd9 --- /dev/null +++ b/frontend/.eslintrc.js @@ -0,0 +1,14 @@ +module.exports = { + root: true, + env: { + node: true + }, + extends: ['plugin:vue/essential'], + rules: { + 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', + 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' + }, + parserOptions: { + parser: 'babel-eslint' + } +}; diff --git a/frontend/.gitattributes b/frontend/.gitattributes new file mode 100644 index 000000000..aa70f3c26 --- /dev/null +++ b/frontend/.gitattributes @@ -0,0 +1,15 @@ +# Auto detect text files and perform LF normalization +*.scss linguist-language=Vue +*.css linguist-language=Vue + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 000000000..82783fce2 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,20 @@ +.DS_Store +node_modules/ +dist/ +.cache/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +test/unit/coverage + +package-lock.json +.env +.env.development.local +.env.production.local + +# Editor directories and files +.idea +*.suo +*.ntvs* +*.njsproj +*.sln diff --git a/frontend/.postcssrc.js b/frontend/.postcssrc.js new file mode 100644 index 000000000..373f665cb --- /dev/null +++ b/frontend/.postcssrc.js @@ -0,0 +1,8 @@ +// https://github.com/michael-ciniawsky/postcss-load-config + +module.exports = { + plugins: { + // to edit target browsers: use "browserslist" field in package.json + autoprefixer: {} + } +}; diff --git a/frontend/CHANGELOG.md b/frontend/CHANGELOG.md new file mode 100755 index 000000000..5d720d3d4 --- /dev/null +++ b/frontend/CHANGELOG.md @@ -0,0 +1,2 @@ +## [1.0.0] - 2020-07-27 +### Initial Release diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 000000000..63d81c9f4 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,108 @@ +################################################################################## +# BASE ########################################################################### +################################################################################## +FROM node:12.19.0-alpine3.10 as base + +# ENVs (available in production aswell, can be overwritten by commandline or env file) +## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame +ENV DOCKER_WORKDIR="/app" +## We Cannot do `$(date -u +'%Y-%m-%dT%H:%M:%SZ')` here so we use unix timestamp=0 +ENV BUILD_DATE="1970-01-01T00:00:00.00Z" +## We cannot do $(npm run version).${BUILD_NUMBER} here so we default to 0.0.0.0 +ENV BUILD_VERSION="0.0.0.0" +## We cannot do `$(git rev-parse --short HEAD)` here so we default to 0000000 +ENV BUILD_COMMIT="0000000" +## SET NODE_ENV +ENV NODE_ENV="production" +## App relevant Envs +ENV PORT="8080" + +# Labels +LABEL org.label-schema.build-date="${BUILD_DATE}" +LABEL org.label-schema.name="gradido:frontend" +LABEL org.label-schema.description="Gradido Vue Webwallet" +LABEL org.label-schema.usage="https://github.com/gradido/gradido_vue_wallet/blob/master/README.md" +LABEL org.label-schema.url="https://gradido.net" +LABEL org.label-schema.vcs-url="https://github.com/gradido/gradido_vue_wallet/tree/master/backend" +LABEL org.label-schema.vcs-ref="${BUILD_COMMIT}" +LABEL org.label-schema.vendor="gradido Community" +LABEL org.label-schema.version="${BUILD_VERSION}" +LABEL org.label-schema.schema-version="1.0" +LABEL maintainer="support@ogradido.net" + +# Install Additional Software +## install: git +#RUN apk --no-cache add git + +# Settings +## Expose Container Port +EXPOSE ${PORT} + +## Workdir +RUN mkdir -p ${DOCKER_WORKDIR} +WORKDIR ${DOCKER_WORKDIR} + +################################################################################## +# DEVELOPMENT (Connected to the local environment, to reload on demand) ########## +################################################################################## +FROM base as development + +# We don't need to copy or build anything since we gonna bind to the +# local filesystem which will need a rebuild anyway + +# Run command +# (for development we need to execute npm install since the +# node_modules are on another volume and need updating) +CMD /bin/sh -c "npm install && npm run dev" + +################################################################################## +# BUILD (Does contain all files and is therefore bloated) ######################## +################################################################################## +FROM base as build + +# Copy everything +COPY . . +# npm install +RUN npm install --production=false --frozen-lockfile --non-interactive +# npm build +RUN npm run build + +################################################################################## +# TEST ########################################################################### +################################################################################## +FROM build as test + +# Run command +CMD /bin/sh -c "npm run dev" + +################################################################################## +# PRODUCTION (Does contain only "binary"- and static-files to reduce image size) # +################################################################################## +FROM base as production + +# Copy "binary"-files from build image +COPY --from=build ${DOCKER_WORKDIR}/.nuxt ./.nuxt +COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules +COPY --from=build ${DOCKER_WORKDIR}/nuxt.config.js ./nuxt.config.js +# Copy static files +# TODO - this should be one Folder containign all stuff needed to be copied +#COPY --from=build ${DOCKER_WORKDIR}/constants ./constants +#COPY --from=build ${DOCKER_WORKDIR}/static ./static +#COPY --from=build ${DOCKER_WORKDIR}/locales ./locales +# Copy package.json for script definitions (lock file should not be needed) +COPY --from=build ${DOCKER_WORKDIR}/package.json ./package.json + +# Run command +CMD /bin/sh -c "npm run start" + + + +## add `/usr/src/app/node_modules/.bin` to $PATH +#ENV PATH /usr/src/app/node_modules/.bin:$PATH +# +## install and cache app dependencies +#COPY package.json /usr/src/app/package.json +#RUN npm install +#RUN npm install -g @vue/cli +## start app +#CMD ["npm", "run", "serve"] \ No newline at end of file diff --git a/frontend/ISSUE_TEMPLATE.md b/frontend/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..8103f52e6 --- /dev/null +++ b/frontend/ISSUE_TEMPLATE.md @@ -0,0 +1,9 @@ + + + diff --git a/frontend/README.md b/frontend/README.md new file mode 100755 index 000000000..10fe1c1c0 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,389 @@ +# Vue Gradido Wallet + + +# install mit npm +``` + $ git clone https://github.com/gradido/gradido_vue_wallet.git [project-name] + $ cd [project-name] + $ npm install + $ npm run serve + +### Build + $ npm run build +``` + +# install mit docker +``` + ### build + $ docker build -t [project-name] . + + ### run + $ docker run -it -p 80:80 --rm [project-name] +``` + + + + +**Fully Coded Components** + +Bootstrap Vue Gradido Wallet - + + **DEMO:** [https://vast-atoll-44277.herokuapp.com/](https://vast-atoll-44277.herokuapp.com/) + + +ISSUES: + + - [ ] csrf token management + + + - [ ] Userdaten - Testbenutzer - test.json + + + - [ ] Session Cookie: GRADIDO_LOGIN enhancement + + + - [ ] 🚀 [Feature] - Create a dockerfile for the frontend application enhancement + + + **DEMO:** [https://vast-atoll-44277.herokuapp.com/](https://vast-atoll-44277.herokuapp.com/) + + + + ___________ + + +# 🌟 [EPIC] - Gradido Web- and App- Client + +Web-App: +Einstiegspunkt: +[ ] Login-Server for app-requests (Sollte in der App einstellbar sein) https://staging.gradido.net/appRequest + +[ ] Auch die url für Community-Server requests sollte in einer Variable gespeichert sein. +CakePHP Seite auf die der Login-Server nach dem Login weiterleitet. +https://staging.gradido.net/client + +Hiermit kann ein Konto anlegt werden: +https://staging.gradido.net/account/registerDirect + +# Fehler im Code +Wenn etwas nicht stimmt, entweder mit den Input-Paremetern, oder ein Fehler im Code gibt es meistens folgendes als Ergebnis: +``` +{ + "state": "error", + "msg": "", + "details": "" +} + ``` + +# csfr Token +Bindet das js ein. +Stellt folgende js-Variablen zur Verfügung: + +csfr : string +csfr Token (https://book.cakephp.org/3/en/controllers/components/csrf.html) +user: object + +# Testbenutzer +Enthält Daten des aktuell eingeloggten Benutzers, z.B.: mein Testbenutzer: +console.log(user); +``` +{ + "created": 1578688666, + "disabled": false, + "email": "dervommond@gmail.com", + "email_checked": true, + "first_name": "Max", + "group_alias": "gdd1", + "ident_hash": 2928827813, + "last_name": "Miau", + "public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b", + "role": "admin", + "username": "", + "balance": 174500, // Gradido Cent, 4 Nachkommastellen (2 Reserve) entspricht 17,45 + "id": 1, + "errorCount": 0 +} +``` +Das sind im Grunde die Benutzerangaben aus der Login-Server Datenbank. + +session :int +Login-Server session id, notwendig für alle ajax-request. + +# Seiten +Navigation: +Für alle Benutzer: + +Kontoübersicht +Startseite +Überweisung +Mitgliederbereich (externer Link zu elopage: https://elopage.com/s/gradido/sign_in) +Rechts oben: +Profil +Abmelden +Startseite: +Für alle Benutzer: +Kontoübersicht +Überweisung +Benutzer Suche: +http://daten.einhornimmond.de/gradido_mithril_user_search.zip + +# Mobile App +Login über eingebundene Login-Seite +auslesen der session_id aus dem Session Cookie: GRADIDO_LOGIN +Access Token vom Login-Server anfragen: +GET https://staging.gradido.net/appRequest/acquireAccessToken?session_id = +Du kannst auch den Cookie wieder mitschicken, solange die Login-Server Basis-url die gleiche ist, müsste das auch funktionieren. +Antwort: +``` +{ + "state":"success", + "access_token" : "", + "group_base_url":"" +} +``` +Unterschied Access Token von der session_id: Access Tokens sind länger gültig +Du kannst über eine gültige session_id einen Access Token erhalten der eine Woche gültig ist. Die Client-IP des Aufrufess muss die gleiche sein, mit der eingeloggt wurde. + + +Mit einem gültigen Access-Token kannst du eine session_id erhalten. +GET https://staging.gradido.net/appRequest/appLogin?access_token = +Mit jedem Aufruf wird die Gültigkeit der Access-Tokens erneuert. +Antwort: +``` +{ + "state":"success", + "session_id" : "" +} +``` +# Kontoübersicht: +Liefert den aktuellen Kontostand. +Ajax: +GET https://staging.gradido.net/state-balances/ajaxGetBalance +Antwort: +`{"state":"success","balance":}` + +Listet die letzten Transaktionen auf, mit Paging. +Ajax: +GET https://staging.gradido.net/state-user-transactions/ajaxListTransactions// +page: Seite der Transaktionen, default = 1 +count: Wie viele Transaktionen pro Seite, default = 20 + +Antwort: +Wenn alles okay: +``` +{"state":"success", "transactions": + [ + { + "name": "", + "email": "", //optional, only if send or receive and other user is known + "type": "creation|send|receive", + "transaction_id": , // db id not id from blockchain + "date": "", + "balance": , + "memo": "", + "pubkey": "" + + } + ], + "transactionExecutingCount": , + "count": +} +``` +Holt die aktuelle Summe und Anzahl Einträge vom GDT Server für den Benutzer. +Ajax: +GET https://staging.gradido.net/state-balances/ajaxGdtOverview +```{"state": "success", "gdt": {"sum": , "count":}}``` + + +# 🌟 [EPIC] - Gradido Web- and App- Client + +Web-App: +Einstiegspunkt: +[ ] Login-Server for app-requests (Sollte in der App einstellbar sein) https://staging.gradido.net/appRequest + +[ ] Auch die url für Community-Server requests sollte in einer Variable gespeichert sein. +CakePHP Seite auf die der Login-Server nach dem Login weiterleitet. +https://staging.gradido.net/client + +Hiermit kann ein Konto anlegt werden: +https://staging.gradido.net/account/registerDirect + + +# Fehler im Code +Wenn etwas nicht stimmt, entweder mit den Input-Paremetern, oder ein Fehler im Code gibt es meistens folgendes als Ergebnis: +``` +{ + "state": "error", + "msg": "", + "details": "" +} + ``` + +# csfr Token +Bindet das js ein. +Stellt folgende js-Variablen zur Verfügung: + +csfr : string +csfr Token (https://book.cakephp.org/3/en/controllers/components/csrf.html) +user: object + +# Testbenutzer +Enthält Daten des aktuell eingeloggten Benutzers, z.B.: mein Testbenutzer: +console.log(user); +``` +{ + "created": 1578688666, + "disabled": false, + "email": "dervommond@gmail.com", + "email_checked": true, + "first_name": "Max", + "group_alias": "gdd1", + "ident_hash": 2928827813, + "last_name": "Miau", + "public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b", + "role": "admin", + "username": "", + "balance": 174500, // Gradido Cent, 4 Nachkommastellen (2 Reserve) entspricht 17,45 + "id": 1, + "errorCount": 0 +} +``` +Das sind im Grunde die Benutzerangaben aus der Login-Server Datenbank. + +session :int +Login-Server session id, notwendig für alle ajax-request. + +# Seiten +Navigation: +Für alle Benutzer: + +Kontoübersicht +Startseite +Überweisung +Mitgliederbereich (externer Link zu elopage: https://elopage.com/s/gradido/sign_in) +Rechts oben: +Profil +Abmelden +Startseite: +Für alle Benutzer: +Kontoübersicht +Überweisung +Benutzer Suche: +http://daten.einhornimmond.de/gradido_mithril_user_search.zip + +# Mobile App +Login über eingebundene Login-Seite +auslesen der session_id aus dem Session Cookie: GRADIDO_LOGIN +Access Token vom Login-Server anfragen: +GET https://staging.gradido.net/appRequest/acquireAccessToken?session_id = +Du kannst auch den Cookie wieder mitschicken, solange die Login-Server Basis-url die gleiche ist, müsste das auch funktionieren. +Antwort: +``` +{ + "state":"success", + "access_token" : "", + "group_base_url":"" +} +``` +Unterschied Access Token von der session_id: Access Tokens sind länger gültig +Du kannst über eine gültige session_id einen Access Token erhalten der eine Woche gültig ist. Die Client-IP des Aufrufess muss die gleiche sein, mit der eingeloggt wurde. + +Mit einem gültigen Access-Token kannst du eine session_id erhalten. +GET https://staging.gradido.net/appRequest/appLogin?access_token = +Mit jedem Aufruf wird die Gültigkeit der Access-Tokens erneuert. +Antwort: +``` +{ + "state":"success", + "session_id" : "" +} +``` +# Kontoübersicht: +Liefert den aktuellen Kontostand. +Ajax: +GET https://staging.gradido.net/state-balances/ajaxGetBalance +Antwort: +`{"state":"success","balance":}` + +Listet die letzten Transaktionen auf, mit Paging. +Ajax: +GET https://staging.gradido.net/state-user-transactions/ajaxListTransactions// +page: Seite der Transaktionen, default = 1 +count: Wie viele Transaktionen pro Seite, default = 20 + +Antwort: +Wenn alles okay: +``` +{"state":"success", "transactions": + [ + { + "name": "", + "email": "", //optional, only if send or receive and other user is known + "type": "creation|send|receive", + "transaction_id": , // db id not id from blockchain + "date": "", + "balance": , + "memo": "", + "pubkey": "" + + } + ], + "transactionExecutingCount": , + "count": +} +``` +Holt die aktuelle Summe und Anzahl Einträge vom GDT Server für den Benutzer. +Ajax: +GET https://staging.gradido.net/state-balances/ajaxGdtOverview +```{"state": "success", "gdt": {"sum": , "count":}}``` + +Holt die letzten 100 GDT-Einträge für den Benutzer + + + +Ein GDT Eintrag sieht so aus: +``` +{ + "id": 8857, + "amount": 1000, // = 10,00 Euro + "date": "2020-06-17T14:12:00+00:00", + "email": "foerderkreis-1@gradido.org", + "comment": null, + "coupon_code": "", + "gdt_entry_type_id": 4, + "factor": "20.0000", + "amount2": 0, + "factor2": "0.0500", + "gdt": 1000 +} +``` + +gdt entry types: (Auf welchen Weg der Eintrag eingetragen wurde) +1. Form: einzeln über das Formular, sollte nur wenige Einträg e betreffen +2. CVS: CVS Import, betrifft vor allem ältere Einträge von Spenden die weder über Elopage noch über Digistore reinkamen +3. Elopage: Alle GDT Einträge die automatisch durch eine Elopage-Transaktion erstellt wurden für den Einzahlenden. +4. Elopage-Publisher: Alle GDT Einträge die automatisch durch eine Elopage-Transaktion erstellt wurden für den Publisher, bis zu 5 Level nach oben. +5. Digistore: Alle GDT Einträge die automatisch durch eine Digistore-Transaktion angelegt wurden. +6. Cvs2: GDT Einträge die durch ein anderen CVS Import eingetragen wurden, betrifft ebenfalls nur alte Einträge. +amount: Menge in Euro-cent (2 Nachkommastellen) was eingezahlt wurde +factor: Der Umrechnungsfaktor der beim Einzahlen für den betreffenden Unterstützer galt. +amount2: ein Bonus Factor der drauf gerechnet wird bei Sonderaktionen, default 0 +factor2: ein Bonus-Factor, default 1, wird aktuell im Code auf für Publisher-Transactionen benutzt. +Gdt: resultierender GDT Wert, wird folgendermaßen aus den bisherigen Werten berechnet: +gdt = amount * factor * factor2 + amount2 +Es gibt zwei Arten von GDT Einträgen: + +Was der Benutzer selbst in Euro gespendet hat +Was jemand anderes an Euro gespendet hat, der den Benutzer als Publisher gewählt hat (publisher-id bei Elopage), Publisher bis Level 5 erhalten jeweils 5% an GDT was der Spender erhalten hat. +z.B. Anna spendet 100 Euro bei einem Faktor von 20, bekommt also 2000 GDT. +Sie hat als Publisher Bernd angegeben, Bern erhält 100 GDT. +Bernd hat als Publisher damals Paul angegeben, Paul erhält also ebenfalls noch 100 GDT. +Bis zum 5. (Bernd ist 2.) +Diese Beziehung wird durch die connectEntries dargestellt. +Insbesondere durch den publishersPath, connect enthält einfach nur alle mögliche Daten. + +# TODO +TODO: Update GDT-Server um paging und Zugriff auf alle Einträge zu erhalten, optimierter Zugriff +GET https://staging.gradido.net/state-balances/ajaxGdtTransactions +Liefert wenn alles in Ordnung ist: + diff --git a/frontend/babel.config.js b/frontend/babel.config.js new file mode 100644 index 000000000..add0e9944 --- /dev/null +++ b/frontend/babel.config.js @@ -0,0 +1,14 @@ +module.exports = { + "presets": [ + "@vue/app" + ], + "plugins": [ + [ + "component", + { + "libraryName": "element-ui", + "styleLibraryName": "theme-chalk" + } + ] + ] +} diff --git a/frontend/intelij.webpack.js b/frontend/intelij.webpack.js new file mode 100644 index 000000000..2f49f3814 --- /dev/null +++ b/frontend/intelij.webpack.js @@ -0,0 +1,12 @@ +// This configuration file is not used anywhere in the code, it's a hack to handle InteliJ relative path imports +// Keep in sync with actual webpack aliases + +const path = require('path'); + +module.exports = { + resolve: { + alias: { + '@': path.resolve(__dirname, 'src') + } + } +}; diff --git a/frontend/package.json b/frontend/package.json new file mode 100755 index 000000000..2e5a80790 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,72 @@ +{ + "name": "bootstrap-vue-gradido-wallet", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "node server.js", + "serve": "vue-cli-service serve --open", + "build": "vue-cli-service build", + "lint": "vue-cli-service lint", + "dev": "npm run serve", + "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'" + }, + "dependencies": { + "axios": "^0.21.1", + "bootstrap": "4.3.1", + "bootstrap-vue": "^2.5.0", + "chart.js": "^2.9.3", + "d3": "^5.7.0", + "datamaps": "^0.5.9", + "date-fns": "^1.30.1", + "dropzone": "^5.5.1", + "element-ui": "2.4.11", + "es6-promise": "^4.1.1", + "eslint": "^5.16.0", + "eslint-plugin-vue": "^7.5.0", + "express": "^4.17.1", + "flatpickr": "^4.5.7", + "fuse.js": "^3.2.0", + "google-maps": "^3.2.1", + "nouislider": "^12.1.0", + "perfect-scrollbar": "^1.3.0", + "quill": "^1.3.6", + "sweetalert2": "^9.5.4", + "vee-validate": "^3.2.1", + "vue": "^2.6.11", + "vue-bootstrap-typeahead": "^0.2.6", + "vue-chartjs": "^3.5.0", + "vue-cli-plugin-i18n": "^1.0.1", + "vue-clickaway": "^2.2.2", + "vue-clipboard2": "^0.3.0", + "vue-cookies": "^1.7.4", + "vue-flatpickr-component": "^8.1.2", + "vue-good-table": "^2.21.3", + "vue-i18n": "^8.22.4", + "vue-qrcode-reader": "^2.3.16", + "vue-router": "^3.0.6", + "vue2-transitions": "^0.2.3", + "vuex": "^3.6.0" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "^3.7.0", + "@vue/cli-plugin-eslint": "^3.7.0", + "@vue/cli-service": "^3.7.0", + "@vue/eslint-config-prettier": "^4.0.1", + "babel-plugin-component": "^1.1.0", + "node-sass": "^4.12.0", + "sass-loader": "^7.1.0", + "vue-template-compiler": "^2.6.11" + }, + "postcss": { + "plugins": { + "autoprefixer": {} + } + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 10" + ], + "author": "Bernd Hückstädt - https://www.gradido.net/", + "description": "Gradido Wallet" +} diff --git a/frontend/public/favicon.png b/frontend/public/favicon.png new file mode 100644 index 000000000..db3d73274 Binary files /dev/null and b/frontend/public/favicon.png differ diff --git a/frontend/public/img/brand/Gradido-Coin_300_120dpi.png b/frontend/public/img/brand/Gradido-Coin_300_120dpi.png new file mode 100644 index 000000000..d7887a4b3 Binary files /dev/null and b/frontend/public/img/brand/Gradido-Coin_300_120dpi.png differ diff --git a/frontend/public/img/brand/Gradido-Coin_300_120dpi_comic.png b/frontend/public/img/brand/Gradido-Coin_300_120dpi_comic.png new file mode 100644 index 000000000..f32b4e922 Binary files /dev/null and b/frontend/public/img/brand/Gradido-Coin_300_120dpi_comic.png differ diff --git a/frontend/public/img/brand/Gradido-Coin_300_120dpi_cubeb.png b/frontend/public/img/brand/Gradido-Coin_300_120dpi_cubeb.png new file mode 100644 index 000000000..e190523bb Binary files /dev/null and b/frontend/public/img/brand/Gradido-Coin_300_120dpi_cubeb.png differ diff --git a/frontend/public/img/brand/Gradido-Coin_300_120dpi_sw.png b/frontend/public/img/brand/Gradido-Coin_300_120dpi_sw.png new file mode 100644 index 000000000..f3bfe05e2 Binary files /dev/null and b/frontend/public/img/brand/Gradido-Coin_300_120dpi_sw.png differ diff --git a/frontend/public/img/brand/Gradido-Coin_500_175dpi.png b/frontend/public/img/brand/Gradido-Coin_500_175dpi.png new file mode 100644 index 000000000..bc7f1ef88 Binary files /dev/null and b/frontend/public/img/brand/Gradido-Coin_500_175dpi.png differ diff --git a/frontend/public/img/brand/cube.webm b/frontend/public/img/brand/cube.webm new file mode 100644 index 000000000..0bfcdad7b Binary files /dev/null and b/frontend/public/img/brand/cube.webm differ diff --git a/frontend/public/img/brand/favicon.png b/frontend/public/img/brand/favicon.png new file mode 100755 index 000000000..7515a34bc Binary files /dev/null and b/frontend/public/img/brand/favicon.png differ diff --git a/frontend/public/img/brand/green.png b/frontend/public/img/brand/green.png new file mode 100644 index 000000000..f87e1487d Binary files /dev/null and b/frontend/public/img/brand/green.png differ diff --git a/frontend/public/img/brand/white.png b/frontend/public/img/brand/white.png new file mode 100755 index 000000000..b7181bf1a Binary files /dev/null and b/frontend/public/img/brand/white.png differ diff --git a/frontend/public/img/icons/cards/bitcoin.png b/frontend/public/img/icons/cards/bitcoin.png new file mode 100755 index 000000000..9a4b04319 Binary files /dev/null and b/frontend/public/img/icons/cards/bitcoin.png differ diff --git a/frontend/public/img/icons/cards/mastercard.png b/frontend/public/img/icons/cards/mastercard.png new file mode 100755 index 000000000..8287feca9 Binary files /dev/null and b/frontend/public/img/icons/cards/mastercard.png differ diff --git a/frontend/public/img/icons/cards/paypal.png b/frontend/public/img/icons/cards/paypal.png new file mode 100755 index 000000000..f8e460db1 Binary files /dev/null and b/frontend/public/img/icons/cards/paypal.png differ diff --git a/frontend/public/img/icons/cards/visa.png b/frontend/public/img/icons/cards/visa.png new file mode 100755 index 000000000..596545fc8 Binary files /dev/null and b/frontend/public/img/icons/cards/visa.png differ diff --git a/frontend/public/img/icons/common/github.svg b/frontend/public/img/icons/common/github.svg new file mode 100644 index 000000000..2227d5e0f --- /dev/null +++ b/frontend/public/img/icons/common/github.svg @@ -0,0 +1,12 @@ + + + + UI/icons/dark/github + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/frontend/public/img/icons/common/google.svg b/frontend/public/img/icons/common/google.svg new file mode 100644 index 000000000..999a208c3 --- /dev/null +++ b/frontend/public/img/icons/common/google.svg @@ -0,0 +1,17 @@ + + + + UI/icons/color/google + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/img/icons/flags/DE.png b/frontend/public/img/icons/flags/DE.png new file mode 100755 index 000000000..62798f3ef Binary files /dev/null and b/frontend/public/img/icons/flags/DE.png differ diff --git a/frontend/public/img/icons/flags/GB.png b/frontend/public/img/icons/flags/GB.png new file mode 100755 index 000000000..f5a50357e Binary files /dev/null and b/frontend/public/img/icons/flags/GB.png differ diff --git a/frontend/public/img/icons/flags/US.png b/frontend/public/img/icons/flags/US.png new file mode 100755 index 000000000..f0672464a Binary files /dev/null and b/frontend/public/img/icons/flags/US.png differ diff --git a/frontend/public/img/icons/gradido/minus-low.png b/frontend/public/img/icons/gradido/minus-low.png new file mode 100644 index 000000000..5c1f5afed Binary files /dev/null and b/frontend/public/img/icons/gradido/minus-low.png differ diff --git a/frontend/public/img/icons/gradido/minus.png b/frontend/public/img/icons/gradido/minus.png new file mode 100644 index 000000000..b6c40ba22 Binary files /dev/null and b/frontend/public/img/icons/gradido/minus.png differ diff --git a/frontend/public/img/icons/gradido/my_gradido.png b/frontend/public/img/icons/gradido/my_gradido.png new file mode 100644 index 000000000..c5131678e Binary files /dev/null and b/frontend/public/img/icons/gradido/my_gradido.png differ diff --git a/frontend/public/img/icons/gradido/plus-low.png b/frontend/public/img/icons/gradido/plus-low.png new file mode 100644 index 000000000..8ddf8a6fe Binary files /dev/null and b/frontend/public/img/icons/gradido/plus-low.png differ diff --git a/frontend/public/img/icons/gradido/plus.png b/frontend/public/img/icons/gradido/plus.png new file mode 100644 index 000000000..8d22e3b50 Binary files /dev/null and b/frontend/public/img/icons/gradido/plus.png differ diff --git a/frontend/public/img/icons/gradido/qr-make.png b/frontend/public/img/icons/gradido/qr-make.png new file mode 100644 index 000000000..4890498e1 Binary files /dev/null and b/frontend/public/img/icons/gradido/qr-make.png differ diff --git a/frontend/public/img/icons/gradido/qr-scan-pure.png b/frontend/public/img/icons/gradido/qr-scan-pure.png new file mode 100644 index 000000000..88ee90091 Binary files /dev/null and b/frontend/public/img/icons/gradido/qr-scan-pure.png differ diff --git a/frontend/public/img/icons/gradido/qr-scan.png b/frontend/public/img/icons/gradido/qr-scan.png new file mode 100644 index 000000000..ac7185a22 Binary files /dev/null and b/frontend/public/img/icons/gradido/qr-scan.png differ diff --git a/frontend/public/img/theme/angular.jpg b/frontend/public/img/theme/angular.jpg new file mode 100755 index 000000000..d971d0c57 Binary files /dev/null and b/frontend/public/img/theme/angular.jpg differ diff --git a/frontend/public/img/theme/bootstrap.jpg b/frontend/public/img/theme/bootstrap.jpg new file mode 100755 index 000000000..775174f5b Binary files /dev/null and b/frontend/public/img/theme/bootstrap.jpg differ diff --git a/frontend/public/img/theme/img-1-1000x600.jpg b/frontend/public/img/theme/img-1-1000x600.jpg new file mode 100755 index 000000000..8459a8bfb Binary files /dev/null and b/frontend/public/img/theme/img-1-1000x600.jpg differ diff --git a/frontend/public/img/theme/img-1-1000x900.jpg b/frontend/public/img/theme/img-1-1000x900.jpg new file mode 100755 index 000000000..5c7086b1f Binary files /dev/null and b/frontend/public/img/theme/img-1-1000x900.jpg differ diff --git a/frontend/public/img/theme/landing-1.png b/frontend/public/img/theme/landing-1.png new file mode 100755 index 000000000..9f653a444 Binary files /dev/null and b/frontend/public/img/theme/landing-1.png differ diff --git a/frontend/public/img/theme/landing-2.png b/frontend/public/img/theme/landing-2.png new file mode 100755 index 000000000..8663005dc Binary files /dev/null and b/frontend/public/img/theme/landing-2.png differ diff --git a/frontend/public/img/theme/landing-3.png b/frontend/public/img/theme/landing-3.png new file mode 100755 index 000000000..6e901e1c8 Binary files /dev/null and b/frontend/public/img/theme/landing-3.png differ diff --git a/frontend/public/img/theme/profile-cover.jpg b/frontend/public/img/theme/profile-cover.jpg new file mode 100755 index 000000000..bf4aa79f8 Binary files /dev/null and b/frontend/public/img/theme/profile-cover.jpg differ diff --git a/frontend/public/img/theme/react.jpg b/frontend/public/img/theme/react.jpg new file mode 100755 index 000000000..3c76e20c6 Binary files /dev/null and b/frontend/public/img/theme/react.jpg differ diff --git a/frontend/public/img/theme/sketch.jpg b/frontend/public/img/theme/sketch.jpg new file mode 100755 index 000000000..3569f2678 Binary files /dev/null and b/frontend/public/img/theme/sketch.jpg differ diff --git a/frontend/public/img/theme/team-1.jpg b/frontend/public/img/theme/team-1.jpg new file mode 100755 index 000000000..38efdd58c Binary files /dev/null and b/frontend/public/img/theme/team-1.jpg differ diff --git a/frontend/public/img/theme/team-2.jpg b/frontend/public/img/theme/team-2.jpg new file mode 100755 index 000000000..ba5dbc6ce Binary files /dev/null and b/frontend/public/img/theme/team-2.jpg differ diff --git a/frontend/public/img/theme/team-3.jpg b/frontend/public/img/theme/team-3.jpg new file mode 100755 index 000000000..08baf2826 Binary files /dev/null and b/frontend/public/img/theme/team-3.jpg differ diff --git a/frontend/public/img/theme/team-4.jpg b/frontend/public/img/theme/team-4.jpg new file mode 100755 index 000000000..849c2407e Binary files /dev/null and b/frontend/public/img/theme/team-4.jpg differ diff --git a/frontend/public/img/theme/team-5.jpg b/frontend/public/img/theme/team-5.jpg new file mode 100755 index 000000000..38efdd58c Binary files /dev/null and b/frontend/public/img/theme/team-5.jpg differ diff --git a/frontend/public/img/theme/vue.jpg b/frontend/public/img/theme/vue.jpg new file mode 100755 index 000000000..b8e5ad0bc Binary files /dev/null and b/frontend/public/img/theme/vue.jpg differ diff --git a/frontend/public/index.html b/frontend/public/index.html new file mode 100644 index 000000000..556e6f2f2 --- /dev/null +++ b/frontend/public/index.html @@ -0,0 +1,38 @@ + + + + + + + + + Gradido Wallet + + + + + + + +
+ +
+ + + + diff --git a/frontend/public/json-example/admin_card_statistic.json b/frontend/public/json-example/admin_card_statistic.json new file mode 100644 index 000000000..bacdccb5a --- /dev/null +++ b/frontend/public/json-example/admin_card_statistic.json @@ -0,0 +1,36 @@ +{"state":"success", "statisticdata": + [ + { + "i_creation_sum": 29288278.4653, + "i_creation_mon": 68278.4653, + "i_creation_365d": 19288278.4653, + "i_creation_30d": 288278.4653, + "i_creation_14d": 88278.4653, + "i_creation_7d": 3278.4653 + }, + { + "i_transience_sum": 8278.4653, + "i_transience_mon": 8278.4653, + "i_transience_365d": 8278.4653, + "i_transience_30d": 178.4653, + "i_transience_14d": 78.4653, + "i_transience_7d": 8.4653 + }, + { + "i_exchange_sum": 23345.2324, + "i_exchange_mon": 2, + "i_exchange_365d": 2, + "i_exchange_30d": 2, + "i_exchange_14d": 2, + "i_exchange_7d": 2 + }, + { + "i_members_sum": 5398, + "i_members_mon": 234, + "i_members_365d": 2356, + "i_members_30d": 123, + "i_members_14d": 23, + "i_members_7d": 24 + } + ] +} \ No newline at end of file diff --git a/frontend/public/json-example/admin_charts_statistic.json b/frontend/public/json-example/admin_charts_statistic.json new file mode 100644 index 000000000..8c7e6667b --- /dev/null +++ b/frontend/public/json-example/admin_charts_statistic.json @@ -0,0 +1,64 @@ +{"state":"success", "statisticdata": + [ + { + "charts_creation_0_mon": 5635, + "charts_creation_1_mon": 5635, + "charts_creation_2_mon": 5635, + "charts_creation_3_mon": 5635, + "charts_creation_4_mon": 5635, + "charts_creation_5_mon": 5635, + "charts_creation_6_mon": 5635, + "charts_creation_7_mon": 5635, + "charts_creation_8_mon": 5635, + "charts_creation_9_mon": 5635, + "charts_creation_10_mon": 5635, + "charts_creation_11_mon": 5635, + "charts_creation_12_mon": 5635 + }, + { + "charts_transience_0_mon": 5635, + "charts_transience_1_mon": 5635, + "charts_transience_2_mon": 5635, + "charts_transience_3_mon": 5635, + "charts_transience_4_mon": 5635, + "charts_transience_5_mon": 5635, + "charts_transience_6_mon": 5635, + "charts_transience_7_mon": 5635, + "charts_transience_8_mon": 5635, + "charts_transience_9_mon": 5635, + "charts_transience_10_mon": 5635, + "charts_transience_11_mon": 5635, + "charts_transience_12_mon": 5635 + }, + { + "charts_exchange_0_mon": 5635, + "charts_exchange_1_mon": 5635, + "charts_exchange_2_mon": 5635, + "charts_exchange_3_mon": 5635, + "charts_exchange_4_mon": 5635, + "charts_exchange_5_mon": 5635, + "charts_exchange_6_mon": 5635, + "charts_exchange_7_mon": 5635, + "charts_exchange_8_mon": 5635, + "charts_exchange_9_mon": 5635, + "charts_exchange_10_mon": 5635, + "charts_exchange_11_mon": 5635, + "charts_exchange_12_mon": 5635 + }, + { + "charts_members_0_mon": 5635, + "charts_members_1_mon": 5635, + "charts_members_2_mon": 5635, + "charts_members_3_mon": 5635, + "charts_members_4_mon": 5635, + "charts_members_5_mon": 5635, + "charts_members_6_mon": 5635, + "charts_members_7_mon": 5635, + "charts_members_8_mon": 5635, + "charts_members_9_mon": 5635, + "charts_members_10_mon": 5635, + "charts_members_11_mon": 5635, + "charts_members_12_mon": 5635 + } + ] +} \ No newline at end of file diff --git a/frontend/public/json-example/admin_community_statistic.json b/frontend/public/json-example/admin_community_statistic.json new file mode 100644 index 000000000..f083991aa --- /dev/null +++ b/frontend/public/json-example/admin_community_statistic.json @@ -0,0 +1,19 @@ +{"state":"success", "statisticdata": + [ + { + "community_entries1_mon": 5635, + "community_entries2_mon": 5635, + "community_entries3_mon": 5635, + "community_entries4_mon": 5635, + "community_entries5_mon": 5635, + "community_entries6_mon": 5635, + "community_entries7_mon": 5635, + "community_entries8_mon": 5635, + "community_entries9_mon": 5635, + "community_entries0_mon": 5635, + "community_entries10_mon": 5635, + "community_entries11_mon": 5635, + "community_entries12_mon": 5635 + } + ] +} \ No newline at end of file diff --git a/frontend/public/json-example/admin_transaction_list.json b/frontend/public/json-example/admin_transaction_list.json new file mode 100644 index 000000000..a1af47db8 --- /dev/null +++ b/frontend/public/json-example/admin_transaction_list.json @@ -0,0 +1,61 @@ +{"state":"success", "transactions": + [ + { + "name": "Jon Tester", + "email": "jon@example.de", + "type": "send", + "transaction_id": 12, + "date": "29-11-2020", + "balance": 7000, + "memo": "Reperatur Waschbecken", + "pubkey": "abcdefghi123456789" + + }, + { + "name": "Gradido Community", + "email": "gradido@example.de", + "type": "creation", + "transaction_id": 11, + "date": "1-11-2020", + "balance": 10000, + "memo": "Müll gesammelt im Wald", + "pubkey": "abcdefghi123456789" + + }, + { + "name": "Maria Tester", + "email": "maria@example.de", + "type": "receive", + "transaction_id": 7, + "date": "23-10-2020", + "balance": 5000, + "memo": "Spende an Alice ", + "pubkey": "abcdefghi123456789" + + }, + { + "name": "Alice Tester", + "email": "alice@example.de", + "type": "receive", + "transaction_id": 5, + "date": "2-8-2020", + "balance": 1000, + "memo": "Bob hat meinen Müll getrennt", + "pubkey": "abcdefghi123456789" + + }, + { + "name": "Gradido Community", + "email": "gradido@example.de", + "type": "creation", + "transaction_id": 1, + "date": "11-7-2020", + "balance": 10000, + "memo": "Bob hat meinen Müll getrennt", + "pubkey": "abcdefghi123456789" + + } + ], + "transactionExecutingCount": 8750, + "count": 5 +} \ No newline at end of file diff --git a/frontend/public/json-example/admin_transience_list.json b/frontend/public/json-example/admin_transience_list.json new file mode 100644 index 000000000..0cbacfbd8 --- /dev/null +++ b/frontend/public/json-example/admin_transience_list.json @@ -0,0 +1,49 @@ +{"state":"success", "participation": + [ + { + "name": "", + "type": "submitted", + "participation_id": 412, + "date_submitted": "9-12-2020", + "titel": "Lorem Ipsum panta lore es Tastina sero was. ", + "text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ", + "date_participation": "8-12-2020", + "plz_participation": "01099", + "pubkey": "abcdefghi123456789" + }, + { + "name": "", + "type": "in progress", + "participation_id": 312, + "date_submitted": "2-11-2020", + "titel": "Lorem Ipsum panta lore es Tastina sero was. ", + "text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ", + "date_participation": "2-11-2020", + "plz_participation": "01099", + "pubkey": "abcdefghi123456789" + }, + { + "name": "", + "type": "confirmed", + "participation_id": 212, + "date_submitted": "20-10-2020", + "titel": "Lorem Ipsum panta lore es Tastina sero was. ", + "text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ", + "date_participation": "20-10-2020", + "plz_participation": "01099", + "pubkey": "abcdefghi123456789" + }, + { + "name": "", + "type": "rejected", + "participation_id": 142, + "date_submitted": "17-9-2020", + "titel": "Lorem Ipsum panta lore es Tastina sero was. ", + "text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ", + "date_participation": "17-9-2020", + "plz_participation": "01099", + "pubkey": "abcdefghi123456789" + } + ], + "count": 4 +} \ No newline at end of file diff --git a/frontend/public/json-example/admin_userlist.json b/frontend/public/json-example/admin_userlist.json new file mode 100644 index 000000000..a8550716f --- /dev/null +++ b/frontend/public/json-example/admin_userlist.json @@ -0,0 +1,52 @@ +{"state":"success", "admin0userlist": + [ + { + "created": 1578688666, + "disabled": false, + "email": "dervommond@gmail.com", + "email_checked": true, + "first_name": "Max", + "group_alias": "gdd1", + "ident_hash": 2928827813, + "last_name": "Miau", + "public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b", + "role": "admin", + "username": "", + "balance_gdd": 174500, + "balance_gdt": 4500, + "errorCount": 0 + }, + { + "created": 1578685678, + "disabled": false, + "email": "ttwer@gmail.com", + "email_checked": true, + "first_name": "John", + "group_alias": "gdd1", + "ident_hash": 2928827813, + "last_name": "Doe", + "public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71x", + "role": "user", + "username": "", + "balance_gdd": 144500, + "balance_gdt": 0, + "errorCount": 0 + }, + { + "created": 1578635671, + "disabled": false, + "email": "test@gmail.com", + "email_checked": true, + "first_name": "Alice", + "group_alias": "gdd1", + "ident_hash": 4928827813, + "last_name": "Seer", + "public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71a", + "role": "user", + "username": "", + "balance_gdd": 444500, + "balance_gdt": 4500, + "errorCount": 0 + } + ] +} \ No newline at end of file diff --git a/frontend/public/json-example/example.json b/frontend/public/json-example/example.json new file mode 100644 index 000000000..e69de29bb diff --git a/frontend/public/json-example/userdata.json b/frontend/public/json-example/userdata.json new file mode 100644 index 000000000..69f5a8041 --- /dev/null +++ b/frontend/public/json-example/userdata.json @@ -0,0 +1,19 @@ +{"state":"success", "userdata": + [ + { + "created": 1578688666, + "disabled": false, + "email": "dervommond@gmail.com", + "email_checked": true, + "first_name": "Max", + "group_alias": "gdd1", + "ident_hash": 2928827813, + "last_name": "Miau", + "public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b", + "role": "admin", + "username": "", + "balance": 174500, + "errorCount": 0 + } + ] +} \ No newline at end of file diff --git a/frontend/public/json-example/userparticipation.json b/frontend/public/json-example/userparticipation.json new file mode 100644 index 000000000..4e29f117b --- /dev/null +++ b/frontend/public/json-example/userparticipation.json @@ -0,0 +1,45 @@ +{"state":"success", "participation": + [ + { + "type": "submitted", + "participation_id": 412, + "date_submitted": "9-12-2020", + "titel": "Lorem Ipsum panta lore es Tastina sero was. ", + "text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ", + "date_participation": "8-12-2020", + "plz_participation": "01099", + "pubkey": "abcdefghi123456789" + }, + { + "type": "in progress", + "participation_id": 312, + "date_submitted": "2-11-2020", + "titel": "Lorem Ipsum panta lore es Tastina sero was. ", + "text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ", + "date_participation": "2-11-2020", + "plz_participation": "01099", + "pubkey": "abcdefghi123456789" + }, + { + "type": "confirmed", + "participation_id": 212, + "date_submitted": "20-10-2020", + "titel": "Lorem Ipsum panta lore es Tastina sero was. ", + "text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ", + "date_participation": "20-10-2020", + "plz_participation": "01099", + "pubkey": "abcdefghi123456789" + }, + { + "type": "rejected", + "participation_id": 142, + "date_submitted": "17-9-2020", + "titel": "Lorem Ipsum panta lore es Tastina sero was. ", + "text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ", + "date_participation": "17-9-2020", + "plz_participation": "01099", + "pubkey": "abcdefghi123456789" + } + ], + "count": 4 +} \ No newline at end of file diff --git a/frontend/public/json-example/usertransactions.json b/frontend/public/json-example/usertransactions.json new file mode 100644 index 000000000..a1af47db8 --- /dev/null +++ b/frontend/public/json-example/usertransactions.json @@ -0,0 +1,61 @@ +{"state":"success", "transactions": + [ + { + "name": "Jon Tester", + "email": "jon@example.de", + "type": "send", + "transaction_id": 12, + "date": "29-11-2020", + "balance": 7000, + "memo": "Reperatur Waschbecken", + "pubkey": "abcdefghi123456789" + + }, + { + "name": "Gradido Community", + "email": "gradido@example.de", + "type": "creation", + "transaction_id": 11, + "date": "1-11-2020", + "balance": 10000, + "memo": "Müll gesammelt im Wald", + "pubkey": "abcdefghi123456789" + + }, + { + "name": "Maria Tester", + "email": "maria@example.de", + "type": "receive", + "transaction_id": 7, + "date": "23-10-2020", + "balance": 5000, + "memo": "Spende an Alice ", + "pubkey": "abcdefghi123456789" + + }, + { + "name": "Alice Tester", + "email": "alice@example.de", + "type": "receive", + "transaction_id": 5, + "date": "2-8-2020", + "balance": 1000, + "memo": "Bob hat meinen Müll getrennt", + "pubkey": "abcdefghi123456789" + + }, + { + "name": "Gradido Community", + "email": "gradido@example.de", + "type": "creation", + "transaction_id": 1, + "date": "11-7-2020", + "balance": 10000, + "memo": "Bob hat meinen Müll getrennt", + "pubkey": "abcdefghi123456789" + + } + ], + "transactionExecutingCount": 8750, + "count": 5 +} \ No newline at end of file diff --git a/frontend/server.js b/frontend/server.js new file mode 100644 index 000000000..7f91163e5 --- /dev/null +++ b/frontend/server.js @@ -0,0 +1,7 @@ +var express = require('express'); +var serveStatic = require('serve-static'); +var app = express(); +app.use(serveStatic(__dirname + "/dist")); +var port = process.env.PORT || 5000; +app.listen(port); +// console.log('http://localhost:5000 server started.'); \ No newline at end of file diff --git a/frontend/src/App.vue b/frontend/src/App.vue new file mode 100755 index 000000000..b4c26ef8e --- /dev/null +++ b/frontend/src/App.vue @@ -0,0 +1,71 @@ + + + + diff --git a/frontend/src/assets/logo.png b/frontend/src/assets/logo.png new file mode 100644 index 000000000..2939ccf19 Binary files /dev/null and b/frontend/src/assets/logo.png differ diff --git a/frontend/src/assets/scss/argon.scss b/frontend/src/assets/scss/argon.scss new file mode 100644 index 000000000..01a002691 --- /dev/null +++ b/frontend/src/assets/scss/argon.scss @@ -0,0 +1,69 @@ +/*! + +========================================================= +* Bootstrap Vue Gradido Wallet- v0.0.1 +========================================================= + +* Product Page: https://www.gradido.net +* Copyright 2020 Bernd Hückstädt - Gradido (https://www.gradido.net) + +* Coded by www.gradido.net + +========================================================= + +* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +*/ + +// Core + +@import "custom/functions"; +@import "custom/variables"; +@import "custom/mixins"; + +// Bootstrap (4.1.3) components + +@import "~bootstrap/scss/root"; +@import "~bootstrap/scss/reboot"; +@import "~bootstrap/scss/type"; +@import "~bootstrap/scss/images"; +@import "~bootstrap/scss/code"; +@import "~bootstrap/scss/grid"; +@import "~bootstrap/scss/tables"; +@import "~bootstrap/scss/forms"; +@import "~bootstrap/scss/buttons"; +@import "~bootstrap/scss/transitions"; +@import "~bootstrap/scss/dropdown"; +@import "~bootstrap/scss/button-group"; +@import "~bootstrap/scss/input-group"; +@import "~bootstrap/scss/custom-forms"; +@import "~bootstrap/scss/nav"; +@import "~bootstrap/scss/navbar"; +@import "~bootstrap/scss/card"; +@import "~bootstrap/scss/breadcrumb"; +@import "~bootstrap/scss/pagination"; +@import "~bootstrap/scss/badge"; +@import "~bootstrap/scss/jumbotron"; +@import "~bootstrap/scss/alert"; +@import "~bootstrap/scss/progress"; +@import "~bootstrap/scss/media"; +@import "~bootstrap/scss/list-group"; +@import "~bootstrap/scss/close"; +@import "~bootstrap/scss/modal"; +@import "~bootstrap/scss/tooltip"; +@import "~bootstrap/scss/popover"; +@import "~bootstrap/scss/carousel"; +@import "~bootstrap/scss/utilities"; +@import "~bootstrap/scss/print"; + +// Argon utilities and components + +@import "custom/reboot"; +@import "custom/utilities"; +@import "custom/components"; + +// Vendor (Plugins) + +@import "custom/vendors"; + + diff --git a/frontend/src/assets/scss/core/alerts/_alert-dismissible.scss b/frontend/src/assets/scss/core/alerts/_alert-dismissible.scss new file mode 100644 index 000000000..aa15ad1db --- /dev/null +++ b/frontend/src/assets/scss/core/alerts/_alert-dismissible.scss @@ -0,0 +1,39 @@ +// +// Dismissible alert +// + +.alert-dismissible { + .close { + top: 50%; + right: $alert-padding-x; + padding: 0; + transform: translateY(-50%); + color: rgba($white, .6); + opacity: 1; + + &:hover, + &:focus { + color: rgba($white, .9); + opacity: 1 !important; + } + + @include media-breakpoint-down(xs) { + top: 1rem; + right: .5rem; + } + + &>span:not(.sr-only) { + font-size: 1.5rem; + background-color: transparent; + color: rgba($white, .6); + } + + &:hover, + &:focus { + &>span:not(.sr-only) { + background-color: transparent; + color: rgba($white, .9); + } + } + } +} diff --git a/frontend/src/assets/scss/core/alerts/_alert.scss b/frontend/src/assets/scss/core/alerts/_alert.scss new file mode 100644 index 000000000..a9bc230a4 --- /dev/null +++ b/frontend/src/assets/scss/core/alerts/_alert.scss @@ -0,0 +1,46 @@ +// +// Alert +// + +.alert { + font-size: $font-size-sm; +} + +// Alert heading + +.alert-heading { + font-weight: $font-weight-bold; + font-size: $h4-font-size; + margin-top: .15rem; +} + + +// Alert icon +.alert-icon { + font-size: 1.25rem; + margin-right: 1.25rem; + display: inline-block; + vertical-align: middle; + + i.ni { + position: relative; + top: 1px; + } +} + + +// Alert text next to an alert icon +.alert-text { + display: inline-block; + vertical-align: middle; +} + + +// Alert links + +[class*="alert-"] { + .alert-link { + color: $white; + border-bottom: 1px dotted rgba($white, .5); + } +} diff --git a/frontend/src/assets/scss/core/avatars/_avatar-group.scss b/frontend/src/assets/scss/core/avatars/_avatar-group.scss new file mode 100644 index 000000000..0fcf4cf21 --- /dev/null +++ b/frontend/src/assets/scss/core/avatars/_avatar-group.scss @@ -0,0 +1,22 @@ +// +// Avatar group +// + +// General styles + +.avatar-group { + .avatar { + position: relative; + z-index: 2; + border: 2px solid $card-bg; + + &:hover { + z-index: 3; + } + } + + .avatar + .avatar { + margin-left: -1rem; + + } +} diff --git a/frontend/src/assets/scss/core/avatars/_avatar.scss b/frontend/src/assets/scss/core/avatars/_avatar.scss new file mode 100644 index 000000000..480fa8d8e --- /dev/null +++ b/frontend/src/assets/scss/core/avatars/_avatar.scss @@ -0,0 +1,42 @@ +// +// Avatar +// + +// General styles + +.avatar { + color: $white; + background-color: $gray-500; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 1rem; + border-radius: 50%; + height: 48px; + width: 48px; + + img { + width: 100%; + border-radius: 50%; + } + + + .avatar-content { + display: inline-block; + margin-left: .75rem; + } +} + + +// Avatar size variations + +.avatar-lg { + width: 58px; + height: 58px; + font-size: $font-size-sm; +} + +.avatar-sm { + width: 36px; + height: 36px; + font-size: $font-size-sm; +} diff --git a/frontend/src/assets/scss/core/badges/_badge-circle.scss b/frontend/src/assets/scss/core/badges/_badge-circle.scss new file mode 100644 index 000000000..88a5d5e5d --- /dev/null +++ b/frontend/src/assets/scss/core/badges/_badge-circle.scss @@ -0,0 +1,17 @@ +// +// Circle badge +// + + +// General styles + +.badge-circle { + text-align: center; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 50%; + width: 2rem; + height: 2rem; + font-size: .875rem; +} diff --git a/frontend/src/assets/scss/core/badges/_badge-dot.scss b/frontend/src/assets/scss/core/badges/_badge-dot.scss new file mode 100644 index 000000000..1ed6ffa86 --- /dev/null +++ b/frontend/src/assets/scss/core/badges/_badge-dot.scss @@ -0,0 +1,42 @@ +// +// Dot badge +// + + +// General styles + +.badge-dot { + padding-left: 0; + padding-right: 0; + background: transparent; + font-weight: $font-weight-normal; + font-size: $font-size-sm; + text-transform: none; + + strong { + color: $gray-800; + } + + i { + display: inline-block; + vertical-align: middle; + width: .375rem; + height: .375rem; + border-radius: 50%; + margin-right: .375rem; + } + + &.badge-md { + i { + width: .5rem; + height: .5rem; + } + } + + &.badge-lg { + i { + width: .625rem; + height: .625rem; + } + } +} diff --git a/frontend/src/assets/scss/core/badges/_badge.scss b/frontend/src/assets/scss/core/badges/_badge.scss new file mode 100644 index 000000000..b0d626a1e --- /dev/null +++ b/frontend/src/assets/scss/core/badges/_badge.scss @@ -0,0 +1,55 @@ +// +// Badge +// + + +// General styles + +.badge { + text-transform: $badge-text-transfom; + + a { + color: $white; + } +} + + +// Size variations + +.badge-md { + padding: .65em 1em; +} + +.badge-lg { + padding: .85em 1.375em; +} + + +// Multiple inline badges + +.badge-inline { + margin-right: .625rem; + + + span { + top: 2px; + position: relative; + + > a { + text-decoration: underline; + } + } +} + + +// Badge spacing inside a btn with some text + +.btn { + .badge { + &:not(:first-child) { + margin-left: .5rem; + } + &:not(:last-child) { + margin-right: .5rem; + } + } +} diff --git a/frontend/src/assets/scss/core/buttons/_button-brand.scss b/frontend/src/assets/scss/core/buttons/_button-brand.scss new file mode 100644 index 000000000..82a3dd7bb --- /dev/null +++ b/frontend/src/assets/scss/core/buttons/_button-brand.scss @@ -0,0 +1,12 @@ +// +// Brand buttons +// + + +// Color variations + +@each $color, $value in $brand-colors { + .btn-#{$color} { + @include button-variant($value, $value); + } +} diff --git a/frontend/src/assets/scss/core/buttons/_button-icon.scss b/frontend/src/assets/scss/core/buttons/_button-icon.scss new file mode 100644 index 000000000..1aceddbf3 --- /dev/null +++ b/frontend/src/assets/scss/core/buttons/_button-icon.scss @@ -0,0 +1,92 @@ +// +// Icon buttons +// + +.btn-icon { + .btn-inner--icon { + img { + width: 20px; + } + } + + .btn-inner--text:not(:first-child) { + margin-left: 0.75em; + } + + .btn-inner--text:not(:last-child) { + margin-right: 0.75em; + } +} + + +// Button only with icon and NO text + +.btn-icon-only { + width: 2.375rem; + height: 2.375rem; + padding: 0; +} + +a.btn-icon-only { + line-height: 2.5; +} + +.btn-icon-only.btn-sm { + width: 2rem; + height: 2rem; +} + + +// +// Clipboard button +// dedicated element for copying icons +// + +.btn-icon-clipboard { + margin: 0; + padding: 1.5rem; + font-size: $font-size-base; + font-weight: $font-weight-normal; + line-height: 1.25; + color: $gray-800; + background-color: $gray-100; + border-radius: $border-radius; + border: 0; + text-align: left; + font-family: inherit; + display: inline-block; + vertical-align: middle; + text-decoration: none; + -moz-appearance: none; + cursor: pointer; + width: 100%; + margin: .5rem 0; + + &:hover { + background-color: $white; + box-shadow: rgba(0, 0, 0, .1) 0 0 0 1px, rgba(0, 0, 0, .1) 0 4px 16px; + } + + > div { + align-items: center; + display: flex; + } + + i { + box-sizing: content-box; + color: theme-color("primary"); + vertical-align: middle; + font-size: 1.5rem; + } + + span { + display: inline-block; + font-size: 0.875rem; + line-height: 1.5; + margin-left: 16px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + vertical-align: middle; + } +} diff --git a/frontend/src/assets/scss/core/buttons/_button.scss b/frontend/src/assets/scss/core/buttons/_button.scss new file mode 100644 index 000000000..9c19674b8 --- /dev/null +++ b/frontend/src/assets/scss/core/buttons/_button.scss @@ -0,0 +1,91 @@ +// +// Icon buttons +// + +// General styles + +.btn { + position: relative; + text-transform: $btn-text-transform; + transition: $transition-base; + letter-spacing: $btn-letter-spacing; + font-size: $input-btn-font-size; + will-change: transform; + + &:hover { + @include box-shadow($btn-hover-box-shadow); + transform: translateY($btn-hover-translate-y); + } + + &:not(:last-child) { + margin-right: .5rem; + } + + + // Icons + + i:not(:first-child), + svg:not(:first-child) { + margin-left: .5rem; + } + + i:not(:last-child), + svg:not(:last-child) { + margin-right: .5rem; + } +} + + +// Remove translateY and margin animation when btn is included in a btn-group or input-group + +.btn-group, +.input-group { + .btn { + margin-right: 0; + transform: translateY(0); + } +} + + +// Size variations + +.btn-sm { + font-size: $input-btn-font-size-sm; +} + +.btn-lg { + font-size: $input-btn-font-size-lg; +} + + +// Some quick fixes (to revise) + +// Fixes +[class*="btn-outline-"] { + border-width: 1px; +} + +.btn-outline-secondary { + color: darken(theme-color("secondary"), 50%); +} + +.btn-inner--icon { + i:not(.fa) { + position: relative; + top: 2px; + } +} + +.btn-link { + font-weight: $btn-font-weight; + box-shadow: none; + + &:hover { + box-shadow: none; + transform: none; + } +} + +.btn-neutral { + color: theme-color("primary"); +} diff --git a/frontend/src/assets/scss/core/cards/_card-animations.scss b/frontend/src/assets/scss/core/cards/_card-animations.scss new file mode 100644 index 000000000..4da8b7877 --- /dev/null +++ b/frontend/src/assets/scss/core/cards/_card-animations.scss @@ -0,0 +1,10 @@ +// +// Card with hover animations +// + +.card-lift--hover { + &:hover { + transform: translateY(-20px); + @include transition($transition-base); + } +} diff --git a/frontend/src/assets/scss/core/cards/_card-blockquote.scss b/frontend/src/assets/scss/core/cards/_card-blockquote.scss new file mode 100644 index 000000000..066bae597 --- /dev/null +++ b/frontend/src/assets/scss/core/cards/_card-blockquote.scss @@ -0,0 +1,17 @@ +// +// Card with blockquote +// + +.card-blockquote { + padding: 2rem; + position: relative; + + .svg-bg { + display: block; + width: 100%; + height: 95px; + position: absolute; + top: -94px; + left: 0; + } +} diff --git a/frontend/src/assets/scss/core/cards/_card-profile.scss b/frontend/src/assets/scss/core/cards/_card-profile.scss new file mode 100644 index 000000000..920f41155 --- /dev/null +++ b/frontend/src/assets/scss/core/cards/_card-profile.scss @@ -0,0 +1,49 @@ +// +// Profile card +// + +.card-profile-image { + position: relative; + + img { + max-width: 180px; + border-radius: $border-radius; + @extend .shadow; + transform: translate(-50%,-30%); + position: absolute; + left: 50%; + transition: $transition-base; + + &:hover { + transform: translate(-50%, -33%); + } + } +} + +.card-profile-stats { + padding: 1rem 0; + + > div { + text-align: center; + margin-right: 1rem; + padding: .875rem; + + &:last-child { + margin-right: 0; + } + + .heading { + font-size: 1.1rem; + font-weight: bold; + display: block; + } + .description { + font-size: .875rem; + color: $gray-500; + } + } +} + +.card-profile-actions { + padding: .875rem; +} diff --git a/frontend/src/assets/scss/core/cards/_card-stats.scss b/frontend/src/assets/scss/core/cards/_card-stats.scss new file mode 100644 index 000000000..1459304b7 --- /dev/null +++ b/frontend/src/assets/scss/core/cards/_card-stats.scss @@ -0,0 +1,16 @@ +// +// Card stats +// + +.card-stats { + .card-body { + padding: 1rem 1.5rem; + } + + .card-status-bullet { + position: absolute; + top: 0; + right: 0; + transform: translate(50%, -50%); + } +} diff --git a/frontend/src/assets/scss/core/cards/_card.scss b/frontend/src/assets/scss/core/cards/_card.scss new file mode 100644 index 000000000..a593e4c3c --- /dev/null +++ b/frontend/src/assets/scss/core/cards/_card.scss @@ -0,0 +1,8 @@ +// +// Card +// + + +.card-translucent { + background-color: rgba(18, 91, 152, 0.08); +} diff --git a/frontend/src/assets/scss/core/charts/_chart.scss b/frontend/src/assets/scss/core/charts/_chart.scss new file mode 100644 index 000000000..9ea3ecead --- /dev/null +++ b/frontend/src/assets/scss/core/charts/_chart.scss @@ -0,0 +1,69 @@ +// +// Chart +// + +.chart { + position: relative; + height: $chart-height; +} + + +// Size variations + +.chart-sm { + height: $chart-height-sm; +} + + +// Legend + +.chart-legend { + display: flex; + justify-content: center; + margin-top: $chart-legend-margin-top; + font-size: $chart-legend-font-size; + text-align: center; + color: $chart-legend-color; +} + +.chart-legend-item { + display: inline-flex; + align-items: center; + + + .chart-legend-item { + margin-left: 1rem; + } +} + +.chart-legend-indicator { + display: inline-block; + width: 0.5rem; + height: 0.5rem; + margin-right: 0.375rem; + border-radius: 50%; +} + + +// Tooltip + +#chart-tooltip { + z-index: 0; + + .arrow { + top: 100%; + left: 50%; + transform: translateX(-50%) translateX(-.5rem); + } +} + + +// Chart info overlay + +.chart-info-overlay { + position: absolute; + top: 0; + left: 5%; + max-width: 350px; + padding: 20px; + z-index: 1; +} diff --git a/frontend/src/assets/scss/core/close/_close.scss b/frontend/src/assets/scss/core/close/_close.scss new file mode 100644 index 000000000..2c0672ae1 --- /dev/null +++ b/frontend/src/assets/scss/core/close/_close.scss @@ -0,0 +1,34 @@ +// +// Close +// + +.close { + @if $enable-transitions { + transition: $transition-base; + } + + &>span:not(.sr-only) { + background-color: $close-bg; + color: $close-color; + line-height: 17px; + height: 1.25rem; + width: 1.25rem; + border-radius: 50%; + font-size: 1.25rem; + display: block; + @if $enable-transitions { + transition: $transition-base; + } + } + + &:hover, + &:focus { + background-color: $close-hover-bg; + color: $close-hover-color; + outline: none; + + span:not(.sr-only) { + background-color: $close-hover-bg; + } + } +} diff --git a/frontend/src/assets/scss/core/custom-forms/_custom-checkbox.scss b/frontend/src/assets/scss/core/custom-forms/_custom-checkbox.scss new file mode 100644 index 000000000..e808b5bb9 --- /dev/null +++ b/frontend/src/assets/scss/core/custom-forms/_custom-checkbox.scss @@ -0,0 +1,37 @@ +// +// Custom checkbox +// + +.custom-checkbox { + .custom-control-input ~ .custom-control-label { + cursor: pointer; + font-size: $font-size-sm; + } + + .custom-control-input { + &:checked { + ~ .custom-control-label { + &::before { + border-color: $custom-control-indicator-checked-border-color; + } + &::after { + background-image: $custom-checkbox-indicator-icon-checked; + } + } + } + + &:disabled { + ~ .custom-control-label { + &::before { + border-color: $custom-control-indicator-disabled-bg; + } + } + + &:checked { + &::before { + border-color: $custom-control-indicator-checked-disabled-bg; + } + } + } + } +} diff --git a/frontend/src/assets/scss/core/custom-forms/_custom-control.scss b/frontend/src/assets/scss/core/custom-forms/_custom-control.scss new file mode 100644 index 000000000..28610029d --- /dev/null +++ b/frontend/src/assets/scss/core/custom-forms/_custom-control.scss @@ -0,0 +1,51 @@ +// +// Custom control +// additional styles for custom checkboxes, radios and other +// + +.custom-control-label { + // Background-color and (when enabled) gradient + &::before { + border: $custom-control-indicator-border-width solid $custom-control-indicator-border-color; + @if $enable-transitions { + transition: $input-transition; + } + } + + span { + position: relative; + top: 2px; + } +} + +.custom-control-label { + margin-bottom: 0; +} + + +// Alternative style + +.custom-control-alternative { + .custom-control-label { + // Background-color and (when enabled) gradient + &::before { + border: 0; + box-shadow: $input-alternative-box-shadow; + } + } + + .custom-control-input { + &:checked { + ~ .custom-control-label { + &::before { + box-shadow: $input-focus-alternative-box-shadow; + } + } + } + + &:active~.custom-control-label::before, + &:focus~.custom-control-label::before { + box-shadow: $input-alternative-box-shadow; + } + } +} diff --git a/frontend/src/assets/scss/core/custom-forms/_custom-form.scss b/frontend/src/assets/scss/core/custom-forms/_custom-form.scss new file mode 100644 index 000000000..e808b5bb9 --- /dev/null +++ b/frontend/src/assets/scss/core/custom-forms/_custom-form.scss @@ -0,0 +1,37 @@ +// +// Custom checkbox +// + +.custom-checkbox { + .custom-control-input ~ .custom-control-label { + cursor: pointer; + font-size: $font-size-sm; + } + + .custom-control-input { + &:checked { + ~ .custom-control-label { + &::before { + border-color: $custom-control-indicator-checked-border-color; + } + &::after { + background-image: $custom-checkbox-indicator-icon-checked; + } + } + } + + &:disabled { + ~ .custom-control-label { + &::before { + border-color: $custom-control-indicator-disabled-bg; + } + } + + &:checked { + &::before { + border-color: $custom-control-indicator-checked-disabled-bg; + } + } + } + } +} diff --git a/frontend/src/assets/scss/core/custom-forms/_custom-radio.scss b/frontend/src/assets/scss/core/custom-forms/_custom-radio.scss new file mode 100644 index 000000000..3ce26f81a --- /dev/null +++ b/frontend/src/assets/scss/core/custom-forms/_custom-radio.scss @@ -0,0 +1,37 @@ +// +// Custom radio +// + +.custom-radio { + .custom-control-input ~ .custom-control-label { + cursor: pointer; + font-size: $font-size-sm; + } + + .custom-control-input { + &:checked { + ~ .custom-control-label { + &::before { + border-color: $custom-control-indicator-checked-border-color; + } + &::after { + background-image: $custom-radio-indicator-icon-checked; + } + } + } + + &:disabled { + ~ .custom-control-label { + &::before { + border-color: $custom-control-indicator-disabled-bg; + } + } + + &:checked { + &::before { + border-color: $custom-control-indicator-checked-disabled-bg; + } + } + } + } +} diff --git a/frontend/src/assets/scss/core/custom-forms/_custom-toggle.scss b/frontend/src/assets/scss/core/custom-forms/_custom-toggle.scss new file mode 100644 index 000000000..88da14583 --- /dev/null +++ b/frontend/src/assets/scss/core/custom-forms/_custom-toggle.scss @@ -0,0 +1,66 @@ +// +// Custom toggle +// + +.custom-toggle { + position: relative; + display: inline-block; + width: $custom-toggle-width; + height: 1.5rem; + + input { + display: none; + + &:checked { + + .custom-toggle-slider { + border: $custom-control-indicator-border-width solid $custom-control-indicator-checked-border-color; + + &:before { + background: $custom-toggle-checked-bg; + transform: translateX(1.625rem); + } + } + } + + &:disabled { + + .custom-toggle-slider { + border: $custom-control-indicator-border-width solid $custom-control-indicator-disabled-bg; + } + + &:checked { + + .custom-toggle-slider { + border: $custom-control-indicator-border-width solid $custom-control-indicator-disabled-bg; + + &:before { + background-color: lighten($custom-control-indicator-checked-bg, 10%); + } + } + } + } + } +} + +.custom-toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + border: $custom-control-indicator-border-width solid $input-border-color; + border-radius: 34px !important; + background-color: transparent; + + + &:before { + position: absolute; + content: ""; + height: 18px; + width: 18px; + left: 2px; + bottom: 2px; + border-radius: 50% !important; + background-color: $custom-toggle-slider-bg; + transition: $input-transition; + } +} diff --git a/frontend/src/assets/scss/core/dropdowns/_dropdown.scss b/frontend/src/assets/scss/core/dropdowns/_dropdown.scss new file mode 100644 index 000000000..6d3106e9f --- /dev/null +++ b/frontend/src/assets/scss/core/dropdowns/_dropdown.scss @@ -0,0 +1,79 @@ +// +// Dropdown +// + +// General styles + +.dropdown, +.dropup, +.dropright, +.dropleft { + display: inline-block; +} + +.dropdown-menu { + min-width: 12rem; + + .dropdown-item { + padding: .5rem 1rem; + font-size: $font-size-sm; + > i, + > svg { + margin-right: 1rem; + font-size: 1rem; + vertical-align: -17%; + } + } +} + +.dropdown-header { + padding-left: 1rem; + padding-right: 1rem; + color: $gray-100; + font-size: .625rem; + text-transform: uppercase; + font-weight: 700; +} + + +// Media components inside dropdown link + +.dropdown-menu { + a.media { + + > div { + &:first-child { + line-height: 1; + } + } + + p { + color: $gray-600; + } + + &:hover { + .heading, + p { + color: theme-color("default") !important; + } + } + } +} + + +// Size variations + +.dropdown-menu-sm { + min-width: 100px; + border: $border-radius-lg; +} + +.dropdown-menu-lg { + min-width: 260px; + border-radius: $border-radius-lg; +} + +.dropdown-menu-xl { + min-width: 450px; + border-radius: $border-radius-lg; +} diff --git a/frontend/src/assets/scss/core/footers/_footer.scss b/frontend/src/assets/scss/core/footers/_footer.scss new file mode 100644 index 000000000..a34180e9b --- /dev/null +++ b/frontend/src/assets/scss/core/footers/_footer.scss @@ -0,0 +1,98 @@ +// +// Footer +// + + +// General styles + +.footer { + background: $footer-bg; + padding: $footer-padding-y $footer-padding-x; + + .col-footer { + .heading { + color: $footer-heading-color; + letter-spacing: 0; + font-size: $footer-heading-font-size; + text-transform: uppercase; + font-weight: $font-weight-bold; + margin-bottom: 1rem; + } + } + + .nav .nav-item .nav-link, + .footer-link { + color: $footer-link-color !important; + + &:hover { + color: $footer-link-hover-color !important; + } + } + + .list-unstyled li a { + display: inline-block; + padding: .125rem 0; + color: $footer-link-color; + font-size: $footer-link-font-size; + + &:hover { + color: $footer-link-hover-color; + } + } + + .copyright { + font-size: $font-size-sm; + } +} + + +// Dark footer + +.footer-dark { + .col-footer .heading { + color: $white; + } +} + + +// Footer nav used for copyright and some links, but not limited to this + +.nav-footer { + .nav-link { + font-size: $font-size-sm; + } + + .nav-item:last-child { + .nav-link { + padding-right: 0; + } + } +} + + +// Footer with cards over + +.footer.has-cards { + overflow: hidden; + padding-top: 500px; + margin-top: -420px; + position: relative; + background: transparent; + pointer-events: none; + + &:before { + content: ""; + position: absolute; + left: 0; + right: 0; + top: 600px; + height: 2000px; + background: theme-color("secondary"); + transform: skew(0,-8deg); + } + + .container { + pointer-events: auto; + position: relative; + } +} diff --git a/frontend/src/assets/scss/core/forms/_form-validation.scss b/frontend/src/assets/scss/core/forms/_form-validation.scss new file mode 100644 index 000000000..bb97e39fa --- /dev/null +++ b/frontend/src/assets/scss/core/forms/_form-validation.scss @@ -0,0 +1,71 @@ +// +// Form validation +// + +// Validation + +.has-success, +.has-danger { + position: relative; + + &:after, { + width: 19px; + height: 19px; + line-height: 19px; + text-align: center; + font-family: 'NucleoIcons'; + display: inline-block; + position: absolute; + right: 15px; + top: 2px; + transform: translateY(50%); + border-radius: 50%; + font-size: 9px; + opacity: 1; + } +} + +.has-success { + &:after { + content: "\ea26"; + color: daken($form-feedback-valid-color, 18%); + background-color: $form-feedback-valid-bg; + } + + .form-control { + background-color: $input-focus-bg; + + &:focus { + border-color: $input-focus-border-color; + } + + + // Placeholder + + &::placeholder { + color: $form-feedback-valid-color; + } + } +} + +.has-danger { + &:after { + content: "\ea53"; + color: daken($form-feedback-invalid-color, 18%); + background-color: $form-feedback-invalid-bg; + } + + .form-control { + background-color: $input-focus-bg; + + &:focus { + border-color: $input-focus-border-color; + } + + // Placeholder + + &::placeholder { + color: $form-feedback-invalid-color; + } + } +} diff --git a/frontend/src/assets/scss/core/forms/_form.scss b/frontend/src/assets/scss/core/forms/_form.scss new file mode 100644 index 000000000..8afeb8787 --- /dev/null +++ b/frontend/src/assets/scss/core/forms/_form.scss @@ -0,0 +1,78 @@ +// +// Forms +// + + +// Labels + +.form-control-label { + color: $gray-700; + font-size: $font-size-sm; + font-weight: $font-weight-bold; +} + + +// Text inputs + +.form-control { + font-size: $input-btn-font-size; + + &:focus { + &::placeholder { + color: $input-focus-placeholder-color; + } + } +} + + +// Textarea + +textarea[resize="none"] { + resize: none!important; +} + +textarea[resize="both"] { + resize: both!important; +} + +textarea[resize="vertical"] { + resize: vertical!important; +} + +textarea[resize="horizontal"] { + resize: horizontal!important; +} + + +// Form input variations + +// Muted input + +.form-control-muted { + background-color: $input-muted-bg; + border-color: $input-muted-bg; + box-shadow: none; + + &:focus { + background-color: $input-focus-muted-bg; + } +} + + +// Alternative input + +.form-control-alternative { + box-shadow: $input-alternative-box-shadow; + border: 0; + transition: box-shadow .15s ease; + + &:focus { + box-shadow: $input-focus-alternative-box-shadow; + } +} + +// Size variations: Fixes to the bootstrap defaults + +.form-control-lg { + font-size: $font-size-base; +} diff --git a/frontend/src/assets/scss/core/forms/_input-group.scss b/frontend/src/assets/scss/core/forms/_input-group.scss new file mode 100644 index 000000000..1ab48cffe --- /dev/null +++ b/frontend/src/assets/scss/core/forms/_input-group.scss @@ -0,0 +1,70 @@ +// +// Input group +// + +.input-group { + box-shadow: $input-box-shadow; + border-radius: $input-border-radius; + transition: $transition-base; + + .form-control { + box-shadow: none; + + &:not(:first-child) { + border-left: 0; + padding-left: 0; + } + &:not(:last-child) { + border-right: 0; + padding-right: 0; + } + &:focus { + box-shadow: none; + } + } +} + +.input-group-text { + transition: $input-transition; +} + + +// Alternative input groups related to .form-control-alternative + + +.input-group-alternative { + box-shadow: $input-alternative-box-shadow; + border: 0; + transition: box-shadow .15s ease; + + .form-control, + .input-group-text { + border: 0; + box-shadow: none; + } +} + +.focused { + .input-group-alternative { + box-shadow: $input-focus-alternative-box-shadow !important; + } +} + + +// .focus class is applied dinamycally from theme.js + +.focused { + .input-group { + box-shadow: $input-focus-box-shadow; + } + + .input-group-text { + color: $input-group-addon-focus-color; + background-color: $input-group-addon-focus-bg; + border-color: $input-group-addon-focus-border-color; + } + + .form-control { + border-color: $input-group-addon-focus-border-color; + } +} diff --git a/frontend/src/assets/scss/core/headers/_header.scss b/frontend/src/assets/scss/core/headers/_header.scss new file mode 100644 index 000000000..3b0e9d2f5 --- /dev/null +++ b/frontend/src/assets/scss/core/headers/_header.scss @@ -0,0 +1,7 @@ +// +// Header +// + +.header { + position: relative; +} diff --git a/frontend/src/assets/scss/core/icons/_icon-shape.scss b/frontend/src/assets/scss/core/icons/_icon-shape.scss new file mode 100644 index 000000000..1747871ff --- /dev/null +++ b/frontend/src/assets/scss/core/icons/_icon-shape.scss @@ -0,0 +1,42 @@ +// +// Icon shape +// + + +.icon-shape { + padding: 12px; + text-align: center; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 50%; + + + i, svg { + font-size: 1.25rem; + } + + &.icon-lg { + i, svg { + font-size: 1.625rem; + } + } + + &.icon-sm { + i, svg { + font-size: .875rem; + } + } + + svg { + width: 30px; + height: 30px; + } + +} + +@each $color, $value in $theme-colors { + .icon-shape-#{$color} { + @include icon-shape-variant(theme-color($color)); + } +} diff --git a/frontend/src/assets/scss/core/icons/_icon.scss b/frontend/src/assets/scss/core/icons/_icon.scss new file mode 100644 index 000000000..f7ed0de3c --- /dev/null +++ b/frontend/src/assets/scss/core/icons/_icon.scss @@ -0,0 +1,65 @@ +// +// Icon +// + +.icon { + width: $icon-size; + height: $icon-size; + + i, svg { + font-size: $icon-size - .75; + } + + + .icon-text { + padding-left: 1rem; + width: calc(100% - #{$icon-size} - 1); + } +} + + +// Extra large icons + +.icon-xl { + width: $icon-size-xl; + height: $icon-size-xl; + + i, svg { + font-size: $icon-size-xl - .75; + } + + + .icon-text { + width: calc(100% - #{$icon-size-xl} - 1); + } +} + + +// Large icons + +.icon-lg { + width: $icon-size-lg; + height: $icon-size-lg; + + i, svg { + font-size: $icon-size-lg - .75; + } + + + .icon-text { + width: calc(100% - #{$icon-size-lg} - 1); + } +} + + +// Small icon + +.icon-sm { + width: $icon-size-sm; + height: $icon-size-sm; + + i, svg { + font-size: $icon-size-sm - .75; + } + + + .icon-text { + width: calc(100% - #{$icon-size-sm} - 1); + } +} diff --git a/frontend/src/assets/scss/core/list-groups/_list-group.scss b/frontend/src/assets/scss/core/list-groups/_list-group.scss new file mode 100644 index 000000000..0aa5cde63 --- /dev/null +++ b/frontend/src/assets/scss/core/list-groups/_list-group.scss @@ -0,0 +1,46 @@ +// +// List group +// + + +// Space list items + +.list-group-space { + .list-group-item { + margin-bottom: 1.5rem; + @include border-radius($list-group-border-radius); + } +} + + +// Extended list group components + +.list-group-img { + width: 3rem; + height: 3rem; + border-radius: 50%; + vertical-align: top; + margin: -.1rem 1.2rem 0 -.2rem; +} + +.list-group-content { + flex: 1; + min-width: 0; + + > p { + color: $gray-500; + line-height: 1.5; + margin: .2rem 0 0; + } +} + +.list-group-heading { + font-size: $font-size-base; + color: $gray-800; + + > small { + float: right; + color: $gray-500; + font-weight: 500; + } +} diff --git a/frontend/src/assets/scss/core/maps/_map.scss b/frontend/src/assets/scss/core/maps/_map.scss new file mode 100644 index 000000000..6c9cda7af --- /dev/null +++ b/frontend/src/assets/scss/core/maps/_map.scss @@ -0,0 +1,10 @@ +// +// Map +// + +.map-canvas { + position: relative; + width: 100%; + height: $map-height; + border-radius: $border-radius; +} diff --git a/frontend/src/assets/scss/core/masks/_mask.scss b/frontend/src/assets/scss/core/masks/_mask.scss new file mode 100644 index 000000000..9df8ba0a4 --- /dev/null +++ b/frontend/src/assets/scss/core/masks/_mask.scss @@ -0,0 +1,12 @@ +// +// Mask +// + +.mask { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + @include transition($transition-base); +} diff --git a/frontend/src/assets/scss/core/mixins/_alert.scss b/frontend/src/assets/scss/core/mixins/_alert.scss new file mode 100644 index 000000000..1dbe85b61 --- /dev/null +++ b/frontend/src/assets/scss/core/mixins/_alert.scss @@ -0,0 +1,13 @@ +@mixin alert-variant($background, $border, $color) { + color: color-yiq($background); + @include gradient-bg($background); + border-color: $border; + + hr { + border-top-color: darken($border, 5%); + } + + .alert-link { + color: darken($color, 10%); + } +} \ No newline at end of file diff --git a/frontend/src/assets/scss/core/mixins/_background-variant.scss b/frontend/src/assets/scss/core/mixins/_background-variant.scss new file mode 100644 index 000000000..1b87864f1 --- /dev/null +++ b/frontend/src/assets/scss/core/mixins/_background-variant.scss @@ -0,0 +1,30 @@ +// Contextual backgrounds +@mixin bg-variant($parent, $color, $ignore-warning: true) { + #{$parent} { + background-color: $color !important; + } + a#{$parent}, + button#{$parent} { + @include hover-focus { + background-color: darken($color, 10%) !important; + } + } +} + +@mixin bg-gradient-variant($parent, $color, $ignore-warning: true) { + #{$parent} { + background: linear-gradient(87deg, $color 0, adjust-hue($color, 25%) 100%) !important; + } +} + +@mixin bg-translucent-variant($parent, $color, $ignore-warning: true) { + #{$parent} { + background-color: darken(rgba($color, $translucent-color-opacity), 7%) !important; + } + a#{$parent}, + button#{$parent} { + @include hover-focus { + background-color: darken(rgba($color, $translucent-color-opacity), 12%) !important; + } + } +} diff --git a/frontend/src/assets/scss/core/mixins/_badge.scss b/frontend/src/assets/scss/core/mixins/_badge.scss new file mode 100644 index 000000000..f19044f91 --- /dev/null +++ b/frontend/src/assets/scss/core/mixins/_badge.scss @@ -0,0 +1,12 @@ +@mixin badge-variant($bg) { + color: saturate(darken($bg, 10%), 10); + background-color: transparentize(lighten($bg, 25%), .5); + + &[href] { + @include hover-focus { + color: color-yiq($bg); + text-decoration: none; + background-color: darken($bg, 10%); + } + } +} diff --git a/frontend/src/assets/scss/core/mixins/_buttons.scss b/frontend/src/assets/scss/core/mixins/_buttons.scss new file mode 100644 index 000000000..5cedd20ef --- /dev/null +++ b/frontend/src/assets/scss/core/mixins/_buttons.scss @@ -0,0 +1,105 @@ +@mixin button-variant($background, $border, $hover-background: darken($background, 0%), $hover-border: darken($border, 0%), $active-background: darken($background, 10%), $active-border: darken($border, 0%)) { + color: color-yiq($background); + @include gradient-bg($background); + border-color: $border; + @include box-shadow($btn-box-shadow); + + @include hover { + color: color-yiq($hover-background); + @include gradient-bg($hover-background); + border-color: $hover-border; + } + + &:focus, + &.focus { + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: $btn-box-shadow, 0 0 0 $btn-focus-width rgba($border, .5); + } + @else { + box-shadow: 0 0 0 $btn-focus-width rgba($border, .5); + } + } // Disabled comes first so active can properly restyle + &.disabled, + &:disabled { + color: color-yiq($background); + background-color: $background; + border-color: $border; + } + + &:not(:disabled):not(.disabled):active, + &:not(:disabled):not(.disabled).active, + .show>&.dropdown-toggle { + color: color-yiq($active-background); + background-color: $active-background; + @if $enable-gradients { + background-image: none; // Remove the gradient for the pressed/active state + } + border-color: $active-border; + + &:focus { + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($border, .5); + } + @else { + box-shadow: 0 0 0 $btn-focus-width rgba($border, .5); + } + } + } +} + +@mixin button-outline-variant($color, $color-hover: color-yiq($color), $active-background: $color, $active-border: $color) { + color: $color; + background-color: transparent; + background-image: none; + border-color: $color; + + &:hover { + color: $color-hover; + background-color: $active-background; + border-color: $active-border; + } + + &:focus, + &.focus { + box-shadow: 0 0 0 $btn-focus-width rgba($color, .5); + } + + &.disabled, + &:disabled { + color: $color; + background-color: transparent; + } + + &:not(:disabled):not(.disabled):active, + &:not(:disabled):not(.disabled).active, + .show>&.dropdown-toggle { + color: color-yiq($active-background); + background-color: $active-background; + border-color: $active-border; + + &:focus { + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows and $btn-active-box-shadow !=none { + box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($color, .5); + } + @else { + box-shadow: 0 0 0 $btn-focus-width rgba($color, .5); + } + } + } +} + +// Button sizes +@mixin button-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) { + padding: $padding-y $padding-x; + font-size: $font-size; + line-height: $line-height; // Manually declare to provide an override to the browser default + @if $enable-rounded { + border-radius: $border-radius; + } + @else { + border-radius: 0; + } +} \ No newline at end of file diff --git a/frontend/src/assets/scss/core/mixins/_forms.scss b/frontend/src/assets/scss/core/mixins/_forms.scss new file mode 100644 index 000000000..0c51a3be6 --- /dev/null +++ b/frontend/src/assets/scss/core/mixins/_forms.scss @@ -0,0 +1,127 @@ +@mixin form-control-focus($ignore-warning: true) { + &:focus { + color: $input-focus-color; + background-color: $input-focus-bg; + border-color: $input-focus-border-color; + outline: 0; + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: $input-box-shadow, $input-focus-box-shadow; + } @else { + box-shadow: $input-focus-box-shadow; + } + } +} + + +@mixin form-validation-state($state, $color, $icon) { + .#{$state}-feedback { + display: none; + width: 100%; + margin-top: $form-feedback-margin-top; + font-size: $form-feedback-font-size; + color: $color; + } + + .#{$state}-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; // Contain to parent when possible + padding: .5rem; + margin-top: .1rem; + font-size: .875rem; + line-height: 1; + color: #fff; + background-color: rgba($color, .8); + border-radius: .2rem; + } + + .form-control, + .custom-select { + .was-validated &:#{$state}, + &.is-#{$state} { + border-color: $color; + + &:focus { + border-color: $color; + //box-shadow: 0 1px $input-focus-width 0 rgba($color, .75); + } + + ~ .#{$state}-feedback, + ~ .#{$state}-tooltip { + display: block; + } + } + } + + .form-check-input { + .was-validated &:#{$state}, + &.is-#{$state} { + ~ .form-check-label { + color: $color; + } + + ~ .#{$state}-feedback, + ~ .#{$state}-tooltip { + display: block; + } + } + } + + .custom-control-input { + .was-validated &:#{$state}, + &.is-#{$state} { + ~ .custom-control-label { + color: $color; + + &::before { + background-color: lighten($color, 25%); + border-color: lighten($color, 25%); + } + } + + ~ .#{$state}-feedback, + ~ .#{$state}-tooltip { + display: block; + } + + &:checked { + ~ .custom-control-label::before { + @include gradient-bg(lighten($color, 10%)); + border-color: lighten($color, 25%); + } + } + + &:focus { + ~ .custom-control-label::before { + box-shadow: 0 0 0 1px $body-bg, 0 0 0 $input-focus-width rgba($color, .25); + } + } + } + } + + // custom file + .custom-file-input { + .was-validated &:#{$state}, + &.is-#{$state} { + ~ .custom-file-label { + border-color: $color; + + &::before { border-color: inherit; } + } + + ~ .#{$state}-feedback, + ~ .#{$state}-tooltip { + display: block; + } + + &:focus { + ~ .custom-file-label { + box-shadow: 0 0 0 $input-focus-width rgba($color, .25); + } + } + } + } +} diff --git a/frontend/src/assets/scss/core/mixins/_icon.scss b/frontend/src/assets/scss/core/mixins/_icon.scss new file mode 100644 index 000000000..88199859f --- /dev/null +++ b/frontend/src/assets/scss/core/mixins/_icon.scss @@ -0,0 +1,4 @@ +@mixin icon-shape-variant($color) { + color: saturate(darken($color, 10%), 10); + background-color: transparentize(lighten($color, 10%), .5); +} \ No newline at end of file diff --git a/frontend/src/assets/scss/core/mixins/_modals.scss b/frontend/src/assets/scss/core/mixins/_modals.scss new file mode 100644 index 000000000..f91249028 --- /dev/null +++ b/frontend/src/assets/scss/core/mixins/_modals.scss @@ -0,0 +1,23 @@ +@mixin modal-variant($background) { + .modal-title { + color: color-yiq($background); + } + .modal-header, + .modal-footer { + border-color: rgba(color-yiq($background), .075); + } + .modal-content { + background-color: $background; + color: color-yiq($background); + + .heading { + color: color-yiq($background); + } + } + + .close { + &>span:not(.sr-only) { + color: $white; + } + } +} \ No newline at end of file diff --git a/frontend/src/assets/scss/core/mixins/_popover.scss b/frontend/src/assets/scss/core/mixins/_popover.scss new file mode 100644 index 000000000..e535b5379 --- /dev/null +++ b/frontend/src/assets/scss/core/mixins/_popover.scss @@ -0,0 +1,36 @@ +@mixin popover-variant($background) { + + background-color: $background; + + .popover-header { + background-color: $background; + color: color-yiq($background); + } + + .popover-body { + color: color-yiq($background); + } + .popover-header{ + border-color: rgba(color-yiq($background), .2); + } + &.bs-popover-top { + .arrow::after { + border-top-color: $background; + } + } + &.bs-popover-right { + .arrow::after { + border-right-color: $background; + } + } + &.bs-popover-bottom { + .arrow::after { + border-bottom-color: $background; + } + } + &.bs-popover-left { + .arrow::after { + border-left-color: $background; + } + } +} \ No newline at end of file diff --git a/frontend/src/assets/scss/core/modals/_modal.scss b/frontend/src/assets/scss/core/modals/_modal.scss new file mode 100644 index 000000000..ed31d511e --- /dev/null +++ b/frontend/src/assets/scss/core/modals/_modal.scss @@ -0,0 +1,25 @@ +// +// Modal +// + + +// Fluid modal + +.modal-fluid { + .modal-dialog { + margin-top: 0; + margin-bottom: 0; + } + .modal-content { + border-radius: 0; + } +} + + +// Background color variations + +@each $color, $value in $theme-colors { + .modal-#{$color} { + @include modal-variant($value); + } +} diff --git a/frontend/src/assets/scss/core/navbars/_navbar-collapse.scss b/frontend/src/assets/scss/core/navbars/_navbar-collapse.scss new file mode 100644 index 000000000..ffd998af3 --- /dev/null +++ b/frontend/src/assets/scss/core/navbars/_navbar-collapse.scss @@ -0,0 +1,125 @@ +// +// Navabar collapse +// + +// Collapse + +.navbar-collapse-header { + display: none; +} + +@include media-breakpoint-down(sm) { + .navbar-nav { + .nav-link { + padding: .625rem 0; + color: theme-color("default") !important; + } + + .dropdown-menu { + box-shadow: none; + min-width: auto; + + .media { + svg { + width: 30px; + } + } + } + } + + .navbar-collapse { + width: calc(100% - 1.4rem); + position: absolute; + top: 0; + left: 0; + right: 0; + z-index: 1050; + margin: .7rem; + overflow-y: auto; + height: auto !important; + opacity: 0; + + .navbar-toggler { + width: 20px; + height: 20px; + position: relative; + cursor: pointer; + display: inline-block; + padding: 0; + + span { + display: block; + position: absolute; + width: 100%; + height: 2px; + border-radius: 2px; + opacity: 1; + background: #283448; + } + + :nth-child(1) { + transform: rotate(135deg); + } + + :nth-child(2) { + transform: rotate(-135deg); + } + } + + .navbar-collapse-header { + display: block; + padding-bottom: 1rem; + margin-bottom: 1rem; + border-bottom: 1px solid rgba(0, 0, 0, .1); + } + + .collapse-brand { + img { + height: 36px; + } + } + + .collapse-close { + text-align: right; + } + } + + .navbar-collapse.collapsing, + .navbar-collapse.show { + padding: 1.5rem; + border-radius: $border-radius; + background: #FFF; + box-shadow: 0 50px 100px rgba(50,50,93,.1),0 15px 35px rgba(50,50,93,.15),0 5px 15px rgba(0,0,0,.1); + animation: show-navbar-collapse .2s ease forwards; + } + + .navbar-collapse.collapsing-out { + animation: hide-navbar-collapse .2s ease forwards; + } +} + +@keyframes show-navbar-collapse { + 0% { + opacity: 0; + transform: scale(.95); + transform-origin: 100% 0; + } + + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes hide-navbar-collapse { + from { + opacity: 1; + transform: scale(1); + transform-origin: 100% 0; + } + + to { + opacity: 0; + transform: scale(.95); + } +} diff --git a/frontend/src/assets/scss/core/navbars/_navbar-dropdown.scss b/frontend/src/assets/scss/core/navbars/_navbar-dropdown.scss new file mode 100644 index 000000000..3db781c86 --- /dev/null +++ b/frontend/src/assets/scss/core/navbars/_navbar-dropdown.scss @@ -0,0 +1,101 @@ +// Dropdown menu + +@include media-breakpoint-up(md) { + .navbar { + .dropdown-menu { + opacity: 0; + pointer-events: none; + margin: 0; + } + + .dropdown-menu-arrow { + &:before { + background: $dropdown-bg; + box-shadow: none; + content: ''; + display: block; + height: 12px; + width: 12px; + left: 20px; + position: absolute; + bottom: 100%; + transform: rotate(-45deg) translateY(12px); + z-index: -5; + border-radius: 2px; + } + } + + .dropdown-menu-right { + &:before { + right: 20px; + left: auto; + } + } + + &:not(.navbar-nav-hover) { + .dropdown-menu { + &.show { + opacity: 1; + pointer-events: auto; + animation: show-navbar-dropdown .25s ease forwards; + } + + &.close { + display: block; + animation: hide-navbar-dropdown .15s ease backwards; + } + } + } + + &.navbar-nav-hover { + .dropdown-menu { + opacity: 0; + display: block; + pointer-events: none; + transform: translate(0, 10px) perspective(200px) rotateX(-2deg); + transition: visibility 0.25s, opacity 0.25s, transform 0.25s; + } + + .nav-item.dropdown:hover > .dropdown-menu { + display: block; + opacity: 1; + pointer-events: auto; + visibility: visible; + transform: translate(0, 0); + animation: none; + } + } + + .dropdown-menu-inner { + position: relative; + padding: 1rem; + } + + + // Keyframes + + @keyframes show-navbar-dropdown { + 0% { + opacity: 0; + transform: translate(0, 10px) perspective(200px) rotateX(-2deg); + transition: visibility 0.25s, opacity 0.25s, transform 0.25s; + } + + 100% { + transform: translate(0, 0); + opacity: 1; + } + } + + @keyframes hide-navbar-dropdown { + from { + opacity: 1; + } + + to { + opacity: 0; + transform: translate(0, 10px); + } + } + } +} diff --git a/frontend/src/assets/scss/core/navbars/_navbar-search.scss b/frontend/src/assets/scss/core/navbars/_navbar-search.scss new file mode 100644 index 000000000..d95a1410a --- /dev/null +++ b/frontend/src/assets/scss/core/navbars/_navbar-search.scss @@ -0,0 +1,69 @@ +// +// Navbar search +// + +.navbar-search { + .input-group { + border-radius: $navbar-search-border-radius; + border: $navbar-search-border-width solid; + background-color: transparent; + + .input-group-text { + background-color: transparent; + padding-left: 1rem; + } + } + + .form-control { + width: $navbar-search-width; + background-color: transparent; + } +} + +.navbar-search-dark { + .input-group { + border-color: $navbar-search-dark-border-color; + } + + .input-group-text { + color: $navbar-search-dark-color; + } + + .form-control { + color: $navbar-search-dark-focus-color; + + &::placeholder { + color: $navbar-search-dark-color; + } + } + + .focused { + .input-group { + border-color: $navbar-search-dark-focus-border-color; + } + } +} + +.navbar-search-light { + .input-group { + border-color: $navbar-search-light-border-color; + } + + .input-group-text { + color: $navbar-search-light-color; + } + + .form-control { + color: $navbar-search-light-focus-color; + + &::placeholder { + color: $navbar-search-light-color; + } + } + + .focused { + .input-group { + border-color: $navbar-search-light-focus-border-color; + } + } +} diff --git a/frontend/src/assets/scss/core/navbars/_navbar-vertical.scss b/frontend/src/assets/scss/core/navbars/_navbar-vertical.scss new file mode 100644 index 000000000..48e1fd7be --- /dev/null +++ b/frontend/src/assets/scss/core/navbars/_navbar-vertical.scss @@ -0,0 +1,286 @@ +// +// Vertical navbar +// + + +// Vertical +// +// Creates a vertically aligned version of the navbar +.navbar-vertical { + box-shadow: $navbar-vertical-box-shadow; + + .navbar { + border-width: 0 0 1px 0; + border-style: solid; + } + + + // Navbar light + + .navbar-light { + background-color: $navbar-light-bg; + border-color: $navbar-light-border-color; + } + + + // Navbar brand + + .navbar-brand { + margin-right: 0; + } + + .navbar-brand-img, + .navbar-brand > img { + max-width: 100%; + max-height: 2rem; + } + + + // Navbar collapse + + @include media-breakpoint-up(md) { + .navbar-collapse { + margin-left: -$navbar-padding-x; + margin-right: -$navbar-padding-x; + padding-left: $navbar-padding-x; + padding-right: $navbar-padding-x; + + &:before { + content: ''; + display: block; + margin: $navbar-padding-y (-$navbar-padding-x); + } + } + } + + + + // Navbar navigaton + + .navbar-nav { + margin-left: -$navbar-padding-x; + margin-right: -$navbar-padding-x; + + + // Navbar link + + .nav-link { + padding-left: $navbar-padding-x; + padding-right: $navbar-padding-x; + font-size: $navbar-nav-link-font-size; + + &.active { + position: relative; + + &:before { + content: ''; + position: absolute; + left: 0; + top: $nav-link-padding-y; + bottom: $nav-link-padding-y; + border-left: 2px solid $primary; + } + } + + + // Icon + + > i { + min-width: $navbar-icon-min-width; + font-size: .9375rem; + line-height: ($font-size-base * $line-height-base); + } + + + // Dropdown + + .dropdown-menu { + border: none; + + .dropdown-menu { + margin-left: $dropdown-item-padding-x / 2; + } + } + } + } + + + // Navbar navigation + .navbar-nav .nav-link { + display: flex; + align-items: center; + } + + .navbar-nav .nav-link[data-toggle="collapse"] { + &:after { + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + font-family: 'Font Awesome 5 Free'; + font-weight: 700; + content: "\f105"; + margin-left: auto; + color: $text-muted; + transition: $transition-base; + } // Expanded + &[aria-expanded="true"] { + + &:after { + transform: rotate(90deg); + } + } + } + + // Second level + .navbar-nav .nav .nav-link { + padding-left: $navbar-padding-x + $navbar-icon-min-width; + } + + // Third level + .navbar-nav .nav .nav .nav-link { + padding-left: $navbar-padding-x * 1.5 + $navbar-icon-min-width; + } + + + // Navbar heading + .navbar-heading { + padding-top: $nav-link-padding-y; + padding-bottom: $nav-link-padding-y; + font-size: $font-size-xs; + text-transform: uppercase; + letter-spacing: .04em; + } + + + // Expanded navbar specific styles + &.navbar-expand { + @each $breakpoint, + $dimension in $grid-breakpoints { + + &-#{$breakpoint} { + @include media-breakpoint-up(#{$breakpoint}) { + display: block; + position: fixed; + top: 0; + bottom: 0; + width: 100%; + max-width: $navbar-vertical-width; + padding-left: $navbar-vertical-padding-x; + padding-right: $navbar-vertical-padding-x; + + overflow-y: auto; + + // Container + >[class*="container"] { + flex-direction: column; + align-items: stretch; + min-height: 100%; + padding-left: 0; + padding-right: 0; // Target IE 10 & 11 + @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { + min-height: none; + height: 100%; + } + } + + + // Fixes the vertical navbar to the left + &.fixed-left { + left: 0; + border-width: 0 1px 0 0; + } + + + // Fixed the vertical navbar to the right + &.fixed-right { + right: 0; + border-width: 0 0 0 1px; + } + + + // Navbar collapse + .navbar-collapse { + flex: 1; + display: flex; + flex-direction: column; + align-items: stretch; + margin-left: -$navbar-vertical-padding-x; + margin-right: -$navbar-vertical-padding-x; + padding-left: $navbar-vertical-padding-x; + padding-right: $navbar-vertical-padding-x; + + > * { + min-width: 100%; + } + } + + + // Navbar navigation + .navbar-nav { + flex-direction: column; + margin-left: -$navbar-vertical-padding-x; + margin-right: -$navbar-vertical-padding-x; + } + + .navbar-nav .nav-link { + padding: $navbar-vertical-nav-link-padding-y $navbar-vertical-nav-link-padding-x; + + &.active { + &:before { + top: $nav-link-padding-y; + bottom: $nav-link-padding-y; + left: 0; + right: auto; + border-left: 2px solid $primary; + border-bottom: 0; + } + } + } + + + // Second level + .navbar-nav .nav .nav-link { + padding-left: $navbar-vertical-padding-x + $navbar-icon-min-width; + } + + + // Third level + .navbar-nav .nav .nav .nav-link { + padding-left: $navbar-vertical-padding-x * 1.5 + $navbar-icon-min-width; + } + + // Navbar brand + .navbar-brand { + display: block; + text-align: center; + padding-top: (2rem - $navbar-padding-y); + padding-bottom: (2rem - $navbar-padding-y); + } + + .navbar-brand-img { + max-height: 2.5rem; + } + + // Navbar user + .navbar-user { + margin-left: -$navbar-vertical-padding-x; + margin-right: -$navbar-vertical-padding-x; + padding-top: $spacer; + padding-bottom: $spacer - $navbar-padding-y; + padding-left: $navbar-vertical-padding-x; + padding-right: $navbar-vertical-padding-x; + border-top: 1px solid $border-color; + + // Dropup menu + .dropup .dropdown-menu { + left: 50%; + transform: translateX(-50%); + } + } + } + } + } + } +} diff --git a/frontend/src/assets/scss/core/navbars/_navbar.scss b/frontend/src/assets/scss/core/navbars/_navbar.scss new file mode 100644 index 000000000..a2390b326 --- /dev/null +++ b/frontend/src/assets/scss/core/navbars/_navbar.scss @@ -0,0 +1,153 @@ +// +// Navbar +// + + +// Navbar links + +.navbar-horizontal { + .navbar-nav { + .nav-link { + font-size: $navbar-nav-link-font-size; + font-weight: $navbar-nav-link-font-weight; + text-transform: $navbar-nav-link-text-transform; + letter-spacing: $navbar-nav-link-letter-spacing; + @include transition($navbar-transition); + + .nav-link-inner--text { + margin-left: .25rem; + } + } + } + + + // Navbar brand (logo) + + .navbar-brand { + font-size: $font-size-sm; + font-weight: 600; + text-transform: uppercase; + font-size: .875rem; + letter-spacing: .05px; + + img { + height: 30px; + } + } + + .navbar-dark { + .navbar-brand { + color: $white; + } + } + + .navbar-light { + .navbar-brand { + color: $gray-800; + } + } + + .navbar-nav { + .nav-item { + .media:not(:last-child){ + margin-bottom: 1.5rem; + } + } + } + + @include media-breakpoint-up(lg) { + .navbar-nav { + .nav-item { + margin-right: .5rem; + + [data-toggle="dropdown"]::after { + transition: $transition-base; + } + + &.show { + [data-toggle="dropdown"]::after { + transform: rotate(180deg); + } + } + } + .nav-link { + padding-top: $navbar-nav-link-padding-y; + padding-bottom: $navbar-nav-link-padding-y; + border-radius: $navbar-nav-link-border-radius; + + i { + margin-right: .625rem; + } + } + + .nav-link-icon { + padding-left: .5rem !important; + padding-right: .5rem !important; + font-size: 1rem; + border-radius: $navbar-nav-link-border-radius; + + i { + margin-right: 0; + } + } + } + } + + + // Transparent navbar + + .navbar-transparent { + position: absolute; + top: 0; + width: 100%; + z-index: 100; + background-color: transparent; + border: 0; + box-shadow: none; + + .navbar-brand { + color: rgba(255, 255, 255, 1); + } + + .navbar-toggler { + color: rgba(255, 255, 255, 1); + } + + .navbar-toggler-icon { + background-image: $navbar-dark-toggler-icon-bg; + } + } + + @include media-breakpoint-up(md) { + .navbar-transparent { + .navbar-nav { + .nav-link { + color: $navbar-dark-color; + + @include hover-focus { + color: $navbar-dark-hover-color; + } + + &.disabled { + color: $navbar-dark-disabled-color; + } + } + + .show > .nav-link, + .active > .nav-link, + .nav-link.show, + .nav-link.active { + color: $navbar-dark-active-color; + } + } + + .navbar-brand { + color: $navbar-dark-color; + + @include hover-focus { + color: $navbar-dark-color; + } + } + } + } +} diff --git a/frontend/src/assets/scss/core/navs/_nav-pills.scss b/frontend/src/assets/scss/core/navs/_nav-pills.scss new file mode 100644 index 000000000..9fe2a3743 --- /dev/null +++ b/frontend/src/assets/scss/core/navs/_nav-pills.scss @@ -0,0 +1,66 @@ +// +// Nav pills +// + + +// General styles + +.nav-pills { + .nav-item:not(:last-child) { + padding-right: $nav-pills-space-x; + } + + .nav-link { + padding: $nav-pills-padding-y $nav-pills-padding-x; + color: $nav-pills-link-color; + font-weight: 500; + font-size: $font-size-sm; + box-shadow: $nav-pills-box-shadow; + background-color: $nav-pills-bg; + transition: $transition-base; + + &:hover { + color: $nav-pills-link-hover-color; + } + } + + .nav-link.active, + .show > .nav-link { + color: $nav-pills-link-active-color; + background-color: $nav-pills-link-active-bg; + } + + @include media-breakpoint-down(xs) { + .nav-item { + margin-bottom: $spacer; + } + } +} + +@include media-breakpoint-down(sm) { + .nav-pills:not(.nav-pills-circle) { + .nav-item { + padding-right: 0; + } + } +} + + +// Rounded circle nav pills + +.nav-pills-circle { + .nav-link { + text-align: center; + height: 60px; + width: 60px; + padding: 0; + line-height: 60px; + border-radius: 50%; + } + + .nav-link-icon { + i, svg { + font-size: 1rem; + } + } +} diff --git a/frontend/src/assets/scss/core/navs/_nav.scss b/frontend/src/assets/scss/core/navs/_nav.scss new file mode 100644 index 000000000..ed1a9f3c9 --- /dev/null +++ b/frontend/src/assets/scss/core/navs/_nav.scss @@ -0,0 +1,33 @@ +// +// Nav +// + + +// Nav wrapper (container) + +// Nav wrapper +.nav-wrapper { + padding: 1rem 0; + @include border-top-radius($card-border-radius); + + + .card { + @include border-top-radius(0); + @include border-bottom-radius($card-border-radius); + } +} + + +// Nav links + +.nav-link { + color: $nav-link-color; + + &:hover { + color: $nav-link-hover-color; + } + + i.ni { + position: relative; + top: 2px; + } +} diff --git a/frontend/src/assets/scss/core/paginations/_pagination.scss b/frontend/src/assets/scss/core/paginations/_pagination.scss new file mode 100644 index 000000000..02f76275c --- /dev/null +++ b/frontend/src/assets/scss/core/paginations/_pagination.scss @@ -0,0 +1,48 @@ +// +// Pagination +// + + +.page-item { + &.active .page-link { + box-shadow: $pagination-active-box-shadow; + } + + .page-link, + span { + display: flex; + align-items: center; + justify-content: center; + padding: 0; + margin: 0 3px; + border-radius: 50% !important; + width: 36px; + height: 36px; + font-size: $font-size-sm; + } +} + + +// Size variations + +.pagination-lg { + .page-item { + .page-link, + span { + width: 46px; + height: 46px; + line-height: 46px; + } + } +} + +.pagination-sm { + .page-item { + .page-link, + span { + width: 30px; + height: 30px; + line-height: 30px; + } + } +} diff --git a/frontend/src/assets/scss/core/popovers/_popover.scss b/frontend/src/assets/scss/core/popovers/_popover.scss new file mode 100644 index 000000000..52cedec0f --- /dev/null +++ b/frontend/src/assets/scss/core/popovers/_popover.scss @@ -0,0 +1,21 @@ +// +// Popover +// + + +.popover { + border: 0; +} + +.popover-header { + font-weight: $font-weight-bold; +} + + +// Alternative colors + +@each $color, $value in $theme-colors { + .popover-#{$color} { + @include popover-variant($value); + } +} diff --git a/frontend/src/assets/scss/core/progresses/_progress.scss b/frontend/src/assets/scss/core/progresses/_progress.scss new file mode 100644 index 000000000..70a50432b --- /dev/null +++ b/frontend/src/assets/scss/core/progresses/_progress.scss @@ -0,0 +1,79 @@ +// +// Progress +// + + +// Progress container + +.progress-wrapper { + position: relative; + padding-top: 1.5rem; +} + + +// General styles + +.progress { + height: 8px; + margin-bottom: $spacer; + overflow: hidden; + border-radius: $border-radius-sm; + background-color: $progress-bg; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + + .sr-only { + width: auto; + height: 20px; + margin: 0 0 0 30px; + left: 0; + clip: auto; + line-height: 20px; + font-size: 13px; + } +} + + +// Progress inner elements + +.progress-heading { + font-size: 14px; + font-weight: 500; + margin: 0 0 2px; + padding: 0; +} + +.progress-bar { + box-shadow: none; + border-radius: 0; + height: auto; +} + +.progress-info{ + margin-bottom: .5rem; + display: flex; + align-items: center; + justify-content: space-between; +} + +.progress-label { + span { + display: inline-block; + color: $primary; + font-size: .625rem; + font-weight: 600; + text-transform: uppercase; + background: rgba($primary, .1); + padding: .25rem 1rem; + border-radius: 30px; + } +} + +.progress-percentage { + text-align: right; + span { + display: inline-block; + color: $gray-600; + font-size: .875rem; + font-weight: 600; + } +} diff --git a/frontend/src/assets/scss/core/separators/_separator.scss b/frontend/src/assets/scss/core/separators/_separator.scss new file mode 100644 index 000000000..4808dfb6c --- /dev/null +++ b/frontend/src/assets/scss/core/separators/_separator.scss @@ -0,0 +1,54 @@ +// +// Separator +// add svg on top or bottom of a section for a more stylish visual +// + + +.separator { + position: absolute; + top: auto; + left: 0; + right: 0; + width: 100%; + height: 150px; + transform: translateZ(0); + overflow: hidden; + pointer-events: none; + + svg { + position: absolute; + pointer-events: none; + } +} + +.separator-top { + top: 0; + bottom: auto; + + svg { + top: 0; + } +} + +.separator-bottom { + top: auto; + bottom: 0; + + svg { + bottom: 0; + } +} + +.separator-inverse { + transform: rotate(180deg); +} + +// Styles + +.separator-skew { + height: 60px; + + @include media-breakpoint-up(xl) { + height: 70px; + } +} diff --git a/frontend/src/assets/scss/core/tables/_table.scss b/frontend/src/assets/scss/core/tables/_table.scss new file mode 100644 index 000000000..18475b5a5 --- /dev/null +++ b/frontend/src/assets/scss/core/tables/_table.scss @@ -0,0 +1,118 @@ +// +// Table +// + + +// General styles + +.table { + thead th { + padding-top: $table-head-spacer-y; + padding-bottom: $table-head-spacer-y; + font-size: $table-head-font-size; + text-transform: $table-head-text-transform; + letter-spacing: $table-head-letter-spacing; + border-bottom: $table-border-width solid $table-border-color; + } + + th { + font-weight: $table-head-font-weight; + } + + td { + .progress { + height: 3px; + width: 120px; + margin: 0; + } + } + + td, + th { + font-size: $table-body-font-size; + white-space: nowrap; + } + + + // Vetical align table content + + &.align-items-center { + td, + th { + vertical-align: middle; + } + } + + + // Styles for dark table + + .thead-dark { + th { + background-color: $table-dark-head-bg; + color: $table-dark-head-color; + } + } + + + // Styles for light table + + .thead-light { + th { + background-color: $table-head-bg; + color: $table-head-color; + } + } +} + + +// Add transition for hover state + +.table-hover { + tr { + @include transition($transition-base); + } +} + + +// Flush tables + +.table-flush { + td, + th { + border-left: 0; + border-right: 0; + } + + tbody { + tr { + &:first-child { + td, + th { + border-top: 0; + } + } + + &:last-child { + td, + th { + border-bottom: 0; + } + } + } + } +} + + +// Tables inside cards + +.card { + .table { + margin-bottom: 0; + + td, + th { + padding-left: $card-spacer-x; + padding-right: $card-spacer-x; + } + } +} diff --git a/frontend/src/assets/scss/core/type/_article.scss b/frontend/src/assets/scss/core/type/_article.scss new file mode 100644 index 000000000..47ac1c754 --- /dev/null +++ b/frontend/src/assets/scss/core/type/_article.scss @@ -0,0 +1,22 @@ +// +// Article +// + +article { + h4:not(:first-child), + h5:not(:first-child) { + margin-top: 3rem; + } + + h4, h5 { + margin-bottom: 1.5rem; + } + + figure { + margin: 3rem 0; + } + + h5 + figure { + margin-top: 0; + } +} diff --git a/frontend/src/assets/scss/core/type/_display.scss b/frontend/src/assets/scss/core/type/_display.scss new file mode 100644 index 000000000..c0b1ec548 --- /dev/null +++ b/frontend/src/assets/scss/core/type/_display.scss @@ -0,0 +1,14 @@ +// +// Display +// + + +.display-1, +.display-2, +.display-3, +.display-4 { + span { + display: block; + font-weight: $font-weight-light; + } +} diff --git a/frontend/src/assets/scss/core/type/_heading.scss b/frontend/src/assets/scss/core/type/_heading.scss new file mode 100644 index 000000000..eb028b7a6 --- /dev/null +++ b/frontend/src/assets/scss/core/type/_heading.scss @@ -0,0 +1,52 @@ +// +// Heading +// + + +// General styles + +.heading { + letter-spacing: $heading-letter-spacing; + font-size: $heading-font-size; + text-transform: $heading-text-transform; + font-weight: $heading-font-weight; +} + + +// Heading variations + +.heading-small { + padding-top: .25rem; + padding-bottom: .25rem; + font-size: .75rem; + text-transform: uppercase; + letter-spacing: .04em; +} + +.heading-title { + letter-spacing: $heading-title-letter-spacing; + font-size: $heading-title-font-size; + font-weight: $heading-title-font-weight; + text-transform: $heading-title-text-transform; +} + +.heading-section { + letter-spacing: $heading-section-letter-spacing; + font-size: $heading-section-font-size; + font-weight: $heading-section-font-weight; + text-transform: $heading-section-text-transform; + + img { + display: block; + width: 72px; + height: 72px; + margin-bottom: 1.5rem; + } + + &.text-center { + img { + margin-left: auto; + margin-right: auto; + } + } +} diff --git a/frontend/src/assets/scss/core/type/_type.scss b/frontend/src/assets/scss/core/type/_type.scss new file mode 100644 index 000000000..6512a7f5f --- /dev/null +++ b/frontend/src/assets/scss/core/type/_type.scss @@ -0,0 +1,27 @@ +// +// Type +// + + +// Paragraphs + +p { + font-size: $paragraph-font-size; + font-weight: $paragraph-font-weight; + line-height: $paragraph-line-height; +} + +.lead { + font-size: $lead-font-size; + font-weight: $lead-font-weight; + line-height: $paragraph-line-height; + margin-top: 1.5rem; + + + .btn-wrapper { + margin-top: 3rem; + } +} + +.description { + font-size: $font-size-sm; +} diff --git a/frontend/src/assets/scss/core/utilities/_backgrounds.scss b/frontend/src/assets/scss/core/utilities/_backgrounds.scss new file mode 100644 index 000000000..45a9f0635 --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_backgrounds.scss @@ -0,0 +1,51 @@ +// +// Backgrounds +// + + +@each $color, $value in $colors { + @include bg-variant(".bg-#{$color}", $value, $ignore-warning: true); +} + +@each $color, $value in $theme-colors { + @include bg-gradient-variant(".bg-gradient-#{$color}", $value, $ignore-warning: true); +} + +@each $color, $value in $colors { + @include bg-gradient-variant(".bg-gradient-#{$color}", $value, $ignore-warning: true); +} + + +// Background colors with transparency + +@each $color, $value in $theme-colors { + @include bg-translucent-variant(".bg-translucent-#{$color}", $value, $ignore-warning: true); +} + + +// Sections backgrounds + +@each $color, $value in $section-colors { + @include bg-variant(".section-#{$color}", $value, $ignore-warning: true); +} + +@each $color, $value in $theme-colors { + @include bg-gradient-variant(".bg-gradient-#{$color}", $value, $ignore-warning: true); +} + + +// Shape (svg) fill colors + +@each $color, $value in $theme-colors { + .fill-#{$color} { + fill: $value; + } + + .stroke-#{$color} { + stroke: $value; + } +} + +.fill-opacity-8 { + fill-opacity: .8; +} diff --git a/frontend/src/assets/scss/core/utilities/_blurable.scss b/frontend/src/assets/scss/core/utilities/_blurable.scss new file mode 100644 index 000000000..a558c0d44 --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_blurable.scss @@ -0,0 +1,37 @@ +// +// Blurable +// add a blue effect on hover on any element with .blur--hover class +// + +.blur--hover { + position: relative; + + .blur-item { + transition: 1s cubic-bezier(.19,1,.22,1); + will-change: transform; + filter: blur(0); + opacity: 1; + } + + .blur-hidden { + position: absolute; + top: calc(50% + 7px); + left: 50%; + transform: translate(-50%, -50%); + opacity: 0; + transition: $transition-base; + z-index: 100; + } + &:hover { + .blur-item { + opacity: .8; + filter: blur(10px); + transform: scale(.95); + z-index: 1; + } + .blur-hidden { + opacity: 1; + top: 50%; + } + } +} diff --git a/frontend/src/assets/scss/core/utilities/_floating.scss b/frontend/src/assets/scss/core/utilities/_floating.scss new file mode 100644 index 000000000..eaa90fc9b --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_floating.scss @@ -0,0 +1,64 @@ +// +// Floating +// floating animation utility class +// + + +.floating { + animation: floating 3s ease infinite; + will-change: transform; + + &:hover { + animation-play-state: paused; + } +} + + +// Size variations + +.floating-lg { + animation: floating-lg 3s ease infinite; +} + +.floating-sm { + animation: floating-sm 3s ease infinite; +} + + +// Keyframes + +@keyframes floating-lg { + 0% { + transform: translateY(0px) + } + 50% { + transform: translateY(15px) + } + 100% { + transform: translateY(0px) + } +} + +@keyframes floating { + 0% { + transform: translateY(0px) + } + 50% { + transform: translateY(10px) + } + 100% { + transform: translateY(0px) + } +} + +@keyframes floating-sm { + 0% { + transform: translateY(0px) + } + 50% { + transform: translateY(5px) + } + 100% { + transform: translateY(0px) + } +} diff --git a/frontend/src/assets/scss/core/utilities/_helper.scss b/frontend/src/assets/scss/core/utilities/_helper.scss new file mode 100644 index 000000000..013bd2890 --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_helper.scss @@ -0,0 +1,18 @@ +// +// Helper +// helper classes for different cases +// + + +// Clearfix for sections that use float property + +.floatfix { + &:before, + &:after { + content: ''; + display: table; + } + &:after { + clear: both; + } +} diff --git a/frontend/src/assets/scss/core/utilities/_image.scss b/frontend/src/assets/scss/core/utilities/_image.scss new file mode 100644 index 000000000..8bdfbbc0f --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_image.scss @@ -0,0 +1,9 @@ +// +// Image +// + +.img-center { + display: block; + margin-left: auto; + margin-right: auto; +} diff --git a/frontend/src/assets/scss/core/utilities/_opacity.scss b/frontend/src/assets/scss/core/utilities/_opacity.scss new file mode 100644 index 000000000..812bfd8bc --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_opacity.scss @@ -0,0 +1,35 @@ +// +// Opacity +// modify the transparency of an element with this quick modifier classes +// + +.opacity-1 { + opacity: .1 !important; +} +.opacity-2 { + opacity: .2 !important; +} +.opacity-3 { + opacity: .3 !important; +} +.opacity-4 { + opacity: .4 !important; +} +.opacity-5 { + opacity: .5 !important; +} +.opacity-6 { + opacity: .6 !important; +} +.opacity-7 { + opacity: .7 !important; +} +.opacity-8 { + opacity: .8 !important; +} +.opacity-8 { + opacity: .9 !important; +} +.opacity-10 { + opacity: 1 !important; +} diff --git a/frontend/src/assets/scss/core/utilities/_overflow.scss b/frontend/src/assets/scss/core/utilities/_overflow.scss new file mode 100644 index 000000000..b4063fc31 --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_overflow.scss @@ -0,0 +1,11 @@ +// +// Overflow +// + +.overflow-visible { + overflow: visible !important; +} + +.overflow-hidden { + overflow: hidden !important; +} diff --git a/frontend/src/assets/scss/core/utilities/_position.scss b/frontend/src/assets/scss/core/utilities/_position.scss new file mode 100644 index 000000000..58aaa0929 --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_position.scss @@ -0,0 +1,25 @@ +// +// Position +// modifier classes to be applied on an abosolute positioned element +// use it next to .position-absolute class +// + +@each $size, $value in $spacers { + .top-#{$size} { + top: $value; + } + .right-#{$size} { + right: $value; + } + .bottom-#{$size} { + bottom: $value; + } + .left-#{$size} { + left: $value; + } +} + +.center { + left: 50%; + transform: translateX(-50%); +} diff --git a/frontend/src/assets/scss/core/utilities/_shadows.scss b/frontend/src/assets/scss/core/utilities/_shadows.scss new file mode 100644 index 000000000..8907c8b5b --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_shadows.scss @@ -0,0 +1,28 @@ +// +// Shadows +// + +// General styles +[class*="shadow"] { + @if $enable-transitions { + transition: $transition-base; + } +} + + +// Size variations +.shadow-sm--hover:hover { + box-shadow: $box-shadow-sm !important; +} + +.shadow--hover:hover { + box-shadow: $box-shadow !important; +} + +.shadow-lg--hover:hover { + box-shadow: $box-shadow-lg !important; +} + +.shadow-none--hover:hover { + box-shadow: none !important; +} diff --git a/frontend/src/assets/scss/core/utilities/_sizing.scss b/frontend/src/assets/scss/core/utilities/_sizing.scss new file mode 100644 index 000000000..5dd6b2195 --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_sizing.scss @@ -0,0 +1,7 @@ +// +// Height +// + +.h-100vh { + height: 100vh !important; +} diff --git a/frontend/src/assets/scss/core/utilities/_spacing.scss b/frontend/src/assets/scss/core/utilities/_spacing.scss new file mode 100644 index 000000000..b3fb9fa0e --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_spacing.scss @@ -0,0 +1,107 @@ +// +// Spacing +// + +.row.row-grid > [class*="col-"] + [class*="col-"] { + margin-top: 3rem; +} + +@include media-breakpoint-up(lg) { + .row.row-grid > [class*="col-lg-"] + [class*="col-lg-"] { + margin-top: 0; + } +} +@include media-breakpoint-up(md) { + .row.row-grid > [class*="col-md-"] + [class*="col-md-"] { + margin-top: 0; + } +} +@include media-breakpoint-up(sm) { + .row.row-grid > [class*="col-sm-"] + [class*="col-sm-"] { + margin-top: 0; + } +} + +.row-grid + .row-grid { + margin-top: 3rem; +} + + +// Negative margins and paddings + +@media(min-width: 992px) { + [class*="mt--"], + [class*="mr--"], + [class*="mb--"], + [class*="ml--"] { + + } + + + // Large negative margins in pixels + + .mt--100 { + margin-top: -100px !important; + } + .mr--100 { + margin-right: -100px !important; + } + .mb--100 { + margin-bottom: -100px !important; + } + .ml--100 { + margin-left: -100px !important; + } + .mt--150 { + margin-top: -150px !important; + } + .mb--150 { + margin-bottom: -150px !important; + } + .mt--200 { + margin-top: -200px !important; + } + .mb--200 { + margin-bottom: -200px !important; + } + .mt--300 { + margin-top: -300px !important; + } + .mb--300 { + margin-bottom: -300px !important; + } + + + // Large margins in pixels + + .pt-100 { + padding-top: 100px !important; + } + .pb-100 { + padding-bottom: 100px !important; + } + .pt-150 { + padding-top: 150px !important; + } + .pb-150 { + padding-bottom: 150px !important; + } + .pt-200 { + padding-top: 200px !important; + } + .pb-200 { + padding-bottom: 200px !important; + } + .pt-250 { + padding-top: 250px !important; + } + .pb-250 { + padding-bottom: 250px !important; + } + .pt-300 { + padding-top: 300px!important; + } + .pb-300 { + padding-bottom: 300px!important; + } +} diff --git a/frontend/src/assets/scss/core/utilities/_text.scss b/frontend/src/assets/scss/core/utilities/_text.scss new file mode 100644 index 000000000..65c1f6cec --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_text.scss @@ -0,0 +1,49 @@ +// Weight and italics + +.font-weight-300 { font-weight: 300 !important; } +.font-weight-400 { font-weight: 400 !important; } +.font-weight-500 { font-weight: 500 !important; } +.font-weight-600 { font-weight: 600 !important; } +.font-weight-700 { font-weight: 700 !important; } +.font-weight-800 { font-weight: 800 !important; } +.font-weight-900 { font-weight: 900 !important; } + + +// Text decorations + +.text-underline { text-decoration: underline; } +.text-through { text-decoration: line-through; } + + +// Text size + +.text-xs { font-size: $font-size-xs !important; } +.text-sm { font-size: $font-size-sm !important; } +.text-lg { font-size: $font-size-lg !important; } +.text-xl { font-size: $font-size-xl !important; } + + +// Line heights + +.lh-100 { line-height: 1; } +.lh-110 { line-height: 1.1; } +.lh-120 { line-height: 1.2; } +.lh-130 { line-height: 1.3; } +.lh-140 { line-height: 1.4; } +.lh-150 { line-height: 1.5; } +.lh-160 { line-height: 1.6; } +.lh-170 { line-height: 1.7; } +.lh-180 { line-height: 1.8; } + + +// Letter spacings + +.ls-1 { letter-spacing: .0625rem; } +.ls-15 { letter-spacing: .09375rem; } +.ls-2 { letter-spacing: 0.125rem; } + +// Color variations + +@each $color, $value in $colors { + @include text-emphasis-variant(".text-#{$color}", $value); +} diff --git a/frontend/src/assets/scss/core/utilities/_transform.scss b/frontend/src/assets/scss/core/utilities/_transform.scss new file mode 100644 index 000000000..e595bf8b4 --- /dev/null +++ b/frontend/src/assets/scss/core/utilities/_transform.scss @@ -0,0 +1,13 @@ +// +// Tranform +// + + +@include media-breakpoint-up(lg) { + .transform-perspective-right { + transform: scale(1) perspective(1040px) rotateY(-11deg) rotateX(2deg) rotate(2deg); + } + .transform-perspective-left{ + transform: scale(1) perspective(2000px) rotateY(11deg) rotateX(2deg) rotate(-2deg) + } +} diff --git a/frontend/src/assets/scss/core/vendors/_flatpickr.scss b/frontend/src/assets/scss/core/vendors/_flatpickr.scss new file mode 100644 index 000000000..655e982c7 --- /dev/null +++ b/frontend/src/assets/scss/core/vendors/_flatpickr.scss @@ -0,0 +1,72 @@ +%active-day { + background: $datepicker-active-background; + color: $datepicker-active-color; + box-shadow: $datepicker-active-box-shadow; + border: none; +} +.flatpickr-calendar { + @include box-shadow($dropdown-box-shadow); + padding: $datepicker-dropdown-padding; + width: 347px; + color: $gray-700; + + .flatpickr-weekday { + text-align: center; + font-size: $font-size-sm; + color: $gray-700; + font-weight: normal; + } + .flatpickr-day { + border: none; + } + .flatpickr-day:hover { + @extend %active-day; + } + .flatpickr-day.selected { + @extend %active-day; + &:hover { + @extend %active-day; + } + } + + .flatpickr-day.today { + border: 1px solid $datepicker-active-background; + &:hover { + background: $datepicker-active-background; + color: $datepicker-active-color; + } + } + .flatpickr-day.inRange { + background: $datepicker-active-background !important; + color: $datepicker-active-color; + box-shadow: -5px 0 0 $datepicker-active-background, 5px 0 0 $datepicker-active-background; + border: none !important; + } + + .flatpickr-day.startRange, .flatpickr-day.endRange { + background: $datepicker-active-background; + } + + .flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)), + .flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)), + .flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)) { + box-shadow: -10px 0 0 $datepicker-active-background; + } + + .flatpickr-months .flatpickr-prev-month:hover svg, + .flatpickr-months .flatpickr-next-month:hover svg{ + fill: $datepicker-active-background; + } + + .flatpickr-current-month span.cur-month, + .flatpickr-current-month input.cur-year{ + padding: 0 10px; + color: $gray-700; + font-size: $font-size-sm; + font-weight: 500; + &:hover { + background: $gray-200; + border-radius: $datepicker-header-cell-border-radius; + } + } +} diff --git a/frontend/src/assets/scss/core/vendors/_headroom.scss b/frontend/src/assets/scss/core/vendors/_headroom.scss new file mode 100644 index 000000000..3542e4a1e --- /dev/null +++ b/frontend/src/assets/scss/core/vendors/_headroom.scss @@ -0,0 +1,25 @@ +// +// Headroom +// + + +.headroom { + will-change: transform; + background-color: inherit; + @include transition($transition-base); +} +.headroom--pinned { + @extend .position-fixed; + transform: translateY(0%); +} +.headroom--unpinned { + @extend .position-fixed; + transform: translateY(-100%); +} + +.headroom--not-top { + padding-top: .5rem; + padding-bottom: .5rem; + background-color: theme-color("default") !important; + box-shadow: 0 1px 10px rgba(130, 130, 134, 0.1); +} diff --git a/frontend/src/assets/scss/core/vendors/_nouislider.scss b/frontend/src/assets/scss/core/vendors/_nouislider.scss new file mode 100644 index 000000000..cb99d7705 --- /dev/null +++ b/frontend/src/assets/scss/core/vendors/_nouislider.scss @@ -0,0 +1,410 @@ +// +// NoUi Slider +// + + +// Original styles + +.noUi-target, +.noUi-target * { + -webkit-touch-callout: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-user-select: none; + touch-action: none; + user-select: none; + box-sizing: border-box; +} + +.noUi-target { + position: relative; + direction: ltr; +} + +.noUi-base, +.noUi-connects { + width: 100%; + height: 100%; + position: relative; + z-index: 1; +} + + +// Wrapper for all connect elements + +.noUi-connects { + overflow: hidden; + z-index: 0; +} + +.noUi-connect, +.noUi-origin { + will-change: transform; + position: absolute; + z-index: 1; + top: 0; + left: 0; + height: 100%; + width: 100%; + transform-origin: 0 0; +} + + +html:not([dir="rtl"]) .noUi-horizontal .noUi-origin { + left: 100%; + width: 10%; + right: 0; +} + +.noUi-vertical .noUi-origin { + width: 0; +} + +.noUi-horizontal .noUi-origin { + height: 0; +} + +.noUi-handle { + position: absolute; +} + +.noUi-state-tap .noUi-connect, +.noUi-state-tap .noUi-origin { + transition: transform .3s; +} + +.noUi-state-drag * { + cursor: inherit !important; +} + +.noUi-horizontal { + height: $noui-target-thickness; +} + +.noUi-horizontal .noUi-handle { + width: 34px; + height: 28px; + left: -17px; + top: -6px; +} + +.noUi-vertical { + width: $noui-target-thickness; +} + +.noUi-vertical .noUi-handle { + width: 28px; + height: 34px; + left: -6px; + top: -17px; +} + +html:not([dir="rtl"]) .noUi-horizontal .noUi-handle { + left: auto; +} + +.noUi-connects { + border-radius: 3px; +} + +.noUi-connect { + background: $noui-slider-connect-bg; +} + +.noUi-draggable { + cursor: ew-resize; +} + +.noUi-vertical .noUi-draggable { + cursor: ns-resize; +} + +.noUi-handle { + border: 1px solid #D9D9D9; + border-radius: 3px; + background: #FFF; + cursor: default; + box-shadow: inset 0 0 1px #FFF, inset 0 1px 7px #EBEBEB, 0 3px 6px -3px #BBB; + outline: none; +} + +.noUi-active { + outline: none; +} + + +/* Disabled state; + */ + +[disabled] .noUi-connect { + background: #B8B8B8; +} + +[disabled].noUi-target, +[disabled].noUi-handle, +[disabled] .noUi-handle { + cursor: not-allowed; +} + + +/* Base; + * + */ + +.noUi-pips, +.noUi-pips * { + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.noUi-pips { + position: absolute; + color: #999; +} + + +/* Values; + * + */ + +.noUi-value { + position: absolute; + white-space: nowrap; + text-align: center; +} + +.noUi-value-sub { + color: #ccc; + font-size: 10px; +} + + +/* Markings; + * + */ + +.noUi-marker { + position: absolute; + background: #CCC; +} + +.noUi-marker-sub { + background: #AAA; +} + +.noUi-marker-large { + background: #AAA; +} + + +/* Horizontal layout; + * + */ + +.noUi-pips-horizontal { + padding: 10px 0; + height: 80px; + top: 100%; + left: 0; + width: 100%; +} + +.noUi-value-horizontal { + transform: translate(-50%, 50%); +} + +.noUi-rtl .noUi-value-horizontal { + transform: translate(50%, 50%); +} + +.noUi-marker-horizontal.noUi-marker { + margin-left: -1px; + width: 2px; + height: 5px; +} + +.noUi-marker-horizontal.noUi-marker-sub { + height: 10px; +} + +.noUi-marker-horizontal.noUi-marker-large { + height: 15px; +} + + +/* Vertical layout; + * + */ + +.noUi-pips-vertical { + padding: 0 10px; + height: 100%; + top: 0; + left: 100%; +} + +.noUi-value-vertical { + -webkit-transform: translate(0, -50%); + transform: translate(0, -50%, 0); + padding-left: 25px; +} + +.noUi-rtl .noUi-value-vertical { + -webkit-transform: translate(0, 50%); + transform: translate(0, 50%); +} + +.noUi-marker-vertical.noUi-marker { + width: 5px; + height: 2px; + margin-top: -1px; +} + +.noUi-marker-vertical.noUi-marker-sub { + width: 10px; +} + +.noUi-marker-vertical.noUi-marker-large { + width: 15px; +} + +.noUi-tooltip { + display: block; + position: absolute; + border: 1px solid #D9D9D9; + border-radius: 3px; + background: #fff; + color: #000; + padding: 5px; + text-align: center; + white-space: nowrap; +} + +.noUi-horizontal .noUi-tooltip { + -webkit-transform: translate(-50%, 0); + transform: translate(-50%, 0); + left: 50%; + bottom: 120%; +} + +.noUi-vertical .noUi-tooltip { + -webkit-transform: translate(0, -50%); + transform: translate(0, -50%); + top: 50%; + right: 120%; +} + + +// Custom styles + +.noUi-target { + background: $noui-target-bg; + border-radius: $noui-target-border-radius; + border: 0; + box-shadow: $noui-target-box-shadow; + margin: 15px 0; + cursor: pointer; +} + +.noUi-horizontal { + height: $noui-target-thickness; +} + + +.noUi-vertical { + width: $noui-target-thickness; +} + +.noUi-connect { + background: theme-color("primary"); + box-shadow: none; +} + +.noUi-handle { + +} + +.noUi-horizontal .noUi-handle, +.noUi-vertical .noUi-handle { + top: -$noui-target-thickness; + width: $noui-handle-width; + height: $noui-handle-width; + border-radius: 100%; + box-shadow: none; + cursor: pointer; + background-color: $noui-handle-bg; + border: $noui-handle-border; + transition: box-shadow .15s, transform .15s; +} + +.noUi-horizontal .noUi-handle.noUi-active, +.noUi-vertical .noUi-handle.noUi-active { + box-shadow: 0px 0px 0px 2px rgba($noui-handle-bg, 1); +} + +.input-slider--cyan .noUi-connect { + background: $cyan; +} + + +/* Disabled state */ + +[disabled] .noUi-connect, +[disabled].noUi-connect { + background: $noui-slider-connect-disabled-bg; +} + +[disabled] .noUi-handle, +[disabled].noUi-origin { + cursor: not-allowed; +} + +/* Range slider value labels */ + +.range-slider-value { + font-size: $font-size-xs; + font-weight: 500; + background-color: rgba($dark, .7); + color: color-yiq($dark); + border-radius: 10px; + padding: .4em .8em .3em .85em; +} + +.range-slider-wrapper .upper-info { + font-weight: 400; + margin-bottom: 5px; +} + +.input-slider-value-output { + background: #333; + color: #fff; + padding: 4px 8px; + position: relative; + top: 12px; + font-size: 11px; + border-radius: 2px; +} + +.input-slider-value-output:after { + bottom: 100%; + left: 10px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border-color: rgba(136, 183, 213, 0); + border-bottom-color: #333; + border-width: 4px; + margin-left: -4px; +} + +.input-slider-value-output.left:after { + left: 10px; + right: auto; +} + +.input-slider-value-output.right:after { + right: 10px; + left: auto; +} diff --git a/frontend/src/assets/scss/core/vendors/_scrollbar.scss b/frontend/src/assets/scss/core/vendors/_scrollbar.scss new file mode 100644 index 000000000..4aff7d92d --- /dev/null +++ b/frontend/src/assets/scss/core/vendors/_scrollbar.scss @@ -0,0 +1,35 @@ +// +// Custom scrollbar +// + +.scrollbar-inner { + height: 100%; + + &:not(:hover) .scroll-element { + opacity: 0; + } + + .scroll-element { + transition: opacity 300ms; + margin-right: 2px; + + .scroll-bar, + .scroll-element_track { + transition: background-color 300ms; + } + + .scroll-element_track { + background-color: transparent; + } + } + + .scroll-element.scroll-y { + width: 3px; + right: 0; + } + + .scroll-element.scroll-x { + height: 3px; + bottom: 0; + } +} diff --git a/frontend/src/assets/scss/custom/_alert.scss b/frontend/src/assets/scss/custom/_alert.scss new file mode 100644 index 000000000..2ef0b7c2f --- /dev/null +++ b/frontend/src/assets/scss/custom/_alert.scss @@ -0,0 +1,6 @@ +// +// Alert +// + +@import "../core/alerts/alert"; +@import "../core/alerts/alert-dismissible"; diff --git a/frontend/src/assets/scss/custom/_avatar.scss b/frontend/src/assets/scss/custom/_avatar.scss new file mode 100644 index 000000000..98818a6d6 --- /dev/null +++ b/frontend/src/assets/scss/custom/_avatar.scss @@ -0,0 +1,6 @@ +// +// Avatar +// + +@import "../core/avatars/avatar"; +@import "../core/avatars/avatar-group"; diff --git a/frontend/src/assets/scss/custom/_badge.scss b/frontend/src/assets/scss/custom/_badge.scss new file mode 100644 index 000000000..2682e1a2f --- /dev/null +++ b/frontend/src/assets/scss/custom/_badge.scss @@ -0,0 +1,7 @@ +// +// Badge +// + +@import "../core/badges/badge"; +@import "../core/badges/badge-circle"; +@import "../core/badges/badge-dot"; diff --git a/frontend/src/assets/scss/custom/_buttons.scss b/frontend/src/assets/scss/custom/_buttons.scss new file mode 100644 index 000000000..4f2888c65 --- /dev/null +++ b/frontend/src/assets/scss/custom/_buttons.scss @@ -0,0 +1,7 @@ +// +// Button +// + +@import "../core/buttons/button"; +@import "../core/buttons/button-icon"; +@import "../core/buttons/button-brand"; diff --git a/frontend/src/assets/scss/custom/_card.scss b/frontend/src/assets/scss/custom/_card.scss new file mode 100644 index 000000000..1eb5ff336 --- /dev/null +++ b/frontend/src/assets/scss/custom/_card.scss @@ -0,0 +1,9 @@ +// +// Cards +// + +@import "../core/cards/card"; +@import "../core/cards/card-profile"; +@import "../core/cards/card-blockquote"; +@import "../core/cards/card-animations"; +@import "../core/cards/card-stats"; diff --git a/frontend/src/assets/scss/custom/_chart.scss b/frontend/src/assets/scss/custom/_chart.scss new file mode 100644 index 000000000..836ade8b7 --- /dev/null +++ b/frontend/src/assets/scss/custom/_chart.scss @@ -0,0 +1,5 @@ +// +// Chart +// + +@import "../core/charts/chart"; diff --git a/frontend/src/assets/scss/custom/_close.scss b/frontend/src/assets/scss/custom/_close.scss new file mode 100644 index 000000000..292d6a090 --- /dev/null +++ b/frontend/src/assets/scss/custom/_close.scss @@ -0,0 +1,5 @@ +// +// Close +// + +@import "../core/close/close" diff --git a/frontend/src/assets/scss/custom/_components.scss b/frontend/src/assets/scss/custom/_components.scss new file mode 100644 index 000000000..8a71d41f6 --- /dev/null +++ b/frontend/src/assets/scss/custom/_components.scss @@ -0,0 +1,31 @@ +// +// Components +// + +@import "custom/alert"; +@import "custom/avatar"; +@import "custom/badge"; +@import "custom/buttons"; +@import "custom/card"; +@import "custom/chart"; +@import "custom/close"; +@import "custom/content"; +@import "custom/custom-forms"; +@import "custom/dropdown"; +@import "custom/footer"; +@import "custom/forms"; +@import "custom/header"; +@import "custom/icons"; +@import "custom/input-group"; +@import "custom/list-group"; +@import "custom/map"; +@import "custom/mask"; +@import "custom/modal"; +@import "custom/nav"; +@import "custom/navbar"; +@import "custom/pagination"; +@import "custom/popover"; +@import "custom/progress"; +@import "custom/separator"; +@import "custom/tables"; +@import "custom/type"; diff --git a/frontend/src/assets/scss/custom/_content.scss b/frontend/src/assets/scss/custom/_content.scss new file mode 100644 index 000000000..d0e638bb0 --- /dev/null +++ b/frontend/src/assets/scss/custom/_content.scss @@ -0,0 +1,47 @@ +.main-content { + position: relative; + + // Navbar + .navbar-top { + position: absolute; + left: 0; + top: 0; + width: 100%; + z-index: 1; + background-color: transparent; + padding-left: 0 !important; + padding-right: 0 !important; + } + + // Container + .container-fluid { + @include media-breakpoint-up(md) { + padding-left: ($main-content-padding-x + $grid-gutter-width / 2) !important; + padding-right: ($main-content-padding-x + $grid-gutter-width / 2) !important; + } + } +} + + +// Offsets the main content depending on the sidebar positioning + +.navbar-vertical.navbar-expand { + + @each $breakpoint, + $dimension in $grid-breakpoints { + + &-#{$breakpoint} { + + @include media-breakpoint-up(#{$breakpoint}) { + + // Left + &.fixed-left + .main-content { + margin-left: $navbar-vertical-width; + } // Right + &.fixed-right + .main-content { + margin-right: $navbar-vertical-width; + } + } + } + } +} diff --git a/frontend/src/assets/scss/custom/_custom-forms.scss b/frontend/src/assets/scss/custom/_custom-forms.scss new file mode 100644 index 000000000..92d8290be --- /dev/null +++ b/frontend/src/assets/scss/custom/_custom-forms.scss @@ -0,0 +1,9 @@ +// +// Custom form +// + +@import "../core/custom-forms/custom-form"; +@import "../core/custom-forms/custom-control"; +@import "../core/custom-forms/custom-checkbox"; +@import "../core/custom-forms/custom-radio"; +@import "../core/custom-forms/custom-toggle"; diff --git a/frontend/src/assets/scss/custom/_dropdown.scss b/frontend/src/assets/scss/custom/_dropdown.scss new file mode 100644 index 000000000..54314b6d3 --- /dev/null +++ b/frontend/src/assets/scss/custom/_dropdown.scss @@ -0,0 +1,5 @@ +// +// Dropdown +// + +@import "../core/dropdowns/dropdown"; diff --git a/frontend/src/assets/scss/custom/_footer.scss b/frontend/src/assets/scss/custom/_footer.scss new file mode 100644 index 000000000..9b65604a7 --- /dev/null +++ b/frontend/src/assets/scss/custom/_footer.scss @@ -0,0 +1,5 @@ +// +// Footer +// + +@import "../core/footers/footer"; diff --git a/frontend/src/assets/scss/custom/_forms.scss b/frontend/src/assets/scss/custom/_forms.scss new file mode 100644 index 000000000..835edea84 --- /dev/null +++ b/frontend/src/assets/scss/custom/_forms.scss @@ -0,0 +1,7 @@ +// +// Forms +// + +@import "../core/forms/form"; +@import "../core/forms/form-validation"; +@import "../core/forms/input-group"; diff --git a/frontend/src/assets/scss/custom/_functions.scss b/frontend/src/assets/scss/custom/_functions.scss new file mode 100644 index 000000000..d0b556c56 --- /dev/null +++ b/frontend/src/assets/scss/custom/_functions.scss @@ -0,0 +1,33 @@ +// +// Functions +// + +// Bootstrap default functions + +@import "~bootstrap/scss/functions"; + + +// Retrieve color Sass maps + +@function section-color($key: "primary") { + @return map-get($section-colors, $key); +} + + +// Lines colors + +@function shapes-primary-color($key: "step-1-gradient-bg") { + @return map-get($shapes-primary-colors, $key); +} + +@function shapes-default-color($key: "step-1-gradient-bg") { + @return map-get($shapes-default-colors, $key); +} + +@function lines-light-color($key: "step-1-gradient-bg") { + @return map-get($shapes-light-colors, $key); +} + +@function shapes-dark-color($key: "step-1-gradient-bg") { + @return map-get($shapes-dark-colors, $key); +} diff --git a/frontend/src/assets/scss/custom/_header.scss b/frontend/src/assets/scss/custom/_header.scss new file mode 100644 index 000000000..d3fb2bb42 --- /dev/null +++ b/frontend/src/assets/scss/custom/_header.scss @@ -0,0 +1,5 @@ +// +// Header +// + +@import "../core/headers/header"; diff --git a/frontend/src/assets/scss/custom/_icons.scss b/frontend/src/assets/scss/custom/_icons.scss new file mode 100644 index 000000000..86df08e38 --- /dev/null +++ b/frontend/src/assets/scss/custom/_icons.scss @@ -0,0 +1,6 @@ +// +// Icon +// + +@import "../core/icons/icon"; +@import "../core/icons/icon-shape"; diff --git a/frontend/src/assets/scss/custom/_input-group.scss b/frontend/src/assets/scss/custom/_input-group.scss new file mode 100644 index 000000000..cc8f3dcef --- /dev/null +++ b/frontend/src/assets/scss/custom/_input-group.scss @@ -0,0 +1,5 @@ +// +// Input group +// + +@import "../core/forms/input-group"; diff --git a/frontend/src/assets/scss/custom/_list-group.scss b/frontend/src/assets/scss/custom/_list-group.scss new file mode 100644 index 000000000..c630aa9ab --- /dev/null +++ b/frontend/src/assets/scss/custom/_list-group.scss @@ -0,0 +1,5 @@ +// +// List group +// + +@import "../core/list-groups/list-group"; diff --git a/frontend/src/assets/scss/custom/_map.scss b/frontend/src/assets/scss/custom/_map.scss new file mode 100644 index 000000000..85983c632 --- /dev/null +++ b/frontend/src/assets/scss/custom/_map.scss @@ -0,0 +1,5 @@ +// +// Maps +// + +@import "../core/maps/map"; diff --git a/frontend/src/assets/scss/custom/_mask.scss b/frontend/src/assets/scss/custom/_mask.scss new file mode 100644 index 000000000..7b2788745 --- /dev/null +++ b/frontend/src/assets/scss/custom/_mask.scss @@ -0,0 +1,5 @@ +// +// Mask +// + +@import "../core/masks/mask"; diff --git a/frontend/src/assets/scss/custom/_mixins.scss b/frontend/src/assets/scss/custom/_mixins.scss new file mode 100644 index 000000000..89e370a42 --- /dev/null +++ b/frontend/src/assets/scss/custom/_mixins.scss @@ -0,0 +1,19 @@ +// +// Mixins +// + +// Bootstrap default mixins + +@import "~bootstrap/scss/mixins"; + + +// Custom mixins + +@import "../core/mixins/alert"; +@import "../core/mixins/badge"; +@import "../core/mixins/background-variant"; +@import "../core/mixins/buttons"; +@import "../core/mixins/forms"; +@import "../core/mixins/icon"; +@import "../core/mixins/modals"; +@import "../core/mixins/popover"; diff --git a/frontend/src/assets/scss/custom/_modal.scss b/frontend/src/assets/scss/custom/_modal.scss new file mode 100644 index 000000000..a33f2e9d8 --- /dev/null +++ b/frontend/src/assets/scss/custom/_modal.scss @@ -0,0 +1,5 @@ +// +// Modal +// + +@import "../core/modals/modal"; diff --git a/frontend/src/assets/scss/custom/_nav.scss b/frontend/src/assets/scss/custom/_nav.scss new file mode 100644 index 000000000..b7c7a0b04 --- /dev/null +++ b/frontend/src/assets/scss/custom/_nav.scss @@ -0,0 +1,7 @@ +// +// Nav +// + + +@import "../core/navs/nav"; +@import "../core/navs/nav-pills"; diff --git a/frontend/src/assets/scss/custom/_navbar.scss b/frontend/src/assets/scss/custom/_navbar.scss new file mode 100644 index 000000000..db24441ff --- /dev/null +++ b/frontend/src/assets/scss/custom/_navbar.scss @@ -0,0 +1,9 @@ +// +// Navbar +// + +@import "../core/navbars/navbar"; +@import "../core/navbars/navbar-vertical"; +@import "../core/navbars/navbar-search"; +@import "../core/navbars/navbar-dropdown"; +@import "../core/navbars/navbar-collapse"; diff --git a/frontend/src/assets/scss/custom/_pagination.scss b/frontend/src/assets/scss/custom/_pagination.scss new file mode 100644 index 000000000..557a8e0cd --- /dev/null +++ b/frontend/src/assets/scss/custom/_pagination.scss @@ -0,0 +1,5 @@ +// +// Pagination +// + +@import "../core/paginations/pagination"; diff --git a/frontend/src/assets/scss/custom/_popover.scss b/frontend/src/assets/scss/custom/_popover.scss new file mode 100644 index 000000000..5e062c459 --- /dev/null +++ b/frontend/src/assets/scss/custom/_popover.scss @@ -0,0 +1,6 @@ +// +// Popover +// + + +@import "../core/popovers/popover"; diff --git a/frontend/src/assets/scss/custom/_progress.scss b/frontend/src/assets/scss/custom/_progress.scss new file mode 100644 index 000000000..bf5840643 --- /dev/null +++ b/frontend/src/assets/scss/custom/_progress.scss @@ -0,0 +1,5 @@ +// +// Progress +// + +@import "../core/progresses/progress"; diff --git a/frontend/src/assets/scss/custom/_reboot.scss b/frontend/src/assets/scss/custom/_reboot.scss new file mode 100644 index 000000000..4a49a6984 --- /dev/null +++ b/frontend/src/assets/scss/custom/_reboot.scss @@ -0,0 +1,13 @@ +iframe { + border: 0; +} + +figcaption, +figure, +main { + display: block; +} + +main { + overflow: hidden; +} diff --git a/frontend/src/assets/scss/custom/_section.scss b/frontend/src/assets/scss/custom/_section.scss new file mode 100644 index 000000000..db88d4025 --- /dev/null +++ b/frontend/src/assets/scss/custom/_section.scss @@ -0,0 +1,139 @@ +// +// Sections +// + + +// Nucleo icons for presentation purpose + +.section-nucleo-icons { + + --icon-size: 5rem; + --icon-sm-size: 3.75rem; + --gutter: 7rem; + + .icons-container { + position: relative; + max-width: 100%; + height: 360px; + margin: 0 auto; + z-index: 1; + + i { + position: absolute; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background: $white; + z-index: 1; + transform: translate(-50%, -50%); + @include box-shadow($box-shadow); + transition: all .2s cubic-bezier(.25,.65,.9,.75); + + &.icon { + width: var(--icon-size); + height: var(--icon-size); + font-size: 1.7em; + } + + &.icon-sm { + width: var(--icon-sm-size); + height: var(--icon-sm-size); + font-size: 1.5em; + } + + &:nth-child(1) { + font-size: 42px; + color: theme-color("warning"); + z-index: 2; + } + } + + &:not(.on-screen) { + i { + transform: translate(-50%, -50%); + left: 50%; + top: 50%; + + &:not(:nth-child(1)) { + opacity: 0; + } + } + } + + &.on-screen { + + i { + opacity: 1; + + &:nth-child(1) { + left: 50%; + top: 50%; + font-size: 42px; + color: theme-color("warning"); + } + + &:nth-child(2) { + left: calc(50% + (var(--gutter) * 1.7)); + top: 50%; + } + + &:nth-child(3) { + left: calc(50% + var(--gutter)); + top: calc(50% + var(--gutter)); + } + + &:nth-child(4) { + left: calc(50% + var(--gutter)); + top: calc(50% - var(--gutter)); + } + + &:nth-child(5) { + left: calc(50% + (var(--gutter) * 4)); + top: 50%; + } + + &:nth-child(6) { + left: calc(50% + (var(--gutter) * 2.7)); + top: calc(50% + (var(--gutter) * 1.5)); + } + + &:nth-child(7) { + left: calc(50% + (var(--gutter) * 2.7)); + top: calc(50% - (var(--gutter) * 1.5)); + } + + &:nth-child(8) { + left: calc(50% - (var(--gutter) * 1.7)); + top: 50%; + } + + &:nth-child(9) { + left: calc(50% - var(--gutter)); + top: calc(50% + var(--gutter)); + } + + &:nth-child(10) { + left: calc(50% - var(--gutter)); + top: calc(50% - var(--gutter)); + } + + &:nth-child(11) { + left: calc(50% - (var(--gutter) * 4)); + top: 50%; + } + + &:nth-child(12) { + left: calc(50% - (var(--gutter) * 2.7)); + top: calc(50% + (var(--gutter) * 1.5)); + } + + &:nth-child(13) { + left: calc(50% - (var(--gutter) * 2.7)); + top: calc(50% - (var(--gutter) * 1.5)); + } + } + + } + } +} diff --git a/frontend/src/assets/scss/custom/_separator.scss b/frontend/src/assets/scss/custom/_separator.scss new file mode 100644 index 000000000..b4df82a6c --- /dev/null +++ b/frontend/src/assets/scss/custom/_separator.scss @@ -0,0 +1,5 @@ +// +// Separator +// + +@import "../core/separators/separator"; diff --git a/frontend/src/assets/scss/custom/_tables.scss b/frontend/src/assets/scss/custom/_tables.scss new file mode 100644 index 000000000..be176ef0a --- /dev/null +++ b/frontend/src/assets/scss/custom/_tables.scss @@ -0,0 +1,5 @@ +// +// Tables +// + +@import "../core/tables/table"; diff --git a/frontend/src/assets/scss/custom/_type.scss b/frontend/src/assets/scss/custom/_type.scss new file mode 100644 index 000000000..6be0c5a69 --- /dev/null +++ b/frontend/src/assets/scss/custom/_type.scss @@ -0,0 +1,8 @@ +// +// Typography +// + +@import "../core/type/type"; +@import "../core/type/heading"; +@import "../core/type/display"; +@import "../core/type/article"; diff --git a/frontend/src/assets/scss/custom/_utilities.scss b/frontend/src/assets/scss/custom/_utilities.scss new file mode 100644 index 000000000..c73c09814 --- /dev/null +++ b/frontend/src/assets/scss/custom/_utilities.scss @@ -0,0 +1,16 @@ +// +// Utilities +// + +@import "../core/utilities/backgrounds"; +@import "../core/utilities/floating"; +@import "../core/utilities/helper"; +@import "../core/utilities/image"; +@import "../core/utilities/opacity"; +@import "../core/utilities/overflow"; +@import "../core/utilities/position"; +@import "../core/utilities/sizing"; +@import "../core/utilities/spacing"; +@import "../core/utilities/shadows"; +@import "../core/utilities/text"; +@import "../core/utilities/transform"; diff --git a/frontend/src/assets/scss/custom/_variables.scss b/frontend/src/assets/scss/custom/_variables.scss new file mode 100644 index 000000000..07cd1500e --- /dev/null +++ b/frontend/src/assets/scss/custom/_variables.scss @@ -0,0 +1,1009 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// +// Variables +// + +// Global settings + +$enable-caret: true !default; +$enable-rounded: true !default; +$enable-shadows: true !default; +$enable-gradients: false !default; +$enable-transitions: true !default; +$enable-grid-classes: true !default; +$enable-print-styles: true !default; + + +// Color system + +$white: #fff !default; +$gray-100: #f6f9fc !default; +$gray-200: #e9ecef !default; +$gray-300: #dee2e6 !default; +$gray-400: #ced4da !default; +$gray-500: #adb5bd !default; +$gray-600: #8898aa !default; // Line footer color +$gray-700: #525f7f !default; // Line p color +$gray-800: #32325d !default; // Line heading color +$gray-900: #212529 !default; +$black: #000 !default; + +$grays: () !default; +$grays: map-merge(( + "100": $gray-100, + "200": $gray-200, + "300": $gray-300, + "400": $gray-400, + "500": $gray-500, + "600": $gray-600, + "700": $gray-700, + "800": $gray-800, + "900": $gray-900 +), $grays); + +$blue: #5e72e4 !default; +$indigo: #5603ad !default; +$purple: #8965e0 !default; +$pink: #f3a4b5 !default; +$red: #f5365c !default; +$orange: #fb6340 !default; +$yellow: #ffd600 !default; +$green: #2dce89 !default; +$teal: #11cdef !default; +$cyan: #2bffc6 !default; + +$colors: () !default; +$colors: map-merge(( + "blue": $blue, + "indigo": $indigo, + "purple": $purple, + "pink": $pink, + "red": $red, + "orange": $orange, + "yellow": $yellow, + "green": $green, + "teal": $teal, + "cyan": $cyan, + "white": $white, + "gray": $gray-600, + "light": $gray-400, + "lighter": $gray-200, + "gray-dark": $gray-800 +), $colors); + +$default: #172b4d !default; +$primary: #5e72e4 !default; +$secondary: #f7fafc !default; +$success: $green !default; +$info: $teal !default; +$warning: $orange !default; +$danger: $red !default; +$light: $gray-500 !default; +$dark: $gray-900 !default; +$darker: darken($gray-900, 15%) !default; + +$facebook: #3b5999 !default; +$twitter: #1da1f2 !default; +$google-plus: #dd4b39 !default; +$instagram: #e4405f !default; +$pinterest: #bd081c !default; +$youtube: #cd201f !default; +$slack: #3aaf85 !default; +$dribbble: #ea4c89 !default; +$github: #222222 !default; + +$theme-colors: () !default; +$theme-colors: map-merge(( + "default": $default, + "primary": $primary, + "secondary": $secondary, + "success": $success, + "info": $info, + "warning": $warning, + "danger": $danger, + "white": $white, + "neutral": $white, + "dark": $dark, + "darker": $darker +), $theme-colors); + +$brand-colors: () !default; +$brand-colors: map-merge(( + "facebook": $facebook, + "twitter": $twitter, + "google-plus": $google-plus, + "instagram": $instagram, + "pinterest": $pinterest, + "youtube": $youtube, + "slack": $slack, + "dribbble": $dribbble, + "github": $github +), $brand-colors); + +$shape-colors: () !default; +$shape-colors: map-merge(( + "default": #32325d, + "primary": #5533ff, + "secondary": #24b47e, + "neutral": #e9ecef, + "blue-gray": #b2cbe1, + +), $shape-colors); + +$shapes-primary-colors: () !default; +$shapes-primary-colors: map-merge(( + "step-1-gradient-bg": #281483, + "step-2-gradient-bg": #8f6ed5, + "step-3-gradient-bg": #d782d9, + "span-1-bg": #53f, + "span-2-bg": #4553ff, + "span-3-bg": #4f40ff, + "span-4-bg": #25ddf5, + "span-5-bg": #1fa2ff +), $shapes-primary-colors); + +$shapes-default-colors: () !default; +$shapes-default-colors: map-merge(( + "step-1-gradient-bg": #7795f8, + "step-2-gradient-bg": #6772e5, + "step-3-gradient-bg": #555abf, + "span-1-bg": #7795f8, + "span-2-bg": #7b9aff, + "span-3-bg": #6f8ff8, + "span-4-bg": #76eea7, + "span-5-bg": #6adaff +), $shapes-default-colors); + +$shapes-light-colors: () !default; +$shapes-light-colors: map-merge(( + "step-1-gradient-bg": #b2cbe1, + "step-2-gradient-bg": #f6f9fc, + "step-3-gradient-bg": #f6f9fc, + "span-1-bg": #b4cce1, + "span-2-bg": #c5dbef, + "span-3-bg": #b9d5ed, + "span-4-bg": #74e4a2, + "span-5-bg": #008169 +), $shapes-light-colors); + +$shapes-dark-colors: () !default; +$shapes-dark-colors: map-merge(( + "step-1-gradient-bg": #32325d, + "step-2-gradient-bg": #32325d, + "step-3-gradient-bg": #32325d, + "span-1-bg": #2e2e57, + "span-2-bg": #2b2b58, + "span-3-bg": #25254d, + "span-4-bg": #d782d9, + "span-5-bg": #008169 +), $shapes-dark-colors); + + +// Translucent color variations +$translucent-color-opacity: .6 !default; + +// Set a specific jump point for requesting color jumps +$theme-color-interval: 8% !default; + +// The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255. +$yiq-contrasted-threshold: 200 !default; + +// Customize the light and dark text colors for use in our YIQ color contrast function. +$yiq-text-dark: $gray-900 !default; +$yiq-text-light: $white !default; + +// Action colors + +$star-rating-color: $gray-400 !default; +$star-rating-color-active: $yellow !default; + +$favorite-color: $yellow !default; +$like-color: $blue !default; +$love-color: $red !default; + + +// Body + + +$body-bg: #f8f9fe !default; +$body-color: $gray-700 !default; + + + +// Sections + +$section-colors: () !default; +$section-colors: map-merge(( + "primary": $body-bg, + "secondary": $secondary, + "light": $gray-400, + "dark": $dark, + "darker": $darker +), $section-colors); + +// Links + +$link-color: $primary !default; +$link-decoration: none !default; +$link-hover-color: darken($link-color, 15%) !default; +$link-hover-decoration: none !default; + +// Grid breakpoints + +$grid-breakpoints: ( + xs: 0, + sm: 576px, + md: 768px, + lg: 992px, + xl: 1200px +); + +@include _assert-ascending($grid-breakpoints, "$grid-breakpoints"); +@include _assert-starts-at-zero($grid-breakpoints); + + +// Grid containers +// +// Define the maximum width of `.container` for different screen sizes. + + + +// Spacing + +$spacer: 1rem !default; +$spacers: () !default; +$spacers: map-merge(( + -9: -($spacer * 10), + -8: -($spacer * 8), + -7: -($spacer * 6), + -6: -($spacer * 4.5), + -5: -($spacer * 3), + -4: -($spacer * 1.5), + -3: -$spacer, + -2: -($spacer * .5), + -1: -($spacer * .25), + 0: 0, + 1: ($spacer * .25), + 2: ($spacer * .5), + 3: $spacer, + 4: ($spacer * 1.5), + 5: ($spacer * 3), + 6: ($spacer * 4.5), + 7: ($spacer * 6), + 8: ($spacer * 8), + 9: ($spacer * 10) +), $spacers); + + +// This variable affects the `.h-*` and `.w-*` classes. + +$sizes: () !default; +$sizes: map-merge(( + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100% +), $sizes); + +// Components + +$shape-height-xl: 1.5 !default; +$shape-height-lg: 1.5 !default; +$shape-height-sm: 1.5 !default; + +$border-width: 1px !default; +$border-color: $gray-200 !default; + +$border-radius: .375rem !default; +$border-radius-xl: .5rem !default; +$border-radius-lg: .4375rem !default; +$border-radius-sm: .25rem !default; + +$box-shadow-sm: 0 0 .5rem rgba($gray-600, .075) !default; +$box-shadow: 0 0 2rem 0 rgba($gray-600, .15) !default; +$box-shadow-lg: 0 0 3rem rgba($gray-600, .175) !default; + +$component-active-color: $white !default; +$component-active-bg: theme-color("primary") !default; +$component-active-border-color: theme-color("primary") !default; + +$component-hover-color: $gray-300 !default; +$component-hover-bg: $gray-300 !default; +$component-hover-border-color: $gray-300 !default; + +$caret-width: .3em !default; + +$transition-base: all .15s ease !default; +$transition-fade: opacity .15s linear !default; +$transition-collapse: height .35s ease !default; + + +// Fonts + +$font-family-sans-serif: Open Sans, sans-serif !default; +$font-family-base: $font-family-sans-serif !default; + +$font-size-base: 1rem !default; // Assumes the browser default, typically `16px` +$font-size-xl: ($font-size-base * 1.5); +$font-size-lg: ($font-size-base * 1.25); +$font-size-sm: ($font-size-base * .875); +$font-size-xs: ($font-size-base * .75); + +$font-weight-light: 300 !default; +$font-weight-normal: 400 !default; +$font-weight-bold: 600 !default; +$font-weight-extra-bold: 700 !default; + +$font-weight-base: $font-weight-normal !default; +$line-height-base: 1.5 !default; +$shape-height-base: 1.5 !default; + + +$h1-font-size: $font-size-base * 1.625 !default; +$h2-font-size: $font-size-base * 1.25 !default; +$h3-font-size: $font-size-base * 1.0625 !default; +$h4-font-size: $font-size-base * .9375 !default; +$h5-font-size: $font-size-base * .8125 !default; +$h6-font-size: $font-size-base * .625 !default; + + +$headings-margin-bottom: ($spacer / 2); +$headings-font-family: inherit !default; +$headings-font-weight: $font-weight-bold !default; +$headings-line-height: 1.5 !default; +$headings-color: $gray-800 !default; + +$heading-letter-spacing: .025em !default; +$heading-font-size: .95rem !default; +$heading-text-transform: uppercase !default; +$heading-font-weight: $headings-font-weight !default; + +$heading-title-letter-spacing: .025em !default; +$heading-title-font-size: 1.375rem !default; +$heading-title-font-weight: $font-weight-bold !default; +$heading-title-text-transform: uppercase !default; + +$heading-section-letter-spacing: .025em !default; +$heading-section-font-size: 1.375rem !default; +$heading-section-font-weight: $font-weight-bold !default; +$heading-section-text-transform: uppercase !default; + +$display1-size: 3.3rem !default; +$display2-size: 2.75rem !default; +$display3-size: 2.1875rem !default; +$display4-size: 1.6275rem !default; + +$display1-weight: $font-weight-bold !default; +$display2-weight: $font-weight-bold !default; +$display3-weight: $font-weight-bold !default; +$display4-weight: $font-weight-bold !default; +$display-line-height: $headings-line-height !default; + +$paragraph-font-size: 1rem !default; +$paragraph-font-weight: 300 !default; +$paragraph-line-height: 1.7 !default; + +$lead-font-size: ($paragraph-font-size * 1.25) !default; +$lead-font-weight: 300 !default; + +$small-font-size: 80% !default; + +$text-muted: $gray-600 !default; + +$blockquote-small-color: $gray-600 !default; +$blockquote-font-size: ($font-size-base * 1.25) !default; + +$hr-border-color: rgba($black, .1); +$hr-border-width: $border-width !default; + +$mark-padding: .2em !default; + +$dt-font-weight: $font-weight-bold !default; + +$list-inline-padding: .5rem !default; + +$mark-bg: #fcf8e3 !default; + +$hr-margin-y: $spacer * 2 !default; + + +// Icons + +$icon-size: 3rem !default; +$icon-size-xl: 5rem !default; +$icon-size-lg: 4rem !default; +$icon-size-sm: 2rem !default; + + +// Tables + +$table-cell-padding: 1rem !default; +$table-cell-padding-sm: .5rem !default; + +$table-bg: transparent !default; +$table-accent-bg: rgba($black, .05) !default; +$table-hover-bg: $gray-100 !default; +$table-active-bg: $table-hover-bg !default; + +$table-border-width: $border-width !default; +$table-border-color: $gray-200 !default; + +$table-head-bg: $gray-100 !default; +$table-head-color: $gray-600 !default; +$table-head-spacer-y: .75rem !default; + +$table-head-font-size: .65rem !default; +$table-head-font-weight: $font-weight-bold !default; +$table-head-text-transform: uppercase !default; +$table-head-letter-spacing: 1px !default; + +$table-body-font-size: .8125rem !default; + +$table-dark-bg: theme-color("default") !default; +$table-dark-accent-bg: rgba($white, .05) !default; +$table-dark-hover-bg: rgba($white, .075) !default; +$table-dark-border-color: lighten(theme-color("default"), 7%) !default; +$table-dark-color: $body-bg !default; + +$table-dark-head-bg: lighten(theme-color("default"), 4%) !default; +$table-dark-head-color: lighten(theme-color("default"), 35%) !default; + +// Buttons + Forms + +$input-btn-padding-y: .625rem !default; +$input-btn-padding-x: .75rem !default; +$input-btn-line-height: $shape-height-base !default; + +$input-btn-focus-width: 0 !default; +$input-btn-focus-color: rgba($component-active-bg, 1) !default; +$input-btn-focus-box-shadow: none !default; + +$input-btn-padding-y-sm: .25rem !default; +$input-btn-padding-x-sm: .5rem !default; +$input-btn-line-height-sm: $shape-height-sm !default; + +$input-btn-padding-y-lg: .875rem !default; +$input-btn-padding-x-lg: 1rem !default; +$input-btn-line-height-lg: $shape-height-lg !default; + +$input-btn-border-width: 1px !default; + +$input-btn-font-size-sm: .75rem !default; +$input-btn-font-size: .875rem !default; +$input-btn-font-size-lg: .875rem !default; + +// Buttons + +$btn-padding-y: $input-btn-padding-y !default; +$btn-padding-x: $input-btn-padding-x + 0.5 !default; +$btn-line-height: $input-btn-line-height !default; + +$btn-padding-y-sm: $input-btn-padding-y-sm !default; +$btn-padding-x-sm: $input-btn-padding-x-sm !default; +$btn-line-height-sm: $input-btn-line-height-sm !default; + +$btn-padding-y-lg: $input-btn-padding-y-lg !default; +$btn-padding-x-lg: $input-btn-padding-x-lg !default; +$btn-line-height-lg: $input-btn-line-height-lg !default; + +$btn-border-width: $input-btn-border-width !default; + +$btn-font-weight: 600 !default; + +$btn-text-transform: none !default; + + +$btn-letter-spacing: .025em !default; +$btn-box-shadow: 0 4px 6px rgba(50,50,93,.11), 0 1px 3px rgba(0,0,0,.08) !default; +$btn-hover-box-shadow: 0 7px 14px rgba(50,50,93,.1), 0 3px 6px rgba(0,0,0,.08) !default; +$btn-focus-box-shadow: $btn-hover-box-shadow !default; +$btn-focus-width: $input-btn-focus-width !default; +$btn-active-box-shadow: none !default; + +$btn-hover-translate-y: -1px !default; + +// Forms + +$input-padding-y: $input-btn-padding-y !default; +$input-padding-x: $input-btn-padding-x !default; +$input-line-height: $input-btn-line-height !default; + +$input-padding-y-sm: $input-btn-padding-y-sm !default; +$input-padding-x-sm: $input-btn-padding-x-sm !default; +$input-line-height-sm: $input-btn-line-height-sm !default; + +$input-padding-y-lg: $input-btn-padding-y-lg !default; +$input-padding-x-lg: $input-btn-padding-x-lg !default; +$input-line-height-lg: $input-btn-line-height-lg !default; + +$input-border-radius: $border-radius !default; +$input-border-radius-xl: $border-radius-xl !default; +$input-border-radius-lg: $border-radius-lg !default; +$input-border-radius-sm: $border-radius-sm !default; + +$input-bg: $white !default; +$input-disabled-bg: $gray-200 !default; + +$input-muted-bg: #F7FAFE !default; +$input-focus-muted-bg: lighten($input-muted-bg, 1%) !default; + +$input-alternative-box-shadow: 0 1px 3px rgba(50,50,93,.15), 0 1px 0 rgba(0,0,0,.02) !default; +$input-focus-alternative-box-shadow: 0 4px 6px rgba(50,50,93,.11),0 1px 3px rgba(0,0,0,.08) !default; + +$input-color: $gray-600 !default; +$input-border-color: #cad1d7 !default; +$input-border-width: $input-btn-border-width !default; +$input-box-shadow: none !default; // 0 1px 3px 0 $gray-400 !default; + +$input-focus-bg: $white !default; +$input-focus-border-color: rgba(50,151,211,.25) !default; +$input-focus-color: $input-color !default; +$input-focus-width: 0 !default; +$input-focus-box-shadow: none !default; //0 1px 3px 0 $gray-500 !default; + +$input-placeholder-color: $gray-500 !default; +$input-focus-placeholder-color: $gray-500 !default; + +$input-height-border: $input-border-width * 2 !default; + +$input-transition: all .2s cubic-bezier(0.68, -0.55, 0.265, 1.55) !default; + + +// Input groups + +$input-group-addon-color: $input-placeholder-color !default; +$input-group-addon-bg: $input-bg !default; +$input-group-addon-border-color: $input-border-color !default; + +$input-group-addon-focus-color: $input-focus-color !default; +$input-group-addon-focus-bg: $input-focus-bg !default; +$input-group-addon-focus-border-color: $input-focus-border-color !default; + + +// Form group + +$form-group-margin-bottom: 1.5rem !default; + + +// Custom forms + +$custom-control-gutter: 1.75rem !default; +$custom-control-spacer-x: 1rem !default; +$custom-control-indicator-size: 1.25rem !default; + +$custom-control-indicator-bg: $input-bg !default; +$custom-control-indicator-border-width: 1px !default; +$custom-control-indicator-border-color: $input-border-color !default; +$custom-control-indicator-box-shadow: none !default; + +$custom-control-indicator-focus-box-shadow: $custom-control-indicator-box-shadow !default; + +$custom-control-indicator-hover-color: $component-hover-color !default; +$custom-control-indicator-hover-bg: $component-hover-bg !default; +$custom-control-indicator-hover-border-color: $component-hover-border-color !default; + +$custom-control-indicator-active-color: $component-active-color !default; +$custom-control-indicator-active-bg: $component-active-bg !default; +$custom-control-indicator-active-border-color: $component-active-border-color !default; +$custom-control-indicator-active-box-shadow: $custom-control-indicator-box-shadow !default; + +$custom-control-indicator-checked-color: $component-active-color !default; +$custom-control-indicator-checked-bg: $component-active-bg !default; +$custom-control-indicator-checked-border-color: $component-active-border-color !default; +$custom-control-indicator-checked-box-shadow: $custom-control-indicator-box-shadow !default; +$custom-control-indicator-checked-disabled-bg: rgba(theme-color("primary"), .5) !default; + +$custom-control-indicator-disabled-bg: $gray-200 !default; +$custom-control-label-disabled-color: $gray-600 !default; + +$custom-checkbox-indicator-border-radius: $border-radius-sm !default; +//$custom-checkbox-indicator-icon-checked: str-replace(url("data:image/svg+xml !default;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"), "#", "%23") !default; + +// Custom toggle + +$custom-toggle-width: 50px !default; +$custom-toggle-slider-bg: $gray-200 !default; +$custom-toggle-checked-bg: theme-color("primary") !default; + +// Form validation + +$form-feedback-valid-bg: lighten($success, 15%) !default; +$form-feedback-valid-color: theme-color("success") !default; +$form-feedback-invalid-bg: lighten($warning, 15%) !default; +$form-feedback-invalid-color: theme-color("warning") !default; + + +// Allows for customizing button radius independently from global border radius + +$btn-border-radius: $input-border-radius !default; +$btn-border-radius-xl: $input-border-radius-xl !default; +$btn-border-radius-lg: $input-border-radius-lg !default; +$btn-border-radius-sm: $input-border-radius !default; + + + +$chart-height: 350px !default; +$chart-height-sm: 230px !default; + +$chart-legend-margin-top: 2.5rem !default; +$chart-legend-font-size: $font-size-sm !default; +$chart-legend-color: $text-muted !default; +$chart-legend-height: $chart-legend-margin-top + $chart-legend-font-size * $line-height-base !default; + + + + +// Map +$map-height: 500px !default; + + +// No UI Slider + +$noui-target-bg: #eceeef !default; +$noui-target-thickness: 5px !default; +$noui-target-border-radius: 5px !default; +$noui-target-border-color: 0 !default; +$noui-target-box-shadow: inset 0 1px 2px rgba(90,97,105,.1) !default; + +$noui-slider-connect-bg: $primary !default; +$noui-slider-connect-disabled-bg: #b2b2b2 !default; + +$noui-handle-width: 15px !default; +$noui-handle-bg: theme-color("primary") !default; +$noui-handle-border: 0 !default; +$noui-handle-border-radius: 100% !default; + +$noui-origin-border-radius: 2px !default; + + +// Dropdown + +$dropdown-bg: $white !default; +$dropdown-border-width: 0 !default; +$dropdown-border-color: rgba($black, .15) !default; +$dropdown-border-radius: $border-radius-lg !default; +$dropdown-box-shadow: 0 50px 100px rgba(50, 50, 93, .1), 0 15px 35px rgba(50, 50, 93, .15), 0 5px 15px rgba(0, 0, 0, .1) !default; + + +// Navs + +$nav-link-padding-y: .25rem !default; +$nav-link-padding-x: .75rem !default; +$nav-link-color: $gray-700 !default; +$nav-link-hover-color: theme-color("primary") !default; +$nav-link-disabled-color: $gray-600 !default; + +$nav-pills-padding-y: .75rem !default; +$nav-pills-padding-x: 1rem !default; + +$nav-pills-space-x: 1rem !default; + +$nav-pills-bg: $white !default; +$nav-pills-border-width: 1px !default; +$nav-pills-border-color: theme-color("primary") !default; +$nav-pills-border-radius: $border-radius !default; + +$nav-pills-link-color: theme-color("primary") !default; +$nav-pills-link-hover-color: darken(theme-color("primary"), 5%) !default; +$nav-pills-link-active-color: color-yiq(theme-color("primary")) !default; +$nav-pills-link-active-bg: theme-color("primary") !default; +$nav-pills-box-shadow: $btn-box-shadow !default; + +// Navbar + +$navbar-transition: all .15s linear !default; +$navbar-padding-y: 1rem !default; +$navbar-padding-x: 1rem !default; + +$navbar-nav-link-padding-x: 1rem !default; +$navbar-nav-link-padding-y: 1rem !default; + +$navbar-nav-link-font-size: .9rem !default; +$navbar-nav-link-font-weight: 400 !default; +$navbar-nav-link-text-transform: normal !default; +$navbar-nav-link-letter-spacing: 0 !default; +$navbar-nav-link-border-radius: $border-radius !default; + +$navbar-search-width: 270px !default; +$navbar-search-bg: transparent !default; + +$navbar-search-border-radius: 2rem !default; +$navbar-search-border-width: 2px !default; + +$navbar-dark-bg: transparent !default; +$navbar-dark-hover-bg: rgba(255, 255, 255, .1) !default; +$navbar-dark-active-bg: rgba(255, 255, 255, .1) !default; +$navbar-dark-color: rgba($white, .95) !default; +$navbar-dark-hover-color: rgba($white, .65) !default; +$navbar-dark-active-color: rgba($white, .65) !default; +$navbar-dark-disabled-color: rgba($white, .25) !default; +$navbar-dark-toggler-border-color: transparent !default; + +$navbar-search-dark-border-color: rgba(255, 255, 255, .6) !default; +$navbar-search-dark-color: rgba(255, 255, 255, .6) !default; +$navbar-search-dark-focus-border-color: rgba(255, 255, 255, .9) !default; +$navbar-search-dark-focus-color: rgba(255, 255, 255, .9) !default; + +$navbar-light-bg: transparent !default; +$navbar-light-hover-bg: rgba(0, 0, 0, .1) !default; +$navbar-light-active-bg: rgba(0, 0, 0, .1) !default; +$navbar-light-border-color: $gray-100 !default; +$navbar-light-color: rgba($black, .5) !default; +$navbar-light-hover-color: rgba($black, .7) !default; +$navbar-light-active-color: rgba($black, .9) !default; +$navbar-light-disabled-color: rgba($black, .3) !default; +$navbar-light-toggler-border-color: transparent !default; + +$navbar-search-light-border-color: rgba(0, 0, 0, .6) !default; +$navbar-search-light-color: rgba(0, 0, 0, .6) !default; +$navbar-search-light-focus-border-color: rgba(0, 0, 0, .9) !default; +$navbar-search-light-focus-color: rgba(0, 0, 0, .9) !default; + + + +// Vertical navbar +$navbar-vertical-box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15) !important; +$navbar-vertical-width: 250px !default; +$navbar-vertical-padding-x: 1.5rem !default; +$navbar-vertical-nav-link-padding-x: 1.5rem !default; +$navbar-vertical-nav-link-padding-y: .65rem !default; + +$navbar-icon-min-width: 2.25rem !default; + +$navbar-breadcrumb-padding-y: $nav-link-padding-y !default; +$navbar-breadcrumb-padding-x: 0 !default; + +$navbar-light-bg: $white !default; +$navbar-light-border-color: $border-color !default; + + + + +// Main content + +$main-content-padding-y: 40px !default; +$main-content-padding-x: 24px !default; // in px to combine with $grid-gutter-width + + +// Alerts + +$alert-padding-y: 1rem !default; +$alert-padding-x: 1.5rem !default; +$alert-border-radius: $border-radius !default; + +$alert-bg-level: -2 !default; +$alert-border-level: -2 !default; +$alert-color-level: 0 !default; + + +// List group + +$list-group-bg: $white !default; +$list-group-border-color: $border-color !default; //rgba($black, .125); +$list-group-border-width: $border-width !default; +$list-group-border-radius: $border-radius !default; + +$list-group-item-padding-y: 1rem !default; +$list-group-item-padding-x: 1rem !default; + +$list-group-hover-bg: $gray-100 !default; +$list-group-active-color: $component-active-color !default; +$list-group-active-bg: $component-active-bg !default; +$list-group-active-border-color: $list-group-active-bg !default; + +$list-group-disabled-color: $gray-600 !default; +$list-group-disabled-bg: $list-group-bg !default; + +$list-group-action-color: $gray-700 !default; +$list-group-action-hover-color: $list-group-action-color !default; + +$list-group-action-active-color: $list-group-action-color !default; +$list-group-action-active-bg: $gray-200 !default; + + +// Close + +$close-font-size: $font-size-base * 1.5 !default; +$close-font-weight: $font-weight-bold !default; +$close-bg: transparent !default; +$close-hover-bg: transparent !default; +$close-color: rgba(0, 0, 0, .6) !default !default; +$close-hover-color: rgba(0, 0, 0, .9) !default; +$close-text-shadow: none !default; + + +// Popovers + +$popover-font-size: $font-size-sm !default; +$popover-bg: $white !default; +$popover-max-width: 276px !default; +$popover-border-width: 1px !default; +$popover-border-color: rgba($black, .05) !default; +$popover-border-radius: $border-radius-lg !default; +$popover-box-shadow: 0px .5rem 2rem 0px rgba($black, .2) !default; + +$popover-header-bg: $popover-bg !default; +$popover-header-color: $headings-color !default; +$popover-header-padding-y: .5rem !default; +$popover-header-padding-x: .95rem !default; + +$popover-body-color: $body-color !default; +$popover-body-padding-y: $popover-header-padding-y !default; +$popover-body-padding-x: $popover-header-padding-x !default; + +$popover-arrow-width: 1.5rem !default; +$popover-arrow-height: .75rem !default; +$popover-arrow-color: $popover-bg !default; + +$popover-arrow-outer-color: transparent !default; + + +// Badges + +$badge-font-size: 66% !default; +$badge-font-weight: $font-weight-bold !default; +$badge-padding-y: .35rem !default; +$badge-padding-x: .375rem !default; +$badge-border-radius: $border-radius !default; +$badge-text-transfom: uppercase; + +$badge-pill-padding-x: .875em !default; +$badge-pill-border-radius: 10rem !default; + +$badge-circle-size: 2rem !default; + +// Pagination + +// $pagination-padding-y: .5rem !default; +// $pagination-padding-x: .75rem !default; +// $pagination-padding-y-sm: .25rem !default; +// $pagination-padding-x-sm: .5rem !default; +// $pagination-padding-y-lg: .75rem !default; +// $pagination-padding-x-lg: 1.5rem !default; +// $pagination-line-height: 1.25 !default; + +$pagination-color: $gray-600 !default; +$pagination-bg: $white !default; +$pagination-border-width: $border-width !default; +$pagination-border-color: $gray-300 !default; + +//$pagination-focus-box-shadow: $btn-hover-box-shadow !default; + +$pagination-hover-color: $gray-600 !default; +$pagination-hover-bg: $gray-300 !default; +$pagination-hover-border-color: $gray-300 !default; + +$pagination-active-color: $component-active-color !default; +$pagination-active-bg: $component-active-bg !default; +$pagination-active-border-color: $pagination-active-bg !default; +$pagination-active-box-shadow: $btn-hover-box-shadow !default; + +$pagination-disabled-color: $gray-600 !default; +$pagination-disabled-bg: $white !default; +$pagination-disabled-border-color: $gray-300 !default; + + +// Cards + +$card-spacer-y: 1.25rem !default; +$card-spacer-x: 1.5rem !default; +$card-border-width: $border-width !default; +$card-border-radius: $border-radius !default; +$card-border-color: rgba($black, .05) !default; +$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default; +$card-cap-bg: $white !default; +$card-bg: $white !default; + +$card-img-overlay-padding: 1.25rem !default; + +//$card-group-margin: ($grid-gutter-width / 2); +//$card-deck-margin: $card-group-margin !default; + +$card-columns-count: 3 !default; +$card-columns-gap: 1.25rem !default; +$card-columns-margin: $card-spacer-y !default; + +// Tooltips + +$tooltip-font-size: $font-size-sm !default; + +// Modals + +$modal-inner-padding: 1.5rem !default; + +$modal-lg: 800px !default; +$modal-md: 500px !default; +$modal-sm: 380px !default; + +$modal-title-line-height: 1.1; + +$modal-content-bg: $white !default; +$modal-content-border-color: rgba($black, .2) !default; +$modal-content-border-width: 0 !default; +$modal-content-border-radius: $border-radius-lg !default; +$modal-content-box-shadow-xs: 0 15px 35px rgba(50,50,93,.2), 0 5px 15px rgba(0,0,0,.17); +$modal-content-box-shadow-sm-up: 0 15px 35px rgba(50,50,93,.2), 0 5px 15px rgba(0,0,0,.17); + +$modal-backdrop-bg: $black !default; +$modal-backdrop-opacity: .16 !default; +$modal-header-border-color: $gray-200 !default; +$modal-footer-border-color: $modal-header-border-color !default; +$modal-header-border-width: $modal-content-border-width !default; +$modal-footer-border-width: $modal-header-border-width !default; +$modal-header-padding: 1.25rem !default; + +// Datepicker + +$datepicker-border-radius: $card-border-radius !default; +$datepicker-dropdown-padding: 20px 22px !default; + +$datepicker-cell-transition: $transition-base !default; +$datepicker-cell-hover-background: lighten($gray-400, 55%); +$datepicker-cell-border-radius: 50% !default; +$datepicker-cell-width: 36px !default; +$datepicker-cell-height: 36px !default; + +$datepicker-disabled-cell-color: $gray-300 !default; +$datepicker-disabled-old-new-color: $gray-500 !default; + +$datepicker-header-cell-border-radius: $border-radius !default; + +$datepicker-active-color: $white !default; +$datepicker-active-background: theme-color("primary") !default; +$datepicker-active-box-shadow: none !default; + +$datepicker-range-background: theme-color("primary") !default; +$datepicker-range-cell-focused-background: darken($datepicker-range-background, 5%); +$datepicker-range-color: $white !default; +$datepicker-range-highlighted-bg: $gray-200 !default; + +$datepicker-dropdown-border: lighten($gray-400, 40%); +$datepicker-dropdown-bg: $white !default; +$datepicker-highlighted-bg: $datepicker-active-background !default; + + +// Footer + + +$footer-padding-y: 2.5rem; +$footer-padding-x: 0; + + +$footer-link-font-size: .85rem !default; +$footer-bg: theme-color("secondary") !default; +$footer-color: $gray-600 !default; +$footer-link-color: $gray-600 !default; +$footer-link-hover-color: $gray-700 !default; +$footer-heading-color: $gray-600 !default; +$footer-heading-font-size: $font-size-sm !default; + +// Import Bootstrap variable defaults + +@import "~bootstrap/scss/variables"; diff --git a/frontend/src/assets/scss/custom/_vendors.scss b/frontend/src/assets/scss/custom/_vendors.scss new file mode 100644 index 000000000..3060e4a02 --- /dev/null +++ b/frontend/src/assets/scss/custom/_vendors.scss @@ -0,0 +1,9 @@ +// +// Vendors +// include plugin styles +// + + +@import "../core/vendors/flatpickr"; +@import "../core/vendors/nouislider"; +@import "../core/vendors/scrollbar"; diff --git a/frontend/src/assets/vendor/nucleo/css/nucleo-svg.css b/frontend/src/assets/vendor/nucleo/css/nucleo-svg.css new file mode 100644 index 000000000..c68c10e35 --- /dev/null +++ b/frontend/src/assets/vendor/nucleo/css/nucleo-svg.css @@ -0,0 +1,135 @@ +/* Generated using nucleoapp.com */ +/* -------------------------------- + +Icon colors + +-------------------------------- */ + +.icon { + display: inline-block; + /* icon primary color */ + color: #111111; + height: 1em; + width: 1em; +} + +.icon use { + /* icon secondary color - fill */ + fill: #7ea6f6; +} + +.icon.icon-outline use { + /* icon secondary color - stroke */ + stroke: #7ea6f6; +} + +/* -------------------------------- + +Change icon size + +-------------------------------- */ + +.icon-xs { + height: 0.5em; + width: 0.5em; +} + +.icon-sm { + height: 0.8em; + width: 0.8em; +} + +.icon-lg { + height: 1.6em; + width: 1.6em; +} + +.icon-xl { + height: 2em; + width: 2em; +} + +/* -------------------------------- + +Align icon and text + +-------------------------------- */ + +.icon-text-aligner { + /* add this class to parent element that contains icon + text */ + display: flex; + align-items: center; +} + +.icon-text-aligner .icon { + color: inherit; + margin-right: 0.4em; +} + +.icon-text-aligner .icon use { + color: inherit; + fill: currentColor; +} + +.icon-text-aligner .icon.icon-outline use { + stroke: currentColor; +} + +/* -------------------------------- + +Icon reset values - used to enable color customizations + +-------------------------------- */ + +.icon { + fill: currentColor; + stroke: none; +} + +.icon.icon-outline { + fill: none; + stroke: currentColor; +} + +.icon use { + stroke: none; +} + +.icon.icon-outline use { + fill: none; +} + +/* -------------------------------- + +Stroke effects - Nucleo outline icons + +- 16px icons -> up to 1px stroke (16px outline icons do not support stroke changes) +- 24px, 32px icons -> up to 2px stroke +- 48px, 64px icons -> up to 4px stroke + +-------------------------------- */ + +.icon-outline.icon-stroke-1 { + stroke-width: 1px; +} + +.icon-outline.icon-stroke-2 { + stroke-width: 2px; +} + +.icon-outline.icon-stroke-3 { + stroke-width: 3px; +} + +.icon-outline.icon-stroke-4 { + stroke-width: 4px; +} + +.icon-outline.icon-stroke-1 use, +.icon-outline.icon-stroke-3 use { + -webkit-transform: translateX(0.5px) translateY(0.5px); + -moz-transform: translateX(0.5px) translateY(0.5px); + -ms-transform: translateX(0.5px) translateY(0.5px); + -o-transform: translateX(0.5px) translateY(0.5px); + transform: translateX(0.5px) translateY(0.5px); +} \ No newline at end of file diff --git a/frontend/src/assets/vendor/nucleo/css/nucleo.css b/frontend/src/assets/vendor/nucleo/css/nucleo.css new file mode 100644 index 000000000..481bf62c8 --- /dev/null +++ b/frontend/src/assets/vendor/nucleo/css/nucleo.css @@ -0,0 +1,572 @@ +/*-------------------------------- + +hermes-dashboard-icons Web Font - built using nucleoapp.com +License - nucleoapp.com/license/ + +-------------------------------- */ +@font-face { + font-family: 'NucleoIcons'; + src: url('../fonts/nucleo-icons.eot'); + src: url('../fonts/nucleo-icons.eot') format('embedded-opentype'), url('../fonts/nucleo-icons.woff2') format('woff2'), url('../fonts/nucleo-icons.woff') format('woff'), url('../fonts/nucleo-icons.ttf') format('truetype'), url('../fonts/nucleo-icons.svg') format('svg'); + font-weight: normal; + font-style: normal; +} +/*------------------------ + base class definition +-------------------------*/ +.ni { + display: inline-block; + font: normal normal normal 14px/1 NucleoIcons; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/*------------------------ + change icon size +-------------------------*/ +.ni-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.ni-2x { + font-size: 2em; +} +.ni-3x { + font-size: 3em; +} +.ni-4x { + font-size: 4em; +} +.ni-5x { + font-size: 5em; +} + +/*---------------------------------- + add a square/circle background +-----------------------------------*/ +.ni.square, +.ni.circle { + padding: 0.33333333em; + vertical-align: -16%; + background-color: #eee; +} +.ni.circle { + border-radius: 50%; +} +/*------------------------ + list icons +-------------------------*/ +.ni-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.ni-ul > li { + position: relative; +} +.ni-ul > li > .ni { + position: absolute; + left: -1.57142857em; + top: 0.14285714em; + text-align: center; +} +.ni-ul > li > .ni.lg { + top: 0; + left: -1.35714286em; +} +.ni-ul > li > .ni.circle, +.ni-ul > li > .ni.square { + top: -0.19047619em; + left: -1.9047619em; +} +/*------------------------ + spinning icons +-------------------------*/ +.ni.spin { + -webkit-animation: nc-spin 2s infinite linear; + -moz-animation: nc-spin 2s infinite linear; + animation: nc-spin 2s infinite linear; +} +@-webkit-keyframes nc-spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + } +} +@-moz-keyframes nc-spin { + 0% { + -moz-transform: rotate(0deg); + } + 100% { + -moz-transform: rotate(360deg); + } +} +@keyframes nc-spin { + 0% { + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } +} +/*------------------------ + rotated/flipped icons +-------------------------*/ +.ni.rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} +.ni.rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} +.ni.rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); +} +.ni.flip-y { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0); + -webkit-transform: scale(-1, 1); + -moz-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.ni.flip-x { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: scale(1, -1); + -moz-transform: scale(1, -1); + -ms-transform: scale(1, -1); + -o-transform: scale(1, -1); + transform: scale(1, -1); +} +/*------------------------ + font icons +-------------------------*/ + +.ni-active-40::before { + content: "\ea02"; +} + +.ni-air-baloon::before { + content: "\ea03"; +} + +.ni-album-2::before { + content: "\ea04"; +} + +.ni-align-center::before { + content: "\ea05"; +} + +.ni-align-left-2::before { + content: "\ea06"; +} + +.ni-ambulance::before { + content: "\ea07"; +} + +.ni-app::before { + content: "\ea08"; +} + +.ni-archive-2::before { + content: "\ea09"; +} + +.ni-atom::before { + content: "\ea0a"; +} + +.ni-badge::before { + content: "\ea0b"; +} + +.ni-bag-17::before { + content: "\ea0c"; +} + +.ni-basket::before { + content: "\ea0d"; +} + +.ni-bell-55::before { + content: "\ea0e"; +} + +.ni-bold-down::before { + content: "\ea0f"; +} + +.ni-bold-left::before { + content: "\ea10"; +} + +.ni-bold-right::before { + content: "\ea11"; +} + +.ni-bold-up::before { + content: "\ea12"; +} + +.ni-bold::before { + content: "\ea13"; +} + +.ni-book-bookmark::before { + content: "\ea14"; +} + +.ni-books::before { + content: "\ea15"; +} + +.ni-box-2::before { + content: "\ea16"; +} + +.ni-briefcase-24::before { + content: "\ea17"; +} + +.ni-building::before { + content: "\ea18"; +} + +.ni-bulb-61::before { + content: "\ea19"; +} + +.ni-bullet-list-67::before { + content: "\ea1a"; +} + +.ni-bus-front-12::before { + content: "\ea1b"; +} + +.ni-button-pause::before { + content: "\ea1c"; +} + +.ni-button-play::before { + content: "\ea1d"; +} + +.ni-button-power::before { + content: "\ea1e"; +} + +.ni-calendar-grid-58::before { + content: "\ea1f"; +} + +.ni-camera-compact::before { + content: "\ea20"; +} + +.ni-caps-small::before { + content: "\ea21"; +} + +.ni-cart::before { + content: "\ea22"; +} + +.ni-chart-bar-32::before { + content: "\ea23"; +} + +.ni-chart-pie-35::before { + content: "\ea24"; +} + +.ni-chat-round::before { + content: "\ea25"; +} + +.ni-check-bold::before { + content: "\ea26"; +} + +.ni-circle-08::before { + content: "\ea27"; +} + +.ni-cloud-download-95::before { + content: "\ea28"; +} + +.ni-cloud-upload-96::before { + content: "\ea29"; +} + +.ni-compass-04::before { + content: "\ea2a"; +} + +.ni-controller::before { + content: "\ea2b"; +} + +.ni-credit-card::before { + content: "\ea2c"; +} + +.ni-curved-next::before { + content: "\ea2d"; +} + +.ni-delivery-fast::before { + content: "\ea2e"; +} + +.ni-diamond::before { + content: "\ea2f"; +} + +.ni-email-83::before { + content: "\ea30"; +} + +.ni-fat-add::before { + content: "\ea31"; +} + +.ni-fat-delete::before { + content: "\ea32"; +} + +.ni-fat-remove::before { + content: "\ea33"; +} + +.ni-favourite-28::before { + content: "\ea34"; +} + +.ni-folder-17::before { + content: "\ea35"; +} + +.ni-glasses-2::before { + content: "\ea36"; +} + +.ni-hat-3::before { + content: "\ea37"; +} + +.ni-headphones::before { + content: "\ea38"; +} + +.ni-html5::before { + content: "\ea39"; +} + +.ni-istanbul::before { + content: "\ea3a"; +} + +.ni-key-25::before { + content: "\ea3b"; +} + +.ni-laptop::before { + content: "\ea3c"; +} + +.ni-like-2::before { + content: "\ea3d"; +} + +.ni-lock-circle-open::before { + content: "\ea3e"; +} + +.ni-map-big::before { + content: "\ea3f"; +} + +.ni-mobile-button::before { + content: "\ea40"; +} + +.ni-money-coins::before { + content: "\ea41"; +} + +.ni-note-03::before { + content: "\ea42"; +} + +.ni-notification-70::before { + content: "\ea43"; +} + +.ni-palette::before { + content: "\ea44"; +} + +.ni-paper-diploma::before { + content: "\ea45"; +} + +.ni-pin-3::before { + content: "\ea46"; +} + +.ni-planet::before { + content: "\ea47"; +} + +.ni-ruler-pencil::before { + content: "\ea48"; +} + +.ni-satisfied::before { + content: "\ea49"; +} + +.ni-scissors::before { + content: "\ea4a"; +} + +.ni-send::before { + content: "\ea4b"; +} + +.ni-settings-gear-65::before { + content: "\ea4c"; +} + +.ni-settings::before { + content: "\ea4d"; +} + +.ni-single-02::before { + content: "\ea4e"; +} + +.ni-single-copy-04::before { + content: "\ea4f"; +} + +.ni-sound-wave::before { + content: "\ea50"; +} + +.ni-spaceship::before { + content: "\ea51"; +} + +.ni-square-pin::before { + content: "\ea52"; +} + +.ni-support-16::before { + content: "\ea53"; +} + +.ni-tablet-button::before { + content: "\ea54"; +} + +.ni-tag::before { + content: "\ea55"; +} + +.ni-tie-bow::before { + content: "\ea56"; +} + +.ni-time-alarm::before { + content: "\ea57"; +} + +.ni-trophy::before { + content: "\ea58"; +} + +.ni-tv-2::before { + content: "\ea59"; +} + +.ni-umbrella-13::before { + content: "\ea5a"; +} + +.ni-user-run::before { + content: "\ea5b"; +} + +.ni-vector::before { + content: "\ea5c"; +} + +.ni-watch-time::before { + content: "\ea5d"; +} + +.ni-world::before { + content: "\ea5e"; +} + +.ni-zoom-split-in::before { + content: "\ea5f"; +} + +.ni-collection::before { + content: "\ea60"; +} + +.ni-image::before { + content: "\ea61"; +} + +.ni-shop::before { + content: "\ea62"; +} + +.ni-ungroup::before { + content: "\ea63"; +} + +.ni-world-2::before { + content: "\ea64"; +} + +.ni-ui-04::before { + content: "\ea65"; +} + + +/* all icon font classes list here */ diff --git a/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.eot b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.eot new file mode 100644 index 000000000..ab96810ad Binary files /dev/null and b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.eot differ diff --git a/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.svg b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.svg new file mode 100644 index 000000000..6654c1a2d --- /dev/null +++ b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.svg @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.ttf b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.ttf new file mode 100644 index 000000000..1a5598505 Binary files /dev/null and b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.ttf differ diff --git a/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.woff b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.woff new file mode 100644 index 000000000..cb1924708 Binary files /dev/null and b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.woff differ diff --git a/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.woff2 b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.woff2 new file mode 100644 index 000000000..e294e0801 Binary files /dev/null and b/frontend/src/assets/vendor/nucleo/fonts/nucleo-icons.woff2 differ diff --git a/frontend/src/components/Badge.vue b/frontend/src/components/Badge.vue new file mode 100644 index 000000000..4dcaca41d --- /dev/null +++ b/frontend/src/components/Badge.vue @@ -0,0 +1,50 @@ + + + diff --git a/frontend/src/components/BaseAlert.vue b/frontend/src/components/BaseAlert.vue new file mode 100644 index 000000000..a45139aa1 --- /dev/null +++ b/frontend/src/components/BaseAlert.vue @@ -0,0 +1,71 @@ + + diff --git a/frontend/src/components/BaseButton.vue b/frontend/src/components/BaseButton.vue new file mode 100644 index 000000000..d2f6ed3df --- /dev/null +++ b/frontend/src/components/BaseButton.vue @@ -0,0 +1,75 @@ + + + diff --git a/frontend/src/components/BaseDropdown.vue b/frontend/src/components/BaseDropdown.vue new file mode 100644 index 000000000..9c50f40da --- /dev/null +++ b/frontend/src/components/BaseDropdown.vue @@ -0,0 +1,100 @@ + + + diff --git a/frontend/src/components/BaseHeader.vue b/frontend/src/components/BaseHeader.vue new file mode 100644 index 000000000..a51c52874 --- /dev/null +++ b/frontend/src/components/BaseHeader.vue @@ -0,0 +1,23 @@ + + + diff --git a/frontend/src/components/BasePagination.vue b/frontend/src/components/BasePagination.vue new file mode 100755 index 000000000..84d4c7207 --- /dev/null +++ b/frontend/src/components/BasePagination.vue @@ -0,0 +1,56 @@ + + diff --git a/frontend/src/components/BaseProgress.vue b/frontend/src/components/BaseProgress.vue new file mode 100755 index 000000000..678d157e2 --- /dev/null +++ b/frontend/src/components/BaseProgress.vue @@ -0,0 +1,84 @@ + + + diff --git a/frontend/src/components/BaseSlider.vue b/frontend/src/components/BaseSlider.vue new file mode 100644 index 000000000..00d9e67b3 --- /dev/null +++ b/frontend/src/components/BaseSlider.vue @@ -0,0 +1,96 @@ + + + diff --git a/frontend/src/components/BaseTable.vue b/frontend/src/components/BaseTable.vue new file mode 100644 index 000000000..40cb6eae4 --- /dev/null +++ b/frontend/src/components/BaseTable.vue @@ -0,0 +1,70 @@ + + + diff --git a/frontend/src/components/Breadcrumb/Breadcrumb.vue b/frontend/src/components/Breadcrumb/Breadcrumb.vue new file mode 100644 index 000000000..4416c542b --- /dev/null +++ b/frontend/src/components/Breadcrumb/Breadcrumb.vue @@ -0,0 +1,26 @@ + + + diff --git a/frontend/src/components/Breadcrumb/BreadcrumbItem.vue b/frontend/src/components/Breadcrumb/BreadcrumbItem.vue new file mode 100644 index 000000000..b076fbe89 --- /dev/null +++ b/frontend/src/components/Breadcrumb/BreadcrumbItem.vue @@ -0,0 +1,18 @@ + + + diff --git a/frontend/src/components/Breadcrumb/RouteBreadcrumb.vue b/frontend/src/components/Breadcrumb/RouteBreadcrumb.vue new file mode 100644 index 000000000..ff9b3cf12 --- /dev/null +++ b/frontend/src/components/Breadcrumb/RouteBreadcrumb.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/frontend/src/components/ButtonCheckbox.vue b/frontend/src/components/ButtonCheckbox.vue new file mode 100644 index 000000000..1028aa899 --- /dev/null +++ b/frontend/src/components/ButtonCheckbox.vue @@ -0,0 +1,39 @@ + + + diff --git a/frontend/src/components/ButtonRadioGroup.vue b/frontend/src/components/ButtonRadioGroup.vue new file mode 100644 index 000000000..5b8fc6742 --- /dev/null +++ b/frontend/src/components/ButtonRadioGroup.vue @@ -0,0 +1,47 @@ + + + diff --git a/frontend/src/components/Cards/Card.vue b/frontend/src/components/Cards/Card.vue new file mode 100644 index 000000000..d82e6cc35 --- /dev/null +++ b/frontend/src/components/Cards/Card.vue @@ -0,0 +1,73 @@ + + + diff --git a/frontend/src/components/Cards/StatsCard.vue b/frontend/src/components/Cards/StatsCard.vue new file mode 100644 index 000000000..919384882 --- /dev/null +++ b/frontend/src/components/Cards/StatsCard.vue @@ -0,0 +1,57 @@ + + + diff --git a/frontend/src/components/Charts/BarChart.js b/frontend/src/components/Charts/BarChart.js new file mode 100644 index 000000000..c45092cbc --- /dev/null +++ b/frontend/src/components/Charts/BarChart.js @@ -0,0 +1,30 @@ +import { Bar, mixins } from 'vue-chartjs'; +import globalOptionsMixin from "@/components/Charts/globalOptionsMixin"; + +export default { + name: 'bar-chart', + extends: Bar, + mixins: [mixins.reactiveProp, globalOptionsMixin], + props: { + extraOptions: { + type: Object, + default: () => ({}) + } + }, + data() { + return { + ctx: null + }; + }, + mounted() { + this.$watch( + 'chartData', + (newVal, oldVal) => { + if (!oldVal) { + this.renderChart(this.chartData, this.extraOptions); + } + }, + { immediate: true } + ); + } +}; diff --git a/frontend/src/components/Charts/LineChart.js b/frontend/src/components/Charts/LineChart.js new file mode 100644 index 000000000..fffb85571 --- /dev/null +++ b/frontend/src/components/Charts/LineChart.js @@ -0,0 +1,29 @@ +import { Line, mixins } from 'vue-chartjs'; +import globalOptionsMixin from "@/components/Charts/globalOptionsMixin"; +export default { + name: 'line-chart', + extends: Line, + mixins: [mixins.reactiveProp, globalOptionsMixin], + props: { + extraOptions: { + type: Object, + default: () => ({}) + } + }, + data() { + return { + ctx: null + }; + }, + mounted() { + this.$watch( + 'chartData', + (newVal, oldVal) => { + if (!oldVal) { + this.renderChart(this.chartData, this.extraOptions); + } + }, + { immediate: true } + ); + } +}; diff --git a/frontend/src/components/Charts/config.js b/frontend/src/components/Charts/config.js new file mode 100644 index 000000000..c3add6981 --- /dev/null +++ b/frontend/src/components/Charts/config.js @@ -0,0 +1,231 @@ +import { parseOptions } from "@/components/Charts/optionHelpers"; +import Chart from 'chart.js' + +export const Charts = { + mode: 'light',//(themeMode) ? themeMode : 'light'; + fonts: { + base: 'Open Sans' + }, + colors: { + gray: { + 100: '#f6f9fc', + 200: '#e9ecef', + 300: '#dee2e6', + 400: '#ced4da', + 500: '#adb5bd', + 600: '#8898aa', + 700: '#525f7f', + 800: '#32325d', + 900: '#212529' + }, + theme: { + 'default': '#172b4d', + 'primary': '#5e72e4', + 'secondary': '#f4f5f7', + 'info': '#11cdef', + 'success': '#2dce89', + 'danger': '#f5365c', + 'warning': '#fb6340' + }, + black: '#12263F', + white: '#FFFFFF', + transparent: 'transparent', + } +}; + +function chartOptions() { + let { colors, mode, fonts } = Charts; + // Options + let options = { + defaults: { + global: { + responsive: true, + maintainAspectRatio: false, + defaultColor: (mode === 'dark') ? colors.gray[700] : colors.gray[600], + defaultFontColor: (mode === 'dark') ? colors.gray[700] : colors.gray[600], + defaultFontFamily: fonts.base, + defaultFontSize: 13, + layout: { + padding: 0 + }, + legend: { + display: false, + position: 'bottom', + labels: { + usePointStyle: true, + padding: 16 + } + }, + elements: { + point: { + radius: 0, + backgroundColor: colors.theme['primary'] + }, + line: { + tension: .4, + borderWidth: 4, + borderColor: colors.theme['primary'], + backgroundColor: colors.transparent, + borderCapStyle: 'rounded' + }, + rectangle: { + backgroundColor: colors.theme['warning'] + }, + arc: { + backgroundColor: colors.theme['primary'], + borderColor: (mode == 'dark') ? colors.gray[800] : colors.white, + borderWidth: 4 + } + }, + tooltips: { + enabled: true, + mode: 'index', + intersect: false, + } + }, + pie: { + tooltips: { + mode: 'point' + } + }, + doughnut: { + tooltips: { + mode: 'point' + }, + cutoutPercentage: 83, + legendCallback: function (chart) { + let data = chart.data; + let content = ''; + + data.labels.forEach(function (label, index) { + let bgColor = data.datasets[0].backgroundColor[index]; + + content += ''; + content += ''; + content += label; + content += ''; + }); + + return content; + } + } + } + }; + + // yAxes + Chart.scaleService.updateScaleDefaults('linear', { + gridLines: { + borderDash: [2], + borderDashOffset: [2], + color: (mode === 'dark') ? colors.gray[900] : colors.gray[200], + drawBorder: false, + drawTicks: true, + zeroLineWidth: 1, + zeroLineColor: (mode === 'dark') ? colors.gray[900] : colors.gray[200], + zeroLineBorderDash: [2], + zeroLineBorderDashOffset: [2] + }, + ticks: { + beginAtZero: true, + padding: 10, + callback: function (value) { + if (!(value % 10)) { + return value + } + } + } + }); + + // xAxes + Chart.scaleService.updateScaleDefaults('category', { + gridLines: { + drawBorder: false, + drawOnChartArea: false, + drawTicks: false, + lineWidth: 1, + zeroLineWidth: 1, + }, + ticks: { + padding: 20 + }, + maxBarThickness: 10 + }); + + return options; +}; + +let initialized = false + +export function initGlobalOptions() { + if (initialized) { + return + } + parseOptions(Chart, chartOptions()); + initialized = true +} + +export const basicOptions = { + maintainAspectRatio: false, + legend: { + display: false + }, + responsive: true +}; +export let blueChartOptions = { + scales: { + yAxes: [{ + gridLines: { + color: Charts.colors.gray[700], + zeroLineColor: Charts.colors.gray[700] + } + }] + } +}; + +export let lineChartOptionsBlue = { + ...basicOptions, + tooltips: { + backgroundColor: '#f5f5f5', + titleFontColor: '#333', + bodyFontColor: '#666', + bodySpacing: 4, + xPadding: 12, + mode: 'nearest', + intersect: 0, + position: 'nearest' + }, + responsive: true, + scales: { + yAxes: [ + { + barPercentage: 1.6, + gridLines: { + drawBorder: false, + color: 'rgba(29,140,248,0.0)', + zeroLineColor: 'transparent' + }, + ticks: { + suggestedMin: 60, + suggestedMax: 125, + padding: 20, + fontColor: '#9e9e9e' + } + } + ], + + xAxes: [ + { + barPercentage: 1.6, + gridLines: { + drawBorder: false, + color: 'rgba(29,140,248,0.1)', + zeroLineColor: 'transparent' + }, + ticks: { + padding: 20, + fontColor: '#9e9e9e' + } + } + ] + } +}; diff --git a/frontend/src/components/Charts/globalOptionsMixin.js b/frontend/src/components/Charts/globalOptionsMixin.js new file mode 100644 index 000000000..eebaaca55 --- /dev/null +++ b/frontend/src/components/Charts/globalOptionsMixin.js @@ -0,0 +1,7 @@ +import { initGlobalOptions } from "@/components/Charts/config"; +import './roundedCornersExtension' +export default { + mounted() { + initGlobalOptions(); + } +} diff --git a/frontend/src/components/Charts/optionHelpers.js b/frontend/src/components/Charts/optionHelpers.js new file mode 100644 index 000000000..227b229e1 --- /dev/null +++ b/frontend/src/components/Charts/optionHelpers.js @@ -0,0 +1,10 @@ +// Parse global options +export function parseOptions(parent, options) { + for (let item in options) { + if (typeof options[item] !== 'object') { + parent[item] = options[item]; + } else { + parseOptions(parent[item], options[item]); + } + } +} diff --git a/frontend/src/components/Charts/roundedCornersExtension.js b/frontend/src/components/Charts/roundedCornersExtension.js new file mode 100644 index 000000000..b1a91643f --- /dev/null +++ b/frontend/src/components/Charts/roundedCornersExtension.js @@ -0,0 +1,130 @@ +// +// Chart extension for making the bars rounded +// Code from: https://codepen.io/jedtrow/full/ygRYgo +// +import Chart from 'chart.js' +Chart.elements.Rectangle.prototype.draw = function() { + + let ctx = this._chart.ctx; + let vm = this._view; + let left, right, top, bottom, signX, signY, borderSkipped, radius; + let borderWidth = vm.borderWidth; + // Set Radius Here + // If radius is large enough to cause drawing errors a max radius is imposed + let cornerRadius = 6; + + if (!vm.horizontal) { + // bar + left = vm.x - vm.width / 2; + right = vm.x + vm.width / 2; + top = vm.y; + bottom = vm.base; + signX = 1; + signY = bottom > top ? 1 : -1; + borderSkipped = vm.borderSkipped || 'bottom'; + } else { + // horizontal bar + left = vm.base; + right = vm.x; + top = vm.y - vm.height / 2; + bottom = vm.y + vm.height / 2; + signX = right > left ? 1 : -1; + signY = 1; + borderSkipped = vm.borderSkipped || 'left'; + } + + // Canvas doesn't allow us to stroke inside the width so we can + // adjust the sizes to fit if we're setting a stroke on the line + if (borderWidth) { + // borderWidth shold be less than bar width and bar height. + let barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom)); + borderWidth = borderWidth > barSize ? barSize : borderWidth; + let halfStroke = borderWidth / 2; + // Adjust borderWidth when bar top position is near vm.base(zero). + let borderLeft = left + (borderSkipped !== 'left' ? halfStroke * signX : 0); + let borderRight = right + (borderSkipped !== 'right' ? -halfStroke * signX : 0); + let borderTop = top + (borderSkipped !== 'top' ? halfStroke * signY : 0); + let borderBottom = bottom + (borderSkipped !== 'bottom' ? -halfStroke * signY : 0); + // not become a vertical line? + if (borderLeft !== borderRight) { + top = borderTop; + bottom = borderBottom; + } + // not become a horizontal line? + if (borderTop !== borderBottom) { + left = borderLeft; + right = borderRight; + } + } + + ctx.beginPath(); + ctx.fillStyle = vm.backgroundColor; + ctx.strokeStyle = vm.borderColor; + ctx.lineWidth = borderWidth; + + // Corner points, from bottom-left to bottom-right clockwise + // | 1 2 | + // | 0 3 | + let corners = [ + [left, bottom], + [left, top], + [right, top], + [right, bottom] + ]; + + // Find first (starting) corner with fallback to 'bottom' + let borders = ['bottom', 'left', 'top', 'right']; + let startCorner = borders.indexOf(borderSkipped, 0); + if (startCorner === -1) { + startCorner = 0; + } + + function cornerAt(index) { + return corners[(startCorner + index) % 4]; + } + + // Draw rectangle from 'startCorner' + let corner = cornerAt(0); + ctx.moveTo(corner[0], corner[1]); + + for (let i = 1; i < 4; i++) { + corner = cornerAt(i); + let nextCornerId = i + 1; + if (nextCornerId == 4) { + nextCornerId = 0 + } + + let nextCorner = cornerAt(nextCornerId); + + let width = corners[2][0] - corners[1][0]; + let height = corners[0][1] - corners[1][1]; + let x = corners[1][0]; + let y = corners[1][1]; + + let radius = cornerRadius; + + // Fix radius being too large + if (radius > height / 2) { + radius = height / 2; + } + if (radius > width / 2) { + radius = width / 2; + } + + ctx.moveTo(x + radius, y); + ctx.lineTo(x + width - radius, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + radius); + ctx.lineTo(x + width, y + height - radius); + ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); + ctx.lineTo(x + radius, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - radius); + ctx.lineTo(x, y + radius); + ctx.quadraticCurveTo(x, y, x + radius, y); + + } + + ctx.fill(); + if (borderWidth) { + ctx.stroke(); + } +}; diff --git a/frontend/src/components/CloseButton.vue b/frontend/src/components/CloseButton.vue new file mode 100755 index 000000000..756c8b6a5 --- /dev/null +++ b/frontend/src/components/CloseButton.vue @@ -0,0 +1,35 @@ + + + diff --git a/frontend/src/components/Collapse/Collapse.vue b/frontend/src/components/Collapse/Collapse.vue new file mode 100644 index 000000000..a6cf81336 --- /dev/null +++ b/frontend/src/components/Collapse/Collapse.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/frontend/src/components/Collapse/CollapseItem.vue b/frontend/src/components/Collapse/CollapseItem.vue new file mode 100644 index 000000000..acb49c154 --- /dev/null +++ b/frontend/src/components/Collapse/CollapseItem.vue @@ -0,0 +1,92 @@ + + + diff --git a/frontend/src/components/Inputs/BaseCheckbox.vue b/frontend/src/components/Inputs/BaseCheckbox.vue new file mode 100755 index 000000000..dd39f21b4 --- /dev/null +++ b/frontend/src/components/Inputs/BaseCheckbox.vue @@ -0,0 +1,77 @@ + + diff --git a/frontend/src/components/Inputs/BaseInput.vue b/frontend/src/components/Inputs/BaseInput.vue new file mode 100644 index 000000000..31c075c6f --- /dev/null +++ b/frontend/src/components/Inputs/BaseInput.vue @@ -0,0 +1,176 @@ + + + diff --git a/frontend/src/components/Inputs/BaseRadio.vue b/frontend/src/components/Inputs/BaseRadio.vue new file mode 100755 index 000000000..d0d7fd50b --- /dev/null +++ b/frontend/src/components/Inputs/BaseRadio.vue @@ -0,0 +1,68 @@ + + diff --git a/frontend/src/components/LoadingPanel.vue b/frontend/src/components/LoadingPanel.vue new file mode 100644 index 000000000..41fe2cf72 --- /dev/null +++ b/frontend/src/components/LoadingPanel.vue @@ -0,0 +1,25 @@ + + + diff --git a/frontend/src/components/Modal-OLD.vue b/frontend/src/components/Modal-OLD.vue new file mode 100644 index 000000000..71f6af0f2 --- /dev/null +++ b/frontend/src/components/Modal-OLD.vue @@ -0,0 +1,125 @@ + + + diff --git a/frontend/src/components/Modal.vue b/frontend/src/components/Modal.vue new file mode 100644 index 000000000..44996d624 --- /dev/null +++ b/frontend/src/components/Modal.vue @@ -0,0 +1,85 @@ + + + + diff --git a/frontend/src/components/Navbar/BaseNav.vue b/frontend/src/components/Navbar/BaseNav.vue new file mode 100644 index 000000000..81400f61b --- /dev/null +++ b/frontend/src/components/Navbar/BaseNav.vue @@ -0,0 +1,123 @@ + + + diff --git a/frontend/src/components/Navbar/NavbarToggleButton.vue b/frontend/src/components/Navbar/NavbarToggleButton.vue new file mode 100644 index 000000000..7c63c10df --- /dev/null +++ b/frontend/src/components/Navbar/NavbarToggleButton.vue @@ -0,0 +1,21 @@ + + + diff --git a/frontend/src/components/NavbarToggleButton.vue b/frontend/src/components/NavbarToggleButton.vue new file mode 100755 index 000000000..78b0396ba --- /dev/null +++ b/frontend/src/components/NavbarToggleButton.vue @@ -0,0 +1,32 @@ + + + diff --git a/frontend/src/components/NotificationPlugin/Notification.vue b/frontend/src/components/NotificationPlugin/Notification.vue new file mode 100644 index 000000000..6338fa9ea --- /dev/null +++ b/frontend/src/components/NotificationPlugin/Notification.vue @@ -0,0 +1,209 @@ + + + diff --git a/frontend/src/components/NotificationPlugin/Notifications.vue b/frontend/src/components/NotificationPlugin/Notifications.vue new file mode 100644 index 000000000..2689cc923 --- /dev/null +++ b/frontend/src/components/NotificationPlugin/Notifications.vue @@ -0,0 +1,55 @@ + + diff --git a/frontend/src/components/NotificationPlugin/index.js b/frontend/src/components/NotificationPlugin/index.js new file mode 100644 index 000000000..e871fb6ac --- /dev/null +++ b/frontend/src/components/NotificationPlugin/index.js @@ -0,0 +1,66 @@ +import Notifications from './Notifications.vue'; + +const NotificationStore = { + state: [], // here the notifications will be added + settings: { + overlap: false, + verticalAlign: 'top', + horizontalAlign: 'right', + type: 'info', + timeout: 5000, + closeOnClick: true, + showClose: true + }, + setOptions(options) { + this.settings = Object.assign(this.settings, options); + }, + removeNotification(timestamp) { + const indexToDelete = this.state.findIndex(n => n.timestamp === timestamp); + if (indexToDelete !== -1) { + this.state.splice(indexToDelete, 1); + } + }, + addNotification(notification) { + if (typeof notification === 'string' || notification instanceof String) { + notification = { message: notification }; + } + notification.timestamp = new Date(); + notification.timestamp.setMilliseconds( + notification.timestamp.getMilliseconds() + this.state.length + ); + notification = Object.assign({}, this.settings, notification); + this.state.push(notification); + }, + notify(notification) { + if (Array.isArray(notification)) { + notification.forEach(notificationInstance => { + this.addNotification(notificationInstance); + }); + } else { + this.addNotification(notification); + } + } +}; + +const NotificationsPlugin = { + install(Vue, options) { + let app = new Vue({ + data: { + notificationStore: NotificationStore + }, + methods: { + notify(notification) { + this.notificationStore.notify(notification); + } + } + }); + Vue.prototype.$notify = app.notify; + Vue.prototype.$notifications = app.notificationStore; + Vue.component('Notifications', Notifications); + if (options) { + NotificationStore.setOptions(options); + } + } +}; + +export default NotificationsPlugin; diff --git a/frontend/src/components/SearchUser.vue b/frontend/src/components/SearchUser.vue new file mode 100644 index 000000000..143fcfeac --- /dev/null +++ b/frontend/src/components/SearchUser.vue @@ -0,0 +1,85 @@ + + \ No newline at end of file diff --git a/frontend/src/components/SidebarPlugin/SideBar.vue b/frontend/src/components/SidebarPlugin/SideBar.vue new file mode 100755 index 000000000..e28d733e4 --- /dev/null +++ b/frontend/src/components/SidebarPlugin/SideBar.vue @@ -0,0 +1,174 @@ + + diff --git a/frontend/src/components/SidebarPlugin/SidebarItem.vue b/frontend/src/components/SidebarPlugin/SidebarItem.vue new file mode 100755 index 000000000..aea2ccfb4 --- /dev/null +++ b/frontend/src/components/SidebarPlugin/SidebarItem.vue @@ -0,0 +1,197 @@ + + + diff --git a/frontend/src/components/SidebarPlugin/index.js b/frontend/src/components/SidebarPlugin/index.js new file mode 100755 index 000000000..2239c7c31 --- /dev/null +++ b/frontend/src/components/SidebarPlugin/index.js @@ -0,0 +1,43 @@ +import Sidebar from './SideBar.vue'; +import SidebarItem from './SidebarItem.vue'; + +const SidebarStore = { + showSidebar: false, + sidebarLinks: [], + isMinimized: false, + displaySidebar(value) { + this.showSidebar = value; + }, + toggleMinimize() { + document.body.classList.toggle('sidebar-mini'); + // we simulate the window Resize so the charts will get updated in realtime. + const simulateWindowResize = setInterval(() => { + window.dispatchEvent(new Event('resize')); + }, 180); + + // we stop the simulation of Window Resize after the animations are completed + setTimeout(() => { + clearInterval(simulateWindowResize); + }, 1000); + + this.isMinimized = !this.isMinimized; + } +}; + +const SidebarPlugin = { + install(Vue, options) { + if (options && options.sidebarLinks) { + SidebarStore.sidebarLinks = options.sidebarLinks; + } + let app = new Vue({ + data: { + sidebarStore: SidebarStore + } + }); + Vue.prototype.$sidebar = app.sidebarStore; + Vue.component('side-bar', Sidebar); + Vue.component('sidebar-item', SidebarItem); + } +}; + +export default SidebarPlugin; diff --git a/frontend/src/components/SwitchLang.vue b/frontend/src/components/SwitchLang.vue new file mode 100644 index 000000000..cd3c19c89 --- /dev/null +++ b/frontend/src/components/SwitchLang.vue @@ -0,0 +1,126 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/components/Tabs/Tab.vue b/frontend/src/components/Tabs/Tab.vue new file mode 100644 index 000000000..e247f5176 --- /dev/null +++ b/frontend/src/components/Tabs/Tab.vue @@ -0,0 +1,33 @@ + + + diff --git a/frontend/src/components/Tabs/Tabs.vue b/frontend/src/components/Tabs/Tabs.vue new file mode 100644 index 000000000..f77243952 --- /dev/null +++ b/frontend/src/components/Tabs/Tabs.vue @@ -0,0 +1,161 @@ + + + + + diff --git a/frontend/src/components/index.js b/frontend/src/components/index.js new file mode 100755 index 000000000..8b8caea9e --- /dev/null +++ b/frontend/src/components/index.js @@ -0,0 +1,52 @@ +import BaseCheckbox from './Inputs/BaseCheckbox.vue'; +import BaseAlert from './BaseAlert.vue'; +import BaseRadio from './Inputs/BaseRadio.vue'; +import BaseInput from './Inputs/BaseInput.vue'; +import Badge from './Badge'; +import BaseProgress from './BaseProgress.vue'; +import BaseButton from './BaseButton.vue'; + +import BaseDropdown from './BaseDropdown.vue'; +import BaseTable from './BaseTable.vue'; + +import Card from './Cards/Card.vue'; +import StatsCard from './Cards/StatsCard.vue'; +import BaseNav from './Navbar/BaseNav'; +import NavbarToggleButton from './Navbar/NavbarToggleButton'; + +import TabPane from './Tabs/Tab.vue'; +import Tabs from './Tabs/Tabs.vue'; +import Collapse from './Collapse/Collapse.vue'; +import CollapseItem from './Collapse/CollapseItem.vue'; +import Modal from './Modal.vue'; +import BaseSlider from './BaseSlider.vue'; +import LoadingPanel from './LoadingPanel.vue'; + +import BasePagination from './BasePagination.vue'; + +import SidebarPlugin from './SidebarPlugin'; + +export { + BaseCheckbox, + Badge, + BaseAlert, + BaseProgress, + BasePagination, + BaseRadio, + BaseInput, + Card, + StatsCard, + BaseTable, + BaseDropdown, + SidebarPlugin, + BaseNav, + NavbarToggleButton, + TabPane, + Tabs, + Modal, + BaseSlider, + BaseButton, + Collapse, + CollapseItem, + LoadingPanel +}; diff --git a/frontend/src/directives/click-ouside.js b/frontend/src/directives/click-ouside.js new file mode 100644 index 000000000..3021e4980 --- /dev/null +++ b/frontend/src/directives/click-ouside.js @@ -0,0 +1,15 @@ +export default { + bind: function(el, binding, vnode) { + el.clickOutsideEvent = function(event) { + // here I check that click was outside the el and his childrens + if (!(el == event.target || el.contains(event.target))) { + // and if it did, call method provided in attribute value + vnode.context[binding.expression](event); + } + }; + document.body.addEventListener('click', el.clickOutsideEvent); + }, + unbind: function(el) { + document.body.removeEventListener('click', el.clickOutsideEvent); + } +}; diff --git a/frontend/src/i18n.js b/frontend/src/i18n.js new file mode 100644 index 000000000..dbdced961 --- /dev/null +++ b/frontend/src/i18n.js @@ -0,0 +1,23 @@ +import Vue from 'vue' +import VueI18n from 'vue-i18n' + +Vue.use(VueI18n) + +function loadLocaleMessages () { + const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i) + const messages = {} + locales.keys().forEach(key => { + const matched = key.match(/([A-Za-z0-9-_]+)\./i) + if (matched && matched.length > 1) { + const locale = matched[1] + messages[locale] = locales(key) + } + }) + return messages +} + +export default new VueI18n({ + locale: 'en', + fallbackLocale: 'en', + messages: loadLocaleMessages() +}) \ No newline at end of file diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json new file mode 100644 index 000000000..9aa90c698 --- /dev/null +++ b/frontend/src/locales/de.json @@ -0,0 +1,70 @@ +{ + "message": "hallo gradido !!", + "site": { + "welcome":"Willkommen!", + "logout":"Logout", + "login":"Login", + "overview":{ + "account_overview":"Kontoübersicht", + "current_balance":"Aktueller Kontostand", + "gradido_received":"Erhaltene Gradido", + "since_last_month": "seid letzten Monat", + "send_gradido":"Gradido versenden", + "table" : { + "status":"Status", + "amount":"Betrag", + "name":"Name", + "date":"Datum", + "details":"Details", + "view":"Anzeigen", + "hide":"Ausblenden", + "decay":"Vergänglichkeit", + "sender":"Absender", + "hide_details":"Details ausblenden" + }, + "add_work":"neuer Gemeinschaftsbeitrag", + "xx":"xx", + "xxxx":"xxxx" + }, + "navbar" : { + "my-profil":"Mein Profil", + "settings":"Einstellung", + "activity":"Aktivität", + "support":"Support", + "logout":"Logout" + }, + "sidebar" : { + "community":"Gemeinschaft", + "members_area":"Mitgliederbereich", + "membership":"Mitgliedschaft", + "language":"Sprachen" + }, + "landing1" : { + "explore": "Erkunden Sie Gradido", + "text": "Gesundes Geld für eine gesunde Welt - Das Gradido-Modell kann weltweiten Wohlstand und Frieden schaffen", + "link": "Seiten erkunden" + }, + "404" : { + "ooops" : "Ooops!", + "text" : "Seite nicht gefunden. Aber keine Sorge, wir haben noch viele andere Seiten zum Erkunden", + "back" : "zurück zur Übersicht!" + } + }, + "admin": { + "site": { + "overview": { + "created": "created", + "transience" : "Transience", + "exchanged": "Exchanged", + "members" : "Members" + } + } + }, + "nav": { + "features": "Neuigkeiten" + }, + "about": { + "title": "Über uns", + "content": "Lorem ipsum deutsch dolor sit amet consectetur adipisicing elit. Aut dicta incidunt ea ut commodi quidem temporibus illo quia. Et itaque deleniti veniam tempore facere ipsum animi totam culpa minima vel voluptatem adipisci natus blanditiis similique sunt expedita, ex dicta doloremque repellat vitae temporibus. Quisquam quia, accusantium blanditiis architecto facilis saepe! Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad unde laborum ut suscipit iure aliquam sapiente doloribus exercitationem nam sint." + } +} \ No newline at end of file diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json new file mode 100644 index 000000000..484311492 --- /dev/null +++ b/frontend/src/locales/en.json @@ -0,0 +1,70 @@ +{ + "message": "hello gradido !!", + "site": { + "welcome":"Welcome!", + "logout":"Logout", + "login":"Login", + "overview":{ + "account_overview":"Account overview", + "current_balance":"Current account balance", + "gradido_received":"Gradido received", + "since_last_month": "since last month", + "send_gradido":"Send Gradido", + "table" : { + "status":"Status", + "amount":"Amount", + "name":"Name", + "date":"Date", + "details":"Details", + "view":"View", + "hide":"hide", + "decay":"Decay", + "sender":"Sender", + "hide_details":"Hide details" + }, + "add_work":"New Community Contribution", + "xx":"xx", + "xxxx":"xxxx" + }, + "navbar" : { + "my-profil":"My Profil", + "settings":"Settings", + "activity":"Activity", + "support":"Support", + "logout":"Logout" + }, + "sidebar" : { + "community":"Community", + "members_area":"Members area", + "membership":"Membership", + "language":"Language" + }, + "landing1" : { + "explore":"Explore Gradido", + "text":"If you want to get inspiration or just show something directly to your clients, you can jump start your development with our pre-built example pages.", + "link":"Explore pages" + }, + "404" : { + "ooops" : "Ooops!", + "text" : "Page not found. Don't worry though, we have plenty of other pages to explore", + "back" : "Back to dashboard!" + } +}, +"admin": { + "site": { + "overview": { + "creation": "Creation", + "transience" : "Transience", + "exchanged": "Exchanged", + "members" : "Members" + } + } +}, + "nav": { + "features": "Features" + }, + "about": { + "title": "About", + "content": "Lorem ipsum english dolor sit amet consectetur adipisicing elit. Aut dicta incidunt ea ut commodi quidem temporibus illo quia. Et itaque deleniti veniam tempore facere ipsum animi totam culpa minima vel voluptatem adipisci natus blanditiis similique sunt expedita, ex dicta doloremque repellat vitae temporibus. Quisquam quia, accusantium blanditiis architecto facilis saepe! Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad unde laborum ut suscipit iure aliquam sapiente doloribus exercitationem nam sint." + } +} \ No newline at end of file diff --git a/frontend/src/main.js b/frontend/src/main.js new file mode 100755 index 000000000..d98768a6e --- /dev/null +++ b/frontend/src/main.js @@ -0,0 +1,26 @@ +import Vue from 'vue'; +import DashboardPlugin from './plugins/dashboard-plugin'; +import App from './App.vue'; +import i18n from './i18n.js'; +import VueCookies from 'vue-cookies'; + +// store +import {store} from './store/store'; + +// router setup +import router from './routes/router'; + +// plugin setup +Vue.use(DashboardPlugin); +Vue.config.productionTip = false; +Vue.use(VueCookies); + + +/* eslint-disable no-new */ +new Vue({ + el: '#app', + router, + store, + i18n, + render: h => h(App) +}); diff --git a/frontend/src/plugins/dashboard-plugin.js b/frontend/src/plugins/dashboard-plugin.js new file mode 100755 index 000000000..41cfe0509 --- /dev/null +++ b/frontend/src/plugins/dashboard-plugin.js @@ -0,0 +1,63 @@ +// Polyfills for js features used in the Dashboard but not supported in some browsers (mainly IE) +import '@/polyfills'; +// Notifications plugin. Used on Notifications page +import Notifications from '@/components/NotificationPlugin'; +// Validation plugin used to validate forms +import { configure } from 'vee-validate'; +// A plugin file where you could register global components used across the app +import GlobalComponents from './globalComponents'; +// A plugin file where you could register global directives +import GlobalDirectives from './globalDirectives'; +// Sidebar on the right. Used as a local plugin in DashboardLayout.vue +import SideBar from '@/components/SidebarPlugin'; + +// element ui language configuration +import lang from 'element-ui/lib/locale/lang/en'; +import locale from 'element-ui/lib/locale'; +locale.use(lang); + +// vue-bootstrap +import { BootstrapVue, IconsPlugin } from 'bootstrap-vue' + +// asset imports +import '@/assets/scss/argon.scss'; +import '@/assets/vendor/nucleo/css/nucleo.css'; +import { extend } from 'vee-validate'; +import * as rules from 'vee-validate/dist/rules'; +import { messages } from 'vee-validate/dist/locale/en.json'; + +import VueQrcodeReader from "vue-qrcode-reader"; + + +import VueGoodTablePlugin from 'vue-good-table'; +// import the styles +import 'vue-good-table/dist/vue-good-table.css'; + + +Object.keys(rules).forEach(rule => { + extend(rule, { + ...rules[rule], // copies rule configuration + message: messages[rule] // assign message + }); +}); +export default { + install(Vue) { + Vue.use(GlobalComponents); + Vue.use(GlobalDirectives); + Vue.use(SideBar); + Vue.use(Notifications); + Vue.use(BootstrapVue); + Vue.use(IconsPlugin); + Vue.use(VueGoodTablePlugin); + Vue.use(VueQrcodeReader); + configure({ + classes: { + valid: 'is-valid', + invalid: 'is-invalid', + dirty: ['is-dirty', 'is-dirty'], // multiple classes per flag! + } + }) + } +}; + + diff --git a/frontend/src/plugins/globalComponents.js b/frontend/src/plugins/globalComponents.js new file mode 100755 index 000000000..8322d83d1 --- /dev/null +++ b/frontend/src/plugins/globalComponents.js @@ -0,0 +1,45 @@ +import BaseInput from '@/components/Inputs/BaseInput.vue'; +import BaseDropdown from '@/components/BaseDropdown.vue'; +import Card from '@/components/Cards/Card.vue'; +import Modal from '@/components/Modal.vue'; +import StatsCard from '@/components/Cards/StatsCard.vue'; +import BaseButton from '@/components/BaseButton.vue'; +import Badge from '@/components/Badge.vue'; +import BaseCheckbox from '@/components/Inputs/BaseCheckbox.vue'; +import BaseRadio from "@/components/Inputs/BaseRadio"; +import BaseProgress from "@/components/BaseProgress"; +import BasePagination from "@/components/BasePagination"; +import BaseAlert from "@/components/BaseAlert"; +import BaseNav from "@/components/Navbar/BaseNav"; +import BaseHeader from '@/components/BaseHeader'; +import { ValidationProvider, ValidationObserver } from 'vee-validate'; +import { Input, Tooltip, Popover } from 'element-ui'; +/** + * You can register global components here and use them as a plugin in your main Vue instance + */ + +const GlobalComponents = { + install(Vue) { + Vue.component(Badge.name, Badge); + Vue.component(BaseAlert.name, BaseAlert); + Vue.component(BaseButton.name, BaseButton); + Vue.component(BaseCheckbox.name, BaseCheckbox); + Vue.component(BaseHeader.name, BaseHeader); + Vue.component(BaseInput.name, BaseInput); + Vue.component(BaseDropdown.name, BaseDropdown); + Vue.component(BaseNav.name, BaseNav); + Vue.component(BasePagination.name, BasePagination); + Vue.component(BaseProgress.name, BaseProgress); + Vue.component(BaseRadio.name, BaseRadio); + Vue.component(Card.name, Card); + Vue.component(Modal.name, Modal); + Vue.component(StatsCard.name, StatsCard); + Vue.component(Input.name, Input); + Vue.component('validation-provider', ValidationProvider) + Vue.component('validation-observer', ValidationObserver) + Vue.use(Tooltip); + Vue.use(Popover); + } +}; + +export default GlobalComponents; diff --git a/frontend/src/plugins/globalDirectives.js b/frontend/src/plugins/globalDirectives.js new file mode 100755 index 000000000..bea1fff50 --- /dev/null +++ b/frontend/src/plugins/globalDirectives.js @@ -0,0 +1,13 @@ +import clickOutside from '@/directives/click-ouside.js'; + +/** + * You can register global directives here and use them as a plugin in your main Vue instance + */ + +const GlobalDirectives = { + install(Vue) { + Vue.directive('click-outside', clickOutside); + } +}; + +export default GlobalDirectives; diff --git a/frontend/src/polyfills.js b/frontend/src/polyfills.js new file mode 100644 index 000000000..a743ee3e3 --- /dev/null +++ b/frontend/src/polyfills.js @@ -0,0 +1,96 @@ +/* eslint-disable */ +import 'es6-promise/auto' + +export default (function initPollyFills () { + if (!Array.prototype.find) { + Object.defineProperty(Array.prototype, 'find', { + value: function (predicate) { + // 1. Let O be ? ToObject(this value). + if (this == null) { + throw new TypeError('"this" is null or not defined'); + } + + var o = Object(this); + + // 2. Let len be ? ToLength(? Get(O, "length")). + var len = o.length >>> 0; + + // 3. If IsCallable(predicate) is false, throw a TypeError exception. + if (typeof predicate !== 'function') { + throw new TypeError('predicate must be a function'); + } + + // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. + var thisArg = arguments[1]; + + // 5. Let k be 0. + var k = 0; + + // 6. Repeat, while k < len + while (k < len) { + // a. Let Pk be ! ToString(k). + // b. Let kValue be ? Get(O, Pk). + // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). + // d. If testResult is true, return kValue. + var kValue = o[k]; + if (predicate.call(thisArg, kValue, k, o)) { + return kValue; + } + // e. Increase k by 1. + k++; + } + + // 7. Return undefined. + return undefined; + } + }); + } + if (typeof Object.assign !== 'function') { + // Must be writable: true, enumerable: false, configurable: true + Object.defineProperty(Object, "assign", { + value: function assign (target, varArgs) { // .length of function is 2 + 'use strict'; + if (target == null) { // TypeError if undefined or null + throw new TypeError('Cannot convert undefined or null to object'); + } + + var to = Object(target); + + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + + if (nextSource != null) { // Skip over if undefined or null + for (var nextKey in nextSource) { + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + }, + writable: true, + configurable: true + }); + } + if (!String.prototype.startsWith) { + String.prototype.startsWith = function(search, pos) { + return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; + }; + } + if (!String.prototype.includes) { + String.prototype.includes = function(search, start) { + 'use strict'; + if (typeof start !== 'number') { + start = 0; + } + + if (start + search.length > this.length) { + return false; + } else { + return this.indexOf(search, start) !== -1; + } + }; + } +}()) diff --git a/frontend/src/routes/router.js b/frontend/src/routes/router.js new file mode 100644 index 000000000..497d323b2 --- /dev/null +++ b/frontend/src/routes/router.js @@ -0,0 +1,47 @@ +import Vue from 'vue' +import VueRouter from 'vue-router' +import routes from './routes' +import {store} from '../store/store'; + +Vue.use(VueRouter) + +// configure router +const router = new VueRouter({ + routes, // short for routes: routes + linkActiveClass: 'active', + scrollBehavior: (to, from ,savedPosition) => { + if (savedPosition) { + return savedPosition; + } + if (to.hash) { + return { selector: to.hash } + } + return { x: 0, y: 0 } + } +}); + +router.beforeEach((to, from, next) => { + + let language = to.params.lang + if (!language) { + language = 'de' + } + + //console.log("----------------") + //("ROUTER.js to", to) + //console.log("ROUTER.js store.state.is_auth", store.state.is_auth) + //console.log("ROUTER.js store.commit('isActive')", store.commit('isActive')) + + //if (store.commit('isActive') ) { + // next() + //} else { + // next("/login") + //} + //console.log(from) + //console.log(next) + + next() + +}) + +export default router diff --git a/frontend/src/routes/routes.js b/frontend/src/routes/routes.js new file mode 100755 index 000000000..c571acc30 --- /dev/null +++ b/frontend/src/routes/routes.js @@ -0,0 +1,79 @@ +import DashboardLayout from '@/views/Layout/DashboardLayout.vue' +import AuthLayoutGDD from '@/views/Layout/AuthLayout_gdd.vue' +import AuthLayout from '@/views/Layout/AuthLayout.vue' + +import NotFound from '@/views/NotFoundPage.vue' + + +const routes = [ + { + path: '/', + redirect: 'landing', + component: AuthLayoutGDD, + children: [ + { + path: '/Landing', + name: 'Landing', + component: () => import(/* webpackChunkName: "demo" */ '../views/Landing.vue') + }, + { + path: '/login', + name: 'login', + component: () => import(/* webpackChunkName: "demo" */ '../views/Pages/Login.vue') + }, + + ] + }, + { + path: '/', + redirect: 'KontoOverview', + component: DashboardLayout, + children: [ + { + path: '/KontoOverview', + name: 'Kontoübersicht', + component: () => import(/* webpackChunkName: "demo" */ '../views/KontoOverview.vue'), + meta: { + requiresAuth: true + } + }, + { + path: '/profile', + name: 'profile', + component: () => import(/* webpackChunkName: "demo" */ '../views/Pages/UserProfile.vue') + }, + { + path: '/register', + name: 'register', + component: () => import(/* webpackChunkName: "demo" */ '../views/Pages/Register.vue') + }, + ] + }, + , + { + path: '/', + redirect: 'AdminOverview', + component: AuthLayout, + children: [ + { + path: '/AdminOverview', + name: 'Adminübersicht', + component: () => import(/* webpackChunkName: "demo" */ '../views/AdminOverview.vue'), + meta: { + requiresAuth: true + } + } + ] + }, + { + path: '/', + redirect: 'login', + component: AuthLayout, + children: [ + + { path: '*', component: NotFound } + ] + } +]; + +export default routes; diff --git a/frontend/src/routes/starterRouter.js b/frontend/src/routes/starterRouter.js new file mode 100644 index 000000000..261493fd1 --- /dev/null +++ b/frontend/src/routes/starterRouter.js @@ -0,0 +1,33 @@ +import Vue from 'vue'; +import Router from 'vue-router'; +import DashboardLayout from '../views/Starter/SampleLayout.vue'; +import Starter from '../views/Starter/SamplePage.vue'; + +Vue.use(Router); + +export default new Router({ + routes: [ + { + path: '/', + name: 'home', + redirect: '/dashboard', + component: DashboardLayout, + children: [ + { + path: 'dashboard', + name: 'dashboard', + components: { default: Starter } + } + ] + } + ], + scrollBehavior: (to, from ,savedPosition) => { + if (savedPosition) { + return savedPosition; + } + if (to.hash) { + return { selector: to.hash }; + } + return { x: 0, y: 0 }; + } +}); diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js new file mode 100644 index 000000000..b97bf47a1 --- /dev/null +++ b/frontend/src/store/store.js @@ -0,0 +1,92 @@ +import Vue from 'vue' +import Vuex from 'vuex' +Vue.use(Vuex) +import axios from 'axios'; +import VueCookies from 'vue-cookies'; +import router from '../routes/router.js'; + +export const store = new Vuex.Store({ + state: { + path: 'http://192.168.0.89/account/', + is_auth: false, + is_admin: false, + active: false, + modals: false, + user : { + name:"", + email:"" + }, + dataLogout: {"session_id": -127182} + }, + mutations: { + isActive(state) { + //("Im Store PRÜFEN PRÜFEN" ) + return true + }, + login (state, logindata) { + //console.log("Im Store LOGIN() start " ) + //console.log("logon state =>", state ) + //console.log("logon TEST =>", logindata ) + axios.post("http://localhost/login_api/unsecureLogin", logindata).then((ldata) => { + + //console.log("Im Store LOGIN() axios then.statusText ", ldata.statusText); + if (ldata.statusText === "OK") { + console.log("STORE login() ldatasession_id", ldata.data.session_id) + state.is_auth = true + state.active = true + $cookies.set('gdd_is_auth','true'); + $cookies.set('gdd_session_id', ldata.data.session_id); + $cookies.set('gdd_email',logindata.email); + state.user.email = logindata.email + + //console.log("STORE login() to " + state.is_auth) + router.push('/KontoOverview') + + } + + return true + }, (error) => { + console.log(error); + }); + //console.log("STORE login() from" + state.is_auth) + //if (state.is_auth) { + // state.is_auth = false + // state.active = false + //} else { + // state.is_auth = true + // state.active = true + //} + // console.log("STORE login() to " + state.is_auth) + }, + creatUser( state, formdata) { + //console.log("Im Store creatUser() start " ) + axios.post("http://localhost/login_api/createUser", formdata).then((ldata) => { + + console.log("Im Store creatUser() axios then ", ldata); + // this.ldata = ldata.data; + return true + + }, (error) => { + console.log(error); + }); + }, + logout(state){ + axios.post("http://localhost/login_api/logout", this.dataLogout).then((ldata) => { + + //console.log("Im Store logout() axios then ", ldata); + // this.ldata = ldata.data; + //return true + state.is_auth = false + state.is_admin = false + state.active = false + $cookies.set('gdd_is_auth','false'); + $cookies.remove('gdd_email'); + $cookies.remove('gdd_session_id'); + router.push('/Landing') + }, (error) => { + console.log(error); + }); + + } + } +}) \ No newline at end of file diff --git a/frontend/src/util/throttle.js b/frontend/src/util/throttle.js new file mode 100644 index 000000000..9f115248b --- /dev/null +++ b/frontend/src/util/throttle.js @@ -0,0 +1,15 @@ +/** + * Simple throttle function that executes a passed function only once in the specified timeout + * @param handlerFunc + * @param [timeout] the throttle interval + */ +export function throttle(handlerFunc, timeout = 66) { + let resizeTimeout; + if (!resizeTimeout) { + resizeTimeout = setTimeout(() => { + resizeTimeout = null; + handlerFunc(); + // The actualResizeHandler will execute at a rate of 15fps + }, timeout); + } +} diff --git a/frontend/src/views/AdminOverview.vue b/frontend/src/views/AdminOverview.vue new file mode 100644 index 000000000..b54920a9d --- /dev/null +++ b/frontend/src/views/AdminOverview.vue @@ -0,0 +1,385 @@ + + + diff --git a/frontend/src/views/AdminOverview/AdminUserCreation.vue b/frontend/src/views/AdminOverview/AdminUserCreation.vue new file mode 100644 index 000000000..f6006227d --- /dev/null +++ b/frontend/src/views/AdminOverview/AdminUserCreation.vue @@ -0,0 +1,180 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/AdminOverview/AdminUserSearch.vue b/frontend/src/views/AdminOverview/AdminUserSearch.vue new file mode 100644 index 000000000..cb3b5b9d8 --- /dev/null +++ b/frontend/src/views/AdminOverview/AdminUserSearch.vue @@ -0,0 +1,203 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/AdminOverview/default.vue b/frontend/src/views/AdminOverview/default.vue new file mode 100644 index 000000000..ff235e796 --- /dev/null +++ b/frontend/src/views/AdminOverview/default.vue @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/Dashboard.vue b/frontend/src/views/Dashboard.vue new file mode 100644 index 000000000..0e9e6c012 --- /dev/null +++ b/frontend/src/views/Dashboard.vue @@ -0,0 +1,217 @@ + + + diff --git a/frontend/src/views/Dashboard/GoodTable.vue b/frontend/src/views/Dashboard/GoodTable.vue new file mode 100644 index 000000000..9cab3a054 --- /dev/null +++ b/frontend/src/views/Dashboard/GoodTable.vue @@ -0,0 +1,111 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/Dashboard/PageVisitsTable.vue b/frontend/src/views/Dashboard/PageVisitsTable.vue new file mode 100644 index 000000000..fd98bc78b --- /dev/null +++ b/frontend/src/views/Dashboard/PageVisitsTable.vue @@ -0,0 +1,94 @@ + + + diff --git a/frontend/src/views/Dashboard/SocialTrafficTable.vue b/frontend/src/views/Dashboard/SocialTrafficTable.vue new file mode 100644 index 000000000..bd3eace62 --- /dev/null +++ b/frontend/src/views/Dashboard/SocialTrafficTable.vue @@ -0,0 +1,92 @@ + + + diff --git a/frontend/src/views/GoogleMaps.vue b/frontend/src/views/GoogleMaps.vue new file mode 100755 index 000000000..82780f669 --- /dev/null +++ b/frontend/src/views/GoogleMaps.vue @@ -0,0 +1,150 @@ + + diff --git a/frontend/src/views/Icons.vue b/frontend/src/views/Icons.vue new file mode 100644 index 000000000..7f9c932fb --- /dev/null +++ b/frontend/src/views/Icons.vue @@ -0,0 +1,1209 @@ + + + diff --git a/frontend/src/views/KontoOverview.vue b/frontend/src/views/KontoOverview.vue new file mode 100644 index 000000000..b568bf8f0 --- /dev/null +++ b/frontend/src/views/KontoOverview.vue @@ -0,0 +1,135 @@ + + + + + + + + \ No newline at end of file diff --git a/frontend/src/views/KontoOverview/GddAddWork.vue b/frontend/src/views/KontoOverview/GddAddWork.vue new file mode 100644 index 000000000..a0bfb2f43 --- /dev/null +++ b/frontend/src/views/KontoOverview/GddAddWork.vue @@ -0,0 +1,96 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/KontoOverview/GddSent.vue b/frontend/src/views/KontoOverview/GddSent.vue new file mode 100644 index 000000000..c94a48729 --- /dev/null +++ b/frontend/src/views/KontoOverview/GddSent.vue @@ -0,0 +1,174 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/KontoOverview/GddStatus.vue b/frontend/src/views/KontoOverview/GddStatus.vue new file mode 100644 index 000000000..1b0985665 --- /dev/null +++ b/frontend/src/views/KontoOverview/GddStatus.vue @@ -0,0 +1,38 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/KontoOverview/GddTable.vue b/frontend/src/views/KontoOverview/GddTable.vue new file mode 100644 index 000000000..ccc29d67e --- /dev/null +++ b/frontend/src/views/KontoOverview/GddTable.vue @@ -0,0 +1,91 @@ + + + + \ No newline at end of file diff --git a/frontend/src/views/KontoOverview/GddTableSentReceived.vue b/frontend/src/views/KontoOverview/GddTableSentReceived.vue new file mode 100644 index 000000000..e1694f6cf --- /dev/null +++ b/frontend/src/views/KontoOverview/GddTableSentReceived.vue @@ -0,0 +1,75 @@ + + + + \ No newline at end of file diff --git a/frontend/src/views/KontoOverview/GddWorkTable.vue b/frontend/src/views/KontoOverview/GddWorkTable.vue new file mode 100644 index 000000000..463db1da9 --- /dev/null +++ b/frontend/src/views/KontoOverview/GddWorkTable.vue @@ -0,0 +1,52 @@ + + + + \ No newline at end of file diff --git a/frontend/src/views/KontoOverview/default.vue b/frontend/src/views/KontoOverview/default.vue new file mode 100644 index 000000000..ff235e796 --- /dev/null +++ b/frontend/src/views/KontoOverview/default.vue @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/Landing.vue b/frontend/src/views/Landing.vue new file mode 100644 index 000000000..856565a25 --- /dev/null +++ b/frontend/src/views/Landing.vue @@ -0,0 +1,145 @@ + + \ No newline at end of file diff --git a/frontend/src/views/Layout/AdminLayout.vue b/frontend/src/views/Layout/AdminLayout.vue new file mode 100644 index 000000000..cbed877b1 --- /dev/null +++ b/frontend/src/views/Layout/AdminLayout.vue @@ -0,0 +1,118 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/Layout/AuthLayout.vue b/frontend/src/views/Layout/AuthLayout.vue new file mode 100755 index 000000000..48c156c31 --- /dev/null +++ b/frontend/src/views/Layout/AuthLayout.vue @@ -0,0 +1,179 @@ + + + diff --git a/frontend/src/views/Layout/AuthLayout_gdd.vue b/frontend/src/views/Layout/AuthLayout_gdd.vue new file mode 100644 index 000000000..840be9876 --- /dev/null +++ b/frontend/src/views/Layout/AuthLayout_gdd.vue @@ -0,0 +1,147 @@ + + + diff --git a/frontend/src/views/Layout/Content.vue b/frontend/src/views/Layout/Content.vue new file mode 100755 index 000000000..18790e542 --- /dev/null +++ b/frontend/src/views/Layout/Content.vue @@ -0,0 +1,17 @@ + + + diff --git a/frontend/src/views/Layout/ContentFooter.vue b/frontend/src/views/Layout/ContentFooter.vue new file mode 100755 index 000000000..1424984d2 --- /dev/null +++ b/frontend/src/views/Layout/ContentFooter.vue @@ -0,0 +1,37 @@ + + + diff --git a/frontend/src/views/Layout/DashboardLayout.vue b/frontend/src/views/Layout/DashboardLayout.vue new file mode 100755 index 000000000..72793376d --- /dev/null +++ b/frontend/src/views/Layout/DashboardLayout.vue @@ -0,0 +1,112 @@ + + + diff --git a/frontend/src/views/Layout/DashboardNavbar.vue b/frontend/src/views/Layout/DashboardNavbar.vue new file mode 100755 index 000000000..a373a058c --- /dev/null +++ b/frontend/src/views/Layout/DashboardNavbar.vue @@ -0,0 +1,128 @@ + + diff --git a/frontend/src/views/Maps/API_KEY.js b/frontend/src/views/Maps/API_KEY.js new file mode 100755 index 000000000..018f09dc6 --- /dev/null +++ b/frontend/src/views/Maps/API_KEY.js @@ -0,0 +1 @@ +export const API_KEY = 'YOUR_API_KEY'; diff --git a/frontend/src/views/NotFoundPage.vue b/frontend/src/views/NotFoundPage.vue new file mode 100755 index 000000000..4693d8a6b --- /dev/null +++ b/frontend/src/views/NotFoundPage.vue @@ -0,0 +1,48 @@ + + + diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue new file mode 100755 index 000000000..b5f19cd2d --- /dev/null +++ b/frontend/src/views/Pages/Login.vue @@ -0,0 +1,91 @@ + + diff --git a/frontend/src/views/Pages/Register.vue b/frontend/src/views/Pages/Register.vue new file mode 100755 index 000000000..60637cb29 --- /dev/null +++ b/frontend/src/views/Pages/Register.vue @@ -0,0 +1,110 @@ + + + diff --git a/frontend/src/views/Pages/UserProfile.vue b/frontend/src/views/Pages/UserProfile.vue new file mode 100755 index 000000000..dd20ae8e9 --- /dev/null +++ b/frontend/src/views/Pages/UserProfile.vue @@ -0,0 +1,46 @@ + + + diff --git a/frontend/src/views/Pages/UserProfile/EditProfileForm.vue b/frontend/src/views/Pages/UserProfile/EditProfileForm.vue new file mode 100755 index 000000000..50bf78abf --- /dev/null +++ b/frontend/src/views/Pages/UserProfile/EditProfileForm.vue @@ -0,0 +1,142 @@ + + + diff --git a/frontend/src/views/Pages/UserProfile/UserCard.vue b/frontend/src/views/Pages/UserProfile/UserCard.vue new file mode 100755 index 000000000..a56ac61f4 --- /dev/null +++ b/frontend/src/views/Pages/UserProfile/UserCard.vue @@ -0,0 +1,63 @@ + + + diff --git a/frontend/src/views/RegularTables.vue b/frontend/src/views/RegularTables.vue new file mode 100755 index 000000000..72d8fbbb5 --- /dev/null +++ b/frontend/src/views/RegularTables.vue @@ -0,0 +1,112 @@ + + + diff --git a/frontend/src/views/Starter/SampleFooter.vue b/frontend/src/views/Starter/SampleFooter.vue new file mode 100644 index 000000000..7786a507c --- /dev/null +++ b/frontend/src/views/Starter/SampleFooter.vue @@ -0,0 +1,37 @@ + + + diff --git a/frontend/src/views/Starter/SampleLayout.vue b/frontend/src/views/Starter/SampleLayout.vue new file mode 100755 index 000000000..f0faaaa55 --- /dev/null +++ b/frontend/src/views/Starter/SampleLayout.vue @@ -0,0 +1,77 @@ + + diff --git a/frontend/src/views/Starter/SampleNavbar.vue b/frontend/src/views/Starter/SampleNavbar.vue new file mode 100644 index 000000000..a3742dc5a --- /dev/null +++ b/frontend/src/views/Starter/SampleNavbar.vue @@ -0,0 +1,137 @@ + + + diff --git a/frontend/src/views/Starter/SamplePage.vue b/frontend/src/views/Starter/SamplePage.vue new file mode 100755 index 000000000..e0dee359f --- /dev/null +++ b/frontend/src/views/Starter/SamplePage.vue @@ -0,0 +1,95 @@ + + + diff --git a/frontend/src/views/Tables/RegularTables/DarkTable.vue b/frontend/src/views/Tables/RegularTables/DarkTable.vue new file mode 100644 index 000000000..f7a727511 --- /dev/null +++ b/frontend/src/views/Tables/RegularTables/DarkTable.vue @@ -0,0 +1,93 @@ + + diff --git a/frontend/src/views/Tables/RegularTables/LightTable.vue b/frontend/src/views/Tables/RegularTables/LightTable.vue new file mode 100644 index 000000000..f7af4eb73 --- /dev/null +++ b/frontend/src/views/Tables/RegularTables/LightTable.vue @@ -0,0 +1,96 @@ + + diff --git a/frontend/src/views/Tables/projects.js b/frontend/src/views/Tables/projects.js new file mode 100644 index 000000000..3a40d2d34 --- /dev/null +++ b/frontend/src/views/Tables/projects.js @@ -0,0 +1,75 @@ + +export default [ + { + img: 'img/theme/bootstrap.jpg', + title: 'Argon Design System', + budget: '$2500 USD', + status: 'pending', + statusType: 'warning', + completion: 60 + }, + { + img: 'img/theme/angular.jpg', + title: 'Angular Now UI Kit PRO', + budget: '$1800 USD', + status: 'completed', + statusType: 'success', + completion: 100 + }, + { + img: 'img/theme/sketch.jpg', + title: 'Black Dashboard', + budget: '$3150 USD', + status: 'delayed', + statusType: 'danger', + completion: 72 + }, + { + img: 'img/theme/react.jpg', + title: 'React Material Dashboard', + budget: '$4400 USD', + status: 'on schedule', + statusType: 'info', + completion: 90 + }, + { + img: 'img/theme/vue.jpg', + title: 'Vue Paper UI Kit PRO', + budget: '$2200 USD', + status: 'completed', + statusType: 'success', + completion: 100 + }, + { + img: 'img/theme/bootstrap.jpg', + title: 'Argon Design System', + budget: '$2500 USD', + status: 'pending', + statusType: 'warning', + completion: 60 + }, + { + img: 'img/theme/angular.jpg', + title: 'Angular Now UI Kit PRO', + budget: '$1800 USD', + status: 'completed', + statusType: 'success', + completion: 100 + }, + { + img: 'img/theme/sketch.jpg', + title: 'Black Dashboard', + budget: '$3150 USD', + status: 'delayed', + statusType: 'danger', + completion: 72 + }, + { + img: 'img/theme/vue.jpg', + title: 'Vue Paper UI Kit PRO', + budget: '$2200 USD', + status: 'completed', + statusType: 'success', + completion: 100 + } +] diff --git a/frontend/src/views/Tables/users.js b/frontend/src/views/Tables/users.js new file mode 100755 index 000000000..641b8d76e --- /dev/null +++ b/frontend/src/views/Tables/users.js @@ -0,0 +1,42 @@ +export default [ + { + id: 1, + name: 'John Michael', + image: 'img/theme/team-1.jpg', + createdAt: '10/09/2018', + product: 'Argon Dashboard PRO', + active: true + }, + { + id: 2, + name: 'Alexandra Smith', + image: 'img/theme/team-2.jpg', + createdAt: '08/09/2018', + product: 'Argon Design System', + active: false + }, + { + id: 3, + name: 'Samantha Ivy', + image: 'img/theme/team-3.jpg', + createdAt: '30/08/2018', + product: 'Black Dashboard', + active: false + }, + { + id: 4, + name: 'John Michael', + image: 'img/theme/team-1.jpg', + createdAt: '10/09/2018', + product: 'Argon Dashboard PRO', + active: true + }, + { + id: 5, + name: 'Alexandra Smith', + image: 'img/theme/team-2.jpg', + createdAt: '30/09/2018', + product: 'Vue Argon Dashboard', + active: true + }, +]; diff --git a/frontend/src/views/default.vue b/frontend/src/views/default.vue new file mode 100644 index 000000000..ff235e796 --- /dev/null +++ b/frontend/src/views/default.vue @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/frontend/vue.config.js b/frontend/vue.config.js new file mode 100644 index 000000000..e736f9343 --- /dev/null +++ b/frontend/vue.config.js @@ -0,0 +1,29 @@ +const path = require('path'); + +function resolveSrc(_path) { + return path.join(__dirname, _path); +} +// vue.config.js +module.exports = { + pluginOptions: { + i18n: { + locale: 'de', + fallbackLocale: 'de', + localeDir: 'locales', + enableInSFC: false + } + }, + lintOnSave: true, + configureWebpack: { + // Set up all the aliases we use in our app. + resolve: { + alias: { + assets: resolveSrc('src/assets') + } + } + }, + css: { + // Enable CSS source maps. + sourceMap: process.env.NODE_ENV !== 'production' + } +};