diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b6fd6c31d..42b8c526e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -147,7 +147,7 @@ jobs: ########################################################################## - name: mariadb | Build `test` image run: | - docker build --target mariadb_server_test -t "gradido/mariadb:test" -f ./mariadb/Dockerfile ./ + docker build --target mariadb_server -t "gradido/mariadb:test" -f ./mariadb/Dockerfile ./ docker save "gradido/mariadb:test" > /tmp/mariadb.tar - name: Upload Artifact uses: actions/upload-artifact@v2 @@ -344,7 +344,7 @@ jobs: report_name: Coverage Frontend type: lcov result_path: ./coverage/lcov.info - min_coverage: 82 + min_coverage: 83 token: ${{ github.token }} ############################################################################## @@ -409,10 +409,16 @@ jobs: --health-timeout=3s --health-retries=4 steps: - - name: Debug service - run: echo "$(docker ps)" - - name: Debug container choosing script - run: echo "$(docker container ls | grep mariadb | awk '{ print $1 }')" + # - name: Debug service + # run: echo "$(docker ps)" + #- name: Debug container choosing script + # run: echo "$(docker container ls | grep mariadb | awk '{ print $1 }')" + - name: get mariadb container id + run: echo "::set-output name=id::$(docker container ls | grep mariadb | awk '{ print $1 }')" + id: mariadb_container + - name: get automatic created network + run: echo "::set-output name=id::$(docker network ls | grep github_network | awk '{ print $1 }')" + id: network ########################################################################## # CHECKOUT CODE ########################################################## ########################################################################## @@ -420,6 +426,11 @@ jobs: uses: actions/checkout@v2 with: submodules: true + # Database migration + - name: Start database migration + run: | + docker build --target production_up -t "gradido/database:production_up" database/ + docker run --network ${{ steps.network.outputs.id }} --name=database --env NODE_ENV=production --env DB_HOST=mariadb --env DB_DATABASE=gradido_community_test -d gradido/database:production_up ########################################################################## # Build Login-Server Test Docker image ################################### ########################################################################## diff --git a/.gitignore b/.gitignore index caed320af..c09811443 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ /node_modules/* .vscode messages.pot -.skeema nbproject .metadata /.env diff --git a/backend/src/index.ts b/backend/src/index.ts index 9dd75dce5..65f899b26 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -23,7 +23,7 @@ import schema from './graphql/schema' // TODO implement // import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity"; -const DB_VERSION = '0002-add_settings' +const DB_VERSION = '0004-login_server_data' async function main() { // open mysql connection diff --git a/community_server/src/Controller/ServerUsersController.php b/community_server/src/Controller/ServerUsersController.php index 236e35b7f..c07808641 100644 --- a/community_server/src/Controller/ServerUsersController.php +++ b/community_server/src/Controller/ServerUsersController.php @@ -15,7 +15,8 @@ class ServerUsersController extends AppController public function initialize() { parent::initialize(); - $this->Auth->allow(['add', 'edit']); + // uncomment in devmode to add new community server admin user, but don't!!! commit it + //$this->Auth->allow(['add', 'edit']); $this->Auth->deny('index'); } diff --git a/configs/login_server/grd_login.properties b/configs/login_server/grd_login.properties index 96b0ea928..74424328e 100644 --- a/configs/login_server/grd_login.properties +++ b/configs/login_server/grd_login.properties @@ -17,7 +17,7 @@ phpServer.host = nginx loginServer.path = http://localhost/account loginServer.default_locale = de loginServer.db.host = mariadb -loginServer.db.name = gradido_login +loginServer.db.name = gradido_community loginServer.db.user = root loginServer.db.password = loginServer.db.port = 3306 diff --git a/configs/login_server/grd_login_test.properties b/configs/login_server/grd_login_test.properties index 8a269694a..65aa0c5d0 100644 --- a/configs/login_server/grd_login_test.properties +++ b/configs/login_server/grd_login_test.properties @@ -17,7 +17,7 @@ phpServer.host = nginx loginServer.path = http://localhost/account loginServer.default_locale = de loginServer.db.host = mariadb -loginServer.db.name = gradido_login_test +loginServer.db.name = gradido_community_test loginServer.db.user = root loginServer.db.password = loginServer.db.port = 3306 diff --git a/configs/login_server/setup_db_tables/setup_docker_group.sql b/configs/login_server/setup_db_tables/setup_docker_group.sql deleted file mode 100644 index 5f1b64c3f..000000000 --- a/configs/login_server/setup_db_tables/setup_docker_group.sql +++ /dev/null @@ -1,6 +0,0 @@ -INSERT INTO `groups` (`id`, `alias`, `name`, `url`, `host`, `home`, `description`) VALUES -(1, 'docker', 'docker gradido group', 'localhost', 'nginx', '/', 'gradido test group for docker and stage2 with blockchain db'); - - - - diff --git a/database/migrations/0002-add_settings.ts b/database/migrations/0002-add_settings.ts index 68c340040..d26a2b4cc 100644 --- a/database/migrations/0002-add_settings.ts +++ b/database/migrations/0002-add_settings.ts @@ -11,7 +11,7 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { await queryFn(` - CREATE TABLE IF NOT EXISTS \`user_setting\` ( + CREATE TABLE \`user_setting\` ( \`id\` int(10) unsigned NOT NULL AUTO_INCREMENT, \`userId\` int(11) NOT NULL, \`key\` varchar(255) NOT NULL, @@ -22,5 +22,5 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { // write downgrade logic as parameter of queryFn - await queryFn(`DROP TABLE IF EXISTS \`user_setting\`;`) + await queryFn(`DROP TABLE \`user_setting\`;`) } diff --git a/database/migrations/0003-login_server_tables.ts b/database/migrations/0003-login_server_tables.ts new file mode 100644 index 000000000..dacc211ac --- /dev/null +++ b/database/migrations/0003-login_server_tables.ts @@ -0,0 +1,153 @@ +/* FIRST MIGRATION + * + * This migration is special since it takes into account that + * the database can be setup already but also may not be. + * Therefore you will find all `CREATE TABLE` statements with + * a `IF NOT EXISTS`, all `INSERT` with an `IGNORE` and in the + * downgrade function all `DROP TABLE` with a `IF EXISTS`. + * This ensures compatibility for existing or non-existing + * databases. + */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn(` + CREATE TABLE \`login_app_access_tokens\` ( + \`id\` int unsigned NOT NULL AUTO_INCREMENT, + \`user_id\` int NOT NULL, + \`access_code\` bigint unsigned NOT NULL, + \`created\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + \`updated\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (\`id\`), + UNIQUE KEY \`access_code\` (\`access_code\`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `) + await queryFn(` + CREATE TABLE \`login_elopage_buys\` ( + \`id\` int unsigned NOT NULL AUTO_INCREMENT, + \`elopage_user_id\` int DEFAULT NULL, + \`affiliate_program_id\` int NOT NULL, + \`publisher_id\` int NOT NULL, + \`order_id\` int NOT NULL, + \`product_id\` int NOT NULL, + \`product_price\` int NOT NULL, + \`payer_email\` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + \`publisher_email\` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + \`payed\` tinyint NOT NULL, + \`success_date\` datetime NOT NULL, + \`event\` varchar(255) NOT NULL, + PRIMARY KEY (\`id\`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `) + await queryFn(` + CREATE TABLE \`login_email_opt_in_types\` ( + \`id\` int unsigned NOT NULL AUTO_INCREMENT, + \`name\` varchar(255) NOT NULL, + \`description\` varchar(255) NOT NULL, + PRIMARY KEY (\`id\`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `) + await queryFn(` + CREATE TABLE \`login_email_opt_in\` ( + \`id\` int unsigned NOT NULL AUTO_INCREMENT, + \`user_id\` int NOT NULL, + \`verification_code\` bigint unsigned NOT NULL, + \`email_opt_in_type_id\` int NOT NULL, + \`created\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + \`resend_count\` int DEFAULT '0', + \`updated\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (\`id\`), + UNIQUE KEY \`verification_code\` (\`verification_code\`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `) + await queryFn(` + CREATE TABLE \`login_groups\` ( + \`id\` int unsigned NOT NULL AUTO_INCREMENT, + \`alias\` varchar(190) NOT NULL, + \`name\` varchar(255) NOT NULL, + \`url\` varchar(255) NOT NULL, + \`host\` varchar(255) DEFAULT "/", + \`home\` varchar(255) DEFAULT "/", + \`description\` text, + PRIMARY KEY (\`id\`), + UNIQUE KEY \`alias\` (\`alias\`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `) + await queryFn(` + CREATE TABLE \`login_pending_tasks\` ( + \`id\` int UNSIGNED NOT NULL AUTO_INCREMENT, + \`user_id\` int UNSIGNED DEFAULT 0, + \`request\` varbinary(2048) NOT NULL, + \`created\` datetime NOT NULL, + \`finished\` datetime DEFAULT '2000-01-01 000000', + \`result_json\` text DEFAULT NULL, + \`param_json\` text DEFAULT NULL, + \`task_type_id\` int UNSIGNED NOT NULL, + \`child_pending_task_id\` int UNSIGNED DEFAULT 0, + \`parent_pending_task_id\` int UNSIGNED DEFAULT 0, + PRIMARY KEY (\`id\`) + ) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; + `) + await queryFn(` + CREATE TABLE \`login_roles\` ( + \`id\` int unsigned NOT NULL AUTO_INCREMENT, + \`name\` varchar(255) NOT NULL, + \`description\` varchar(255) NOT NULL, + \`flags\` bigint NOT NULL DEFAULT '0', + PRIMARY KEY (\`id\`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `) + await queryFn(` + CREATE TABLE \`login_user_backups\` ( + \`id\` int unsigned NOT NULL AUTO_INCREMENT, + \`user_id\` int NOT NULL, + \`passphrase\` text NOT NULL, + \`mnemonic_type\` int DEFAULT '-1', + PRIMARY KEY (\`id\`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `) + await queryFn(` + CREATE TABLE \`login_user_roles\` ( + \`id\` int unsigned NOT NULL AUTO_INCREMENT, + \`user_id\` int NOT NULL, + \`role_id\` int NOT NULL, + PRIMARY KEY (\`id\`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `) + await queryFn(` + CREATE TABLE \`login_users\` ( + \`id\` int unsigned NOT NULL AUTO_INCREMENT, + \`email\` varchar(191) NOT NULL, + \`first_name\` varchar(150) NOT NULL, + \`last_name\` varchar(255) DEFAULT '', + \`username\` varchar(255) DEFAULT '', + \`description\` text DEFAULT '', + \`password\` bigint unsigned DEFAULT '0', + \`pubkey\` binary(32) DEFAULT NULL, + \`privkey\` binary(80) DEFAULT NULL, + \`email_hash\` binary(32) DEFAULT NULL, + \`created\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + \`email_checked\` tinyint NOT NULL DEFAULT '0', + \`passphrase_shown\` tinyint NOT NULL DEFAULT '0', + \`language\` varchar(4) NOT NULL DEFAULT 'de', + \`disabled\` tinyint DEFAULT '0', + \`group_id\` int unsigned DEFAULT 0, + \`publisher_id\` int DEFAULT 0, + PRIMARY KEY (\`id\`), + UNIQUE KEY \`email\` (\`email\`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // write downgrade logic as parameter of queryFn + await queryFn(`DROP TABLE \`login_app_access_tokens\`;`) + await queryFn(`DROP TABLE \`login_elopage_buys\`;`) + await queryFn(`DROP TABLE \`login_email_opt_in_types\`;`) + await queryFn(`DROP TABLE \`login_email_opt_in\`;`) + await queryFn(`DROP TABLE \`login_groups\`;`) + await queryFn(`DROP TABLE \`login_pending_tasks\`;`) + await queryFn(`DROP TABLE \`login_roles\`;`) + await queryFn(`DROP TABLE \`login_user_backups\`;`) + await queryFn(`DROP TABLE \`login_user_roles\`;`) + await queryFn(`DROP TABLE \`login_users\`;`) +} diff --git a/database/migrations/0004-login_server_data.ts b/database/migrations/0004-login_server_data.ts new file mode 100644 index 000000000..dad7d1e34 --- /dev/null +++ b/database/migrations/0004-login_server_data.ts @@ -0,0 +1,74 @@ +/* FIRST MIGRATION + * + * This migration is special since it takes into account that + * the database can be setup already but also may not be. + * Therefore you will find all `CREATE TABLE` statements with + * a `IF NOT EXISTS`, all `INSERT` with an `IGNORE` and in the + * downgrade function all `DROP TABLE` with a `IF EXISTS`. + * This ensures compatibility for existing or non-existing + * databases. + */ + +const LOGIN_SERVER_DB = 'gradido_login' + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + const loginDatabaseExists = await queryFn(` + SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '${LOGIN_SERVER_DB}' + `) + if (loginDatabaseExists.length === 0) { + // eslint-disable-next-line no-console + console.log(`Skipping Login Server Database migration - Database ${LOGIN_SERVER_DB} not found`) + return + } + + await queryFn(` + INSERT INTO \`login_app_access_tokens\` SELECT * FROM ${LOGIN_SERVER_DB}.\`app_access_tokens\`; + `) + await queryFn(` + INSERT INTO \`login_elopage_buys\` SELECT * FROM ${LOGIN_SERVER_DB}.\`elopage_buys\`; + `) + await queryFn(` + INSERT INTO \`login_email_opt_in_types\` SELECT * FROM ${LOGIN_SERVER_DB}.\`email_opt_in_types\`; + `) + await queryFn(` + INSERT INTO \`login_email_opt_in\` SELECT * FROM ${LOGIN_SERVER_DB}.\`email_opt_in\`; + `) + await queryFn(` + INSERT INTO \`login_groups\` SELECT * FROM ${LOGIN_SERVER_DB}.\`groups\`; + `) + await queryFn(` + INSERT INTO \`login_pending_tasks\` SELECT * FROM ${LOGIN_SERVER_DB}.\`pending_tasks\`; + `) + await queryFn(` + INSERT INTO \`login_roles\` SELECT * FROM ${LOGIN_SERVER_DB}.\`roles\`; + `) + await queryFn(` + INSERT INTO \`login_user_backups\` SELECT * FROM ${LOGIN_SERVER_DB}.\`user_backups\`; + `) + await queryFn(` + INSERT INTO \`login_user_roles\` SELECT * FROM ${LOGIN_SERVER_DB}.\`user_roles\`; + `) + await queryFn(` + INSERT INTO \`login_users\` SELECT * FROM ${LOGIN_SERVER_DB}.\`users\`; + `) + + // TODO clarify if we need this on non docker environment? + await queryFn(` + INSERT IGNORE INTO \`login_groups\` (\`id\`, \`alias\`, \`name\`, \`url\`, \`host\`, \`home\`, \`description\`) VALUES + (1, 'docker', 'docker gradido group', 'localhost', 'nginx', '/', 'gradido test group for docker and stage2 with blockchain db'); + `) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // write downgrade logic as parameter of queryFn + await queryFn(`DELETE FROM \`login_app_access_tokens\`;`) + await queryFn(`DELETE FROM \`login_elopage_buys\`;`) + await queryFn(`DELETE FROM \`login_email_opt_in_types\`;`) + await queryFn(`DELETE FROM \`login_email_opt_in\`;`) + await queryFn(`DELETE FROM \`login_groups\`;`) + await queryFn(`DELETE FROM \`login_pending_tasks\`;`) + await queryFn(`DELETE FROM \`login_roles\`;`) + await queryFn(`DELETE FROM \`login_user_backups\`;`) + await queryFn(`DELETE FROM \`login_user_roles\`;`) + await queryFn(`DELETE FROM \`login_users\`;`) +} diff --git a/deployment/bare_metal/update_all.sh b/deployment/bare_metal/update_all.sh index b065a16d4..e045d3f39 100755 --- a/deployment/bare_metal/update_all.sh +++ b/deployment/bare_metal/update_all.sh @@ -36,8 +36,6 @@ cd $PROJECT_PATH # git checkout -f master git pull cd deployment/bare_metal -echo 'update schemas' >> $UPDATE_HTML -./update_db_schemas.sh echo 'starting with rebuilding login-server
' >> $UPDATE_HTML ./build_and_start_login_server.sh echo 'starting with rebuilding frontend
' >> $UPDATE_HTML diff --git a/deployment/bare_metal/update_db_schemas.sh b/deployment/bare_metal/update_db_schemas.sh deleted file mode 100755 index 80628f35c..000000000 --- a/deployment/bare_metal/update_db_schemas.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# For that to work skeema needed to be installed on system -# in login_server/skeema skeema configuration files need to be there also in the subfolders -# Update DB Schemas (only the schemas, not the data) - -cd ../../login_server/skeema -skeema push --allow-unsafe diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 1fa6c7e23..5783b9fe7 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -136,22 +136,7 @@ services: - external-net volumes: - /sessions - - ######################################################### - ## skeema for updating dbs if changes happend ########### - ######################################################### - skeema: - build: - context: . - dockerfile: ./skeema/Dockerfile - target: skeema_dev_run - depends_on: - - mariadb - networks: - - internal-net - volumes: - - ./login_server/skeema/gradido_login:/skeema/gradido_login - + volumes: frontend_node_modules: backend_node_modules: diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 457faf950..73da574d2 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -9,7 +9,7 @@ services: build: context: . dockerfile: ./mariadb/Dockerfile - target: mariadb_server_test + target: mariadb_server environment: - MARIADB_ALLOW_EMPTY_PASSWORD=1 - MARIADB_USER=root @@ -75,19 +75,6 @@ services: - external-net volumes: - /sessions - - ######################################################### - ## skeema for updating dbs if changes happend ########### - ######################################################### - skeema: - build: - context: . - dockerfile: ./skeema/Dockerfile - target: skeema_run - depends_on: - - mariadb - networks: - - internal-net networks: external-net: diff --git a/docker-compose.yml b/docker-compose.yml index b85d155fe..3ce88715d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,9 +35,8 @@ services: ######################################################### mariadb: build: - context: . - dockerfile: ./mariadb/Dockerfile - target: mariadb_server_test + context: ./mariadb + target: mariadb_server environment: - MARIADB_ALLOW_EMPTY_PASSWORD=1 - MARIADB_USER=root @@ -158,41 +157,6 @@ services: - internal-net volumes: - ./community_server/config/php-fpm/php-ini-overrides.ini:/etc/php/7.4/fpm/conf.d/99-overrides.ini - - ######################################################### - ## skeema for updating dbs if changes happend ########### - ######################################################### - skeema: - build: - context: . - dockerfile: ./skeema/Dockerfile - target: skeema_run - depends_on: - - mariadb - networks: - - internal-net - - ######################################################### - ## GRADIDO NODE v1 ###################################### - ######################################################### - # gradido-node: - # build: - # context: . - # dockerfile: ./gn/docker/deprecated-hedera-node/Dockerfile - # volumes: - # - ${GN_INSTANCE_FOLDER}:/opt/instance - # container_name: ${GN_CONTAINER_NAME} - - ######################################################### - ## GRADIDO NODE test ################################### - ######################################################### - # gradido-node-test: - # build: - # context: . - # dockerfile: ./gn/docker/deprecated-hedera-node/Dockerfile - # container_name: gn-test - # working_dir: /opt/gn/build - # command: ["./unit_tests"] networks: external-net: diff --git a/docu/Concepts/TechnicalRequirements/Architecture/TechnicalOverview.md b/docu/Concepts/TechnicalRequirements/Architecture/TechnicalOverview.md index f0fe1e52a..73f74dbae 100644 --- a/docu/Concepts/TechnicalRequirements/Architecture/TechnicalOverview.md +++ b/docu/Concepts/TechnicalRequirements/Architecture/TechnicalOverview.md @@ -15,7 +15,7 @@ This document describes the technical overview for the Gradido infrastructur. Be ![CommunityServerAPI](../image/CommunityServerAPI.png) -### Database Skeema +### Database Skeema (outdated) ![CommunityDBSkeema](../image/CommunityDBSkeema.png) diff --git a/docu/create-coins-as-admin.md b/docu/create-coins-as-admin.md new file mode 100644 index 000000000..6a95df119 --- /dev/null +++ b/docu/create-coins-as-admin.md @@ -0,0 +1,27 @@ +### User creation +A user needs to be created on the login_server we do this when we create a User in the client https://$community_domain/vue/register. + +### Admin user +To set a User admin we need the following SQL query on the gradido_login database: +``` +INSERT INTO user_roles (id, user_id, role_id) VALUES (NULL, '1', '1'); +``` +user_id has to be found in users +Now when we login in on https://$community_domain/account/ we can create coins but we will be restricted cause we can't sign the creations. + +### Signation account +At first we need to enable the server user account creation with uncommenting line: 19 in +community_server/src/Controller/ServerUsersController.php +```php +$this->Auth->allow(['add', 'edit']); +``` +This enable us to use this action without being logged in. +To add a signation account we need to go on the following url: http://$community_domain/server-users/add + +### Coin creation process +The coin creation for work is done in the following url: http://$community_domain/transaction-creations/create-multi +Where we can create coins for a number of as many users as we want excepted for our self. +Furthermore we must sign the transactions we created. Normally after clicking on the left button (Transaktion abschließen) we should be automatically forwarded to http://$community_domain/account/checkTransactions where we can do this. +If not this page can also be reached by clicking on the shield-icon with the hook in it on the Dashboard, which is only shown if at least one transaction is waiting for signing. + +For debug purposes you can check the `pending_tasks` table, which is used to store the transactions which are not signed yet or had errors. \ No newline at end of file diff --git a/docu/presentation/adminarea-old-new.pdf b/docu/presentation/adminarea-old-new.pdf new file mode 100644 index 000000000..3fda700ec Binary files /dev/null and b/docu/presentation/adminarea-old-new.pdf differ diff --git a/frontend/package.json b/frontend/package.json index b5c7868b7..e50c5fe89 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,7 +27,6 @@ "babel-preset-vue": "^2.0.2", "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", @@ -64,7 +63,6 @@ "vue": "^2.6.11", "vue-apollo": "^3.0.7", "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", diff --git a/frontend/src/components/Status.spec.js b/frontend/src/components/Status.spec.js new file mode 100644 index 000000000..30dab4345 --- /dev/null +++ b/frontend/src/components/Status.spec.js @@ -0,0 +1,45 @@ +import { mount } from '@vue/test-utils' +import Status from './Status' + +const localVue = global.localVue + +describe('Status', () => { + let wrapper + + const mocks = { + $n: jest.fn((n) => n), + } + + const propsData = { + balance: 1234, + statusText: 'GDD', + } + + const Wrapper = () => { + return mount(Status, { localVue, mocks, propsData }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + describe('balance is pending', () => { + it('it displays an en-dash', () => { + expect(wrapper.find('div.gdd-status-div').text()).toEqual('— GDD') + }) + }) + + describe('balance is loaded', () => { + beforeEach(() => { + wrapper.setProps({ + pending: false, + }) + }) + + it('it displays the ammount of GDD', () => { + expect(wrapper.find('div.gdd-status-div').text()).toEqual('1234 GDD') + }) + }) + }) +}) diff --git a/frontend/src/components/Status.vue b/frontend/src/components/Status.vue new file mode 100644 index 000000000..7900763f7 --- /dev/null +++ b/frontend/src/components/Status.vue @@ -0,0 +1,24 @@ + + + diff --git a/frontend/src/components/Transaction.spec.js b/frontend/src/components/Transaction.spec.js index 43dc44782..aaad023e0 100644 --- a/frontend/src/components/Transaction.spec.js +++ b/frontend/src/components/Transaction.spec.js @@ -1,8 +1,11 @@ import { mount } from '@vue/test-utils' import Transaction from './Transaction' +import Vue from 'vue' const localVue = global.localVue +const consoleErrorMock = jest.fn() + describe('Transaction', () => { let wrapper @@ -27,5 +30,206 @@ describe('Transaction', () => { it('renders the component', () => { expect(wrapper.find('div.gdt-transaction-list-item').exists()).toBeTruthy() }) + + it('has a collapse button', () => { + expect(wrapper.find('button[type="button"].btn-secondary').text()).toBe('i') + }) + + describe('no valid GDT entry type', () => { + beforeEach(async () => { + // disable throwing Errors on warnings to catch the warning + Vue.config.warnHandler = (w) => {} + // eslint-disable-next-line no-console + console.error = consoleErrorMock + await wrapper.setProps({ gdtEntryType: 'NOT_VALID' }) + }) + + it('throws an error', () => { + expect(consoleErrorMock).toBeCalledWith( + expect.objectContaining({ message: 'no lines for this type: NOT_VALID' }), + ) + }) + }) + + describe('default entry type FORM', () => { + beforeEach(async () => { + await wrapper.setProps({ + amount: 100, + date: '2021-05-02T17:20:11+00:00', + comment: 'This is a comment', + factor: 17, + gdt: 1700, + id: 42, + }) + }) + + it('has the heart icon', () => { + expect(wrapper.find('svg.bi-heart').exists()).toBeTruthy() + }) + + it('has the description gdt.contribution', () => { + expect(wrapper.findAll('div.row').at(0).text()).toContain('gdt.contribution') + }) + + it('renders the amount of euros', () => { + expect(wrapper.findAll('div.row').at(0).text()).toContain('100 €') + }) + + it('renders the amount of GDT', () => { + expect(wrapper.findAll('div.row').at(1).text()).toContain('1700 GDT') + }) + + it('renders the comment message', () => { + expect(wrapper.findAll('div.row').at(2).text()).toContain('This is a comment') + }) + + it('renders the date', () => { + expect(wrapper.findAll('div.row').at(3).text()).toContain('Sun May 02 2021') + }) + + it('does not show the collapse by default', () => { + expect(wrapper.find('div#gdt-collapse-42').isVisible()).toBeFalsy() + }) + + describe('without comment', () => { + it('does not render the message row', async () => { + await wrapper.setProps({ comment: undefined }) + expect(wrapper.findAll('div.row').at(2).text()).toContain('form.date') + }) + }) + /* how to open the collapse ????? + describe('collapse is open', () => { + beforeEach(async () => { + //console.log(wrapper.html()) + await wrapper.find('div#gdt-collapse-42').trigger('click') + await wrapper.vm.$nextTick() + await flushPromises() + await wrapper.vm.$nextTick() + await flushPromises() + //console.log(wrapper.find('[enteractiveclass="collapsing"]').html()) + }) + + it('shows the collapse', () => { + //console.log(wrapper.html()) + expect(wrapper.find('div#gdt-collapse-42').isVisible()).toBeTruthy() + }) + }) + */ + }) + + describe('GdtEntryType.CVS', () => { + it('behaves as default FORM', async () => { + await wrapper.setProps({ gdtEntryType: 'CVS' }) + expect(wrapper.find('svg.bi-heart').exists()).toBeTruthy() + }) + }) + + describe('GdtEntryType.ELOPAGE', () => { + it('behaves as default FORM', async () => { + await wrapper.setProps({ gdtEntryType: 'ELOPAGE' }) + expect(wrapper.find('svg.bi-heart').exists()).toBeTruthy() + }) + }) + + describe('GdtEntryType.DIGISTORE', () => { + it('behaves as default FORM', async () => { + await wrapper.setProps({ gdtEntryType: 'DIGISTORE' }) + expect(wrapper.find('svg.bi-heart').exists()).toBeTruthy() + }) + }) + + describe('GdtEntryType.CVS2', () => { + it('behaves as default FORM', async () => { + await wrapper.setProps({ gdtEntryType: 'CVS2' }) + expect(wrapper.find('svg.bi-heart').exists()).toBeTruthy() + }) + }) + + describe('GdtEntryType.ELOPAGE_PUBLISHER', () => { + beforeEach(async () => { + await wrapper.setProps({ + amount: 365.67, + date: '2020-04-10T13:28:00+00:00', + comment: 'This is a comment', + gdtEntryType: 'ELOPAGE_PUBLISHER', + factor: 22, + gdt: 967.65, + id: 42, + }) + }) + + it('has the person-check icon', () => { + expect(wrapper.find('svg.bi-person-check').exists()).toBeTruthy() + }) + + it('has the description gdt.recruited-member', () => { + expect(wrapper.findAll('div.row').at(0).text()).toContain('gdt.recruited-member') + }) + + it('renders the percentage', () => { + expect(wrapper.findAll('div.row').at(0).text()).toContain('5%') + }) + + it('renders the amount of GDT', () => { + expect(wrapper.findAll('div.row').at(1).text()).toContain('365.67 GDT') + }) + + it('renders the comment message', () => { + expect(wrapper.findAll('div.row').at(2).text()).toContain('This is a comment') + }) + + it('renders the date', () => { + expect(wrapper.findAll('div.row').at(3).text()).toContain('Fri Apr 10 2020') + }) + + it('does not show the collapse by default', () => { + expect(wrapper.find('div#gdt-collapse-42').isVisible()).toBeFalsy() + }) + + describe('without comment', () => { + it('does not render the message row', async () => { + await wrapper.setProps({ comment: undefined }) + expect(wrapper.findAll('div.row').at(2).text()).toContain('form.date') + }) + }) + }) + + describe('GdtEntryType.GLOBAL_MODIFICATOR', () => { + beforeEach(async () => { + await wrapper.setProps({ + amount: 123.45, + date: '2020-03-12T13:28:00+00:00', + comment: 'This is a comment', + gdtEntryType: 'GLOBAL_MODIFICATOR', + factor: 19, + gdt: 61.23, + id: 42, + }) + }) + + it('has the gift icon', () => { + expect(wrapper.find('svg.bi-gift').exists()).toBeTruthy() + }) + + it('has the description gdt.gdt-received', () => { + expect(wrapper.findAll('div.row').at(0).text()).toContain('gdt.gdt-received') + }) + + it('renders the comment', () => { + expect(wrapper.findAll('div.row').at(0).text()).toContain('This is a comment') + }) + + it('renders the amount of GDT', () => { + expect(wrapper.findAll('div.row').at(1).text()).toContain('61.23 GDT') + }) + + it('renders the date', () => { + expect(wrapper.findAll('div.row').at(2).text()).toContain('Thu Mar 12 2020') + }) + + it('does not show the collapse by default', () => { + expect(wrapper.find('div#gdt-collapse-42').isVisible()).toBeFalsy() + }) + }) }) }) diff --git a/frontend/src/components/Transaction.vue b/frontend/src/components/Transaction.vue index cc027306b..f1deca565 100644 --- a/frontend/src/components/Transaction.vue +++ b/frontend/src/components/Transaction.vue @@ -1,13 +1,10 @@