diff --git a/CHANGELOG.md b/CHANGELOG.md index a073aeb5f..6c64df990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,36 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.6.6](https://github.com/gradido/gradido/compare/1.6.5...1.6.6) + +- Fix: Upper case email on register breaks account [`#1542`](https://github.com/gradido/gradido/pull/1542) +- 1106 first transaction cannot be expanded [`#1432`](https://github.com/gradido/gradido/pull/1432) +- added missing bootstrap scss. bootstrap/scss/bootstrap, plus more mis… [`#1540`](https://github.com/gradido/gradido/pull/1540) +- feat: Seed Deleted User [`#1533`](https://github.com/gradido/gradido/pull/1533) +- fix: No Creations for Deleted Users [`#1534`](https://github.com/gradido/gradido/pull/1534) +- fix: Wrong Key Name for Recover User [`#1535`](https://github.com/gradido/gradido/pull/1535) +- [Feature] : user deleted and undeleted functions for adminarea [`#1520`](https://github.com/gradido/gradido/pull/1520) +- fix: Possible SQL Exception in User Search [`#1530`](https://github.com/gradido/gradido/pull/1530) +- Feature: Make lint warnings unwanted [`#1529`](https://github.com/gradido/gradido/pull/1529) +- 1459 list data again on confirm creation [`#1467`](https://github.com/gradido/gradido/pull/1467) +- fix: Return Empty Array When No Pending Creations Are Present [`#1526`](https://github.com/gradido/gradido/pull/1526) +- Fix: Correct path of index.js in production [`#1525`](https://github.com/gradido/gradido/pull/1525) +- refactor: Get Open Creations by One Query [`#1524`](https://github.com/gradido/gradido/pull/1524) +- Admin: Langsame Benutzer-Suche [`#1472`](https://github.com/gradido/gradido/pull/1472) +- fix: Backend Unit Tests Running Again [`#1513`](https://github.com/gradido/gradido/pull/1513) +- Refactor: Combine transaction tables [`#1523`](https://github.com/gradido/gradido/pull/1523) +- Refactor: User resolver [`#1522`](https://github.com/gradido/gradido/pull/1522) +- feature: Soft-Delete for users (backend) [`#1521`](https://github.com/gradido/gradido/pull/1521) +- feature: Soft-Delete for users (database only) [`#1516`](https://github.com/gradido/gradido/pull/1516) +- refactor: Improve Decay Display [`#1517`](https://github.com/gradido/gradido/pull/1517) +- 404 page needs back to login button [`#1515`](https://github.com/gradido/gradido/pull/1515) +- feature: show current version in admin footer [`#1514`](https://github.com/gradido/gradido/pull/1514) +- fix: Never Sent Email Text [`#1512`](https://github.com/gradido/gradido/pull/1512) +- refactor: static decay block [`#1405`](https://github.com/gradido/gradido/pull/1405) +- refactor: Use Bootstrap Vue Toast [`#1499`](https://github.com/gradido/gradido/pull/1499) +- fix: Catch GDT Server Errors [`#1479`](https://github.com/gradido/gradido/pull/1479) +- Fix: Autochangelog - no commits [`#1498`](https://github.com/gradido/gradido/pull/1498) + #### [1.6.5](https://github.com/gradido/gradido/compare/1.6.4...1.6.5) > 15 February 2022 diff --git a/admin/package.json b/admin/package.json index 3cd0c54c0..0cbf57f5a 100644 --- a/admin/package.json +++ b/admin/package.json @@ -3,7 +3,7 @@ "description": "Administraion Interface for Gradido", "main": "index.js", "author": "Moriz Wahl", - "version": "1.6.5", + "version": "1.6.6", "license": "MIT", "private": false, "scripts": { diff --git a/admin/src/locales/de.json b/admin/src/locales/de.json index f301d18bd..e5f4bf4ca 100644 --- a/admin/src/locales/de.json +++ b/admin/src/locales/de.json @@ -91,6 +91,6 @@ }, "userIsDeleted": "Der Nutzer ist gelöscht. Es können keine GDD mehr geschöpft werden.", "user_deleted": "Nutzer ist gelöscht.", - "user_recovered.": "Nutzer ist wiederhergestellt.", + "user_recovered": "Nutzer ist wiederhergestellt.", "user_search": "Nutzer-Suche" } diff --git a/admin/src/locales/en.json b/admin/src/locales/en.json index 4eb1fc975..d772d638f 100644 --- a/admin/src/locales/en.json +++ b/admin/src/locales/en.json @@ -91,6 +91,6 @@ }, "userIsDeleted": "The user is deleted. No more GDD can be created.", "user_deleted": "User is deleted.", - "user_recovered.": "User is recovered.", + "user_recovered": "User is recovered.", "user_search": "User search" } diff --git a/backend/package.json b/backend/package.json index 43023ac90..c27419ddb 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "gradido-backend", - "version": "1.6.5", + "version": "1.6.6", "description": "Gradido unified backend providing an API-Service for Gradido Transactions", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/backend", diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index ed8a893a2..448eb57ab 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -10,7 +10,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0028-clean_transaction_table', + DB_VERSION: '0029-clean_transaction_table', DECAY_START_TIME: new Date('2021-05-13 17:46:31'), // GMT+0 } diff --git a/backend/src/graphql/resolver/AdminResolver.ts b/backend/src/graphql/resolver/AdminResolver.ts index 1ee7f326c..2dfaafbcc 100644 --- a/backend/src/graphql/resolver/AdminResolver.ts +++ b/backend/src/graphql/resolver/AdminResolver.ts @@ -262,7 +262,7 @@ export class AdminResolver { const userIds = pendingCreations.map((p) => p.userId) const userCreations = await getUserCreations(userIds) - const users = await User.find({ id: In(userIds) }) + const users = await User.find({ where: { id: In(userIds) }, withDeleted: true }) return pendingCreations.map((pendingCreation) => { const user = users.find((u) => u.id === pendingCreation.userId) @@ -296,6 +296,9 @@ export class AdminResolver { if (moderatorUser.id === pendingCreation.userId) throw new Error('Moderator can not confirm own pending creation') + const user = await User.findOneOrFail({ id: pendingCreation.userId }, { withDeleted: true }) + if (user.deletedAt) throw new Error('This user was deleted. Cannot confirm a creation.') + const creations = await getUserCreation(pendingCreation.userId, false) if (!isCreationValid(creations, Number(pendingCreation.amount) / 10000, pendingCreation.date)) { throw new Error('Creation is not valid!!') diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index fa358ad1f..6b1e7162e 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -326,7 +326,7 @@ export class UserResolver { } // Validate email unique - // TODO: i can register an email in upper/lower case twice + email = email.trim().toLowerCase() // TODO we cannot use repository.count(), since it does not allow to specify if you want to include the soft deletes const userFound = await DbUser.findOne({ email }, { withDeleted: true }) if (userFound) { @@ -399,6 +399,7 @@ export class UserResolver { @Authorized([RIGHTS.SEND_ACTIVATION_EMAIL]) @Mutation(() => Boolean) async sendActivationEmail(@Arg('email') email: string): Promise { + email = email.trim().toLowerCase() const user = await DbUser.findOneOrFail({ email: email }) const queryRunner = getConnection().createQueryRunner() @@ -439,7 +440,7 @@ export class UserResolver { @Query(() => Boolean) async sendResetPasswordEmail(@Arg('email') email: string): Promise { // TODO: this has duplicate code with createUser - + email = email.trim().toLowerCase() const user = await DbUser.findOneOrFail({ email }) const optInCode = await getOptInCode(user.id) diff --git a/database/entity/0025-combine_transaction_tables2/Transaction.ts b/database/entity/0026-combine_transaction_tables2/Transaction.ts similarity index 100% rename from database/entity/0025-combine_transaction_tables2/Transaction.ts rename to database/entity/0026-combine_transaction_tables2/Transaction.ts diff --git a/database/entity/0027-clean_transaction_table/Transaction.ts b/database/entity/0027-clean_transaction_table/Transaction.ts new file mode 100644 index 000000000..e50f5d164 --- /dev/null +++ b/database/entity/0027-clean_transaction_table/Transaction.ts @@ -0,0 +1,59 @@ +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' + +@Entity('transactions') +export class Transaction extends BaseEntity { + @PrimaryGeneratedColumn('increment', { unsigned: true }) + id: number + + @Column({ name: 'user_id', unsigned: true, nullable: false }) + userId: number + + @Column({ name: 'type_id', unsigned: true, nullable: false }) + typeId: number + + @Column({ type: 'bigint', nullable: false }) + amount: BigInt + + @Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) + memo: string + + @Column({ + name: 'send_sender_final_balance', + type: 'bigint', + nullable: true, + default: null, + }) + sendSenderFinalBalance: BigInt | null + + @Column({ name: 'balance', type: 'bigint', default: 0 }) + balance: BigInt + + @Column({ + name: 'balance_date', + type: 'timestamp', + default: () => 'CURRENT_TIMESTAMP', + nullable: false, + }) + balanceDate: Date + + @Column({ name: 'creation_date', type: 'timestamp', nullable: true, default: null }) + creationDate: Date + + @Column({ + name: 'linked_user_id', + type: 'int', + unsigned: true, + nullable: true, + default: null, + }) + linkedUserId?: number | null + + @Column({ + name: 'linked_transaction_id', + type: 'int', + unsigned: true, + nullable: true, + default: null, + }) + linkedTransactionId?: number | null +} diff --git a/database/entity/Transaction.ts b/database/entity/Transaction.ts index 90871cb41..56c77c557 100644 --- a/database/entity/Transaction.ts +++ b/database/entity/Transaction.ts @@ -1 +1 @@ -export { Transaction } from './0028-clean_transaction_table/Transaction' +export { Transaction } from './0029-clean_transaction_table/Transaction' diff --git a/database/migrations/0025-emails_to_lower.ts b/database/migrations/0025-emails_to_lower.ts new file mode 100644 index 000000000..33f085e69 --- /dev/null +++ b/database/migrations/0025-emails_to_lower.ts @@ -0,0 +1,17 @@ +/* MIGRATION TO MAKE ALL EMAILS LOWERCASE + * + * Make all `email` values in `users` lowercase. + * This allows safe queries without any modificators + */ + +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('UPDATE `users` SET `email` = LOWER(`email`);') +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // This migration cannot be revered +} diff --git a/database/migrations/0025-combine_transaction_tables2.ts b/database/migrations/0026-combine_transaction_tables2.ts similarity index 100% rename from database/migrations/0025-combine_transaction_tables2.ts rename to database/migrations/0026-combine_transaction_tables2.ts diff --git a/database/migrations/0027-clean_transaction_table.ts b/database/migrations/0027-clean_transaction_table.ts new file mode 100644 index 000000000..b5a0e0e2e --- /dev/null +++ b/database/migrations/0027-clean_transaction_table.ts @@ -0,0 +1,73 @@ +/* MIGRATION TO CLEAN THE TRANSACTION TABLE + * + * Remove several unused fields or those with duplicate data + * and rename fields to a proper name in `transactions` . + * + * This migration has data loss + */ + +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // drop column `transaction_id`, it is not needed + await queryFn('ALTER TABLE `transactions` DROP COLUMN `transaction_id`;') + // drop column `received`, it is a duplicate of balance_date + await queryFn('ALTER TABLE `transactions` DROP COLUMN `received`;') + // drop column `tx_hash`, it is not needed + await queryFn('ALTER TABLE `transactions` DROP COLUMN `tx_hash`;') + // drop column `signature`, it is not needed + await queryFn('ALTER TABLE `transactions` DROP COLUMN `signature`;') + // drop column `pubkey`, it is not needed + await queryFn('ALTER TABLE `transactions` DROP COLUMN `pubkey`;') + // drop column `creation_ident_hash`, it is not needed + await queryFn('ALTER TABLE `transactions` DROP COLUMN `creation_ident_hash`;') + + // rename `transaction_type_id` to `type_id` + await queryFn('ALTER TABLE `transactions` RENAME COLUMN transaction_type_id TO type_id;') + // rename `linked_state_user_transaction_id` to `linked_transaction_id` + await queryFn( + 'ALTER TABLE `transactions` RENAME COLUMN linked_state_user_transaction_id TO linked_transaction_id;', + ) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // Not all data is recoverable here, some data is simulated, + // but we have data loss on: + // - transaction_id (we have data here, but its not the same as before) + // - tx_hash (null) + // - signature (null) + // - pubkey (null) + // - creation_ident_hash (null) + + await queryFn( + 'ALTER TABLE `transactions` RENAME COLUMN linked_transaction_id TO linked_state_user_transaction_id;', + ) + await queryFn('ALTER TABLE `transactions` RENAME COLUMN type_id TO transaction_type_id;') + await queryFn( + 'ALTER TABLE `transactions` ADD COLUMN `creation_ident_hash` binary(32) DEFAULT NULL AFTER `linked_state_user_transaction_id`;', + ) + await queryFn( + 'ALTER TABLE `transactions` ADD COLUMN `pubkey` binary(32) DEFAULT NULL AFTER `linked_state_user_transaction_id`;', + ) + await queryFn( + 'ALTER TABLE `transactions` ADD COLUMN `signature` binary(64) DEFAULT NULL AFTER `linked_state_user_transaction_id`;', + ) + await queryFn( + 'ALTER TABLE `transactions` ADD COLUMN `tx_hash` binary(48) DEFAULT NULL AFTER `linked_state_user_transaction_id`;', + ) + await queryFn( + 'ALTER TABLE `transactions` ADD COLUMN `received` timestamp NULL DEFAULT NULL AFTER `balance_date`;', + ) + await queryFn('UPDATE `transactions` SET `received` = `balance_date`;') + await queryFn( + 'ALTER TABLE `transactions` MODIFY COLUMN `received` timestamp NOT NULL DEFAULT current_timestamp();', + ) + await queryFn( + 'ALTER TABLE `transactions` ADD COLUMN `transaction_id` int(10) unsigned DEFAULT NULL AFTER `user_id`;', + ) + await queryFn('UPDATE `transactions` SET `transaction_id` = `id`;') + await queryFn( + 'ALTER TABLE `transactions` MODIFY COLUMN `transaction_id` int(10) unsigned NOT NULL;', + ) +} diff --git a/database/package.json b/database/package.json index 29f5ba511..d4b247082 100644 --- a/database/package.json +++ b/database/package.json @@ -1,6 +1,6 @@ { "name": "gradido-database", - "version": "1.6.5", + "version": "1.6.6", "description": "Gradido Database Tool to execute database migrations", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/database", diff --git a/database/src/index.ts b/database/src/index.ts index 4ae3d21b6..6e99ac582 100644 --- a/database/src/index.ts +++ b/database/src/index.ts @@ -6,6 +6,7 @@ import { CreatePeterLustigSeed } from './seeds/users/peter-lustig.admin.seed' import { CreateBibiBloxbergSeed } from './seeds/users/bibi-bloxberg.seed' import { CreateRaeuberHotzenplotzSeed } from './seeds/users/raeuber-hotzenplotz.seed' import { CreateBobBaumeisterSeed } from './seeds/users/bob-baumeister.seed' +import { CreateStephenHawkingSeed } from './seeds/users/stephen-hawking.seed' import { CreateGarrickOllivanderSeed } from './seeds/users/garrick-ollivander.seed' import { CreateUserSeed } from './seeds/create-user.seed' import { resetDB, pool, migration } from './helpers' @@ -44,6 +45,7 @@ const run = async (command: string) => { await runSeeder(CreateBibiBloxbergSeed) await runSeeder(CreateRaeuberHotzenplotzSeed) await runSeeder(CreateBobBaumeisterSeed) + await runSeeder(CreateStephenHawkingSeed) // eslint-disable-next-line prefer-spread Array.apply(null, Array(96)).forEach(async () => { await runSeeder(CreateUserSeed) diff --git a/database/src/seeds/users/stephen-hawking.seed.ts b/database/src/seeds/users/stephen-hawking.seed.ts new file mode 100644 index 000000000..07e129140 --- /dev/null +++ b/database/src/seeds/users/stephen-hawking.seed.ts @@ -0,0 +1,9 @@ +import { Factory, Seeder } from 'typeorm-seeding' +import { stephenHawking } from './stephen-hawking' +import { userSeeder } from '../helpers/user-helpers' + +export class CreateStephenHawkingSeed implements Seeder { + public async run(factory: Factory): Promise { + await userSeeder(factory, stephenHawking) + } +} diff --git a/database/src/seeds/users/stephen-hawking.ts b/database/src/seeds/users/stephen-hawking.ts new file mode 100644 index 000000000..9bfd83704 --- /dev/null +++ b/database/src/seeds/users/stephen-hawking.ts @@ -0,0 +1,23 @@ +import { UserInterface } from '../../interface/UserInterface' + +export const stephenHawking: UserInterface = { + email: 'stephen@hawking.uk', + firstName: 'Stephen', + lastName: 'Hawking', + // description: 'A Brief History of Time', + password: BigInt('18075098469449931746'), + pubKey: Buffer.from('19576a7aab8cd4ce683ed6735bba937d6bdbd08016568f730a385b6481241213', 'hex'), + privKey: Buffer.from( + '1d8ce9b5df086a713fee9eb562adc127073f3211a6214a54e53eb22c1249d49e1e94580ab00f25fd4b38808c1e31b41624ef627f277d21ef5d5717d4b81958f13dc2b257759caba07c6fdbc72f86ab0f', + 'hex', + ), + emailHash: Buffer.from('71d4ed7a25d2130d445d6451135eefbbdd96c3105dd297783590ced0bf3116fd', 'hex'), + createdAt: new Date('1942-01-08T09:17:52'), + deletedAt: new Date('2018-03-14T09:17:52'), + emailChecked: true, + language: 'en', + passphrase: + 'demise tree praise funny ignore despair vessel shop sorry try day peanut tongue toddler bone december inch chicken clump sheriff weasel rally check suggest ', + isAdmin: false, + addBalance: false, +} diff --git a/frontend/package.json b/frontend/package.json index a46e50f85..5629e0360 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "bootstrap-vue-gradido-wallet", - "version": "1.6.5", + "version": "1.6.6", "private": true, "scripts": { "start": "node run/server.js", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 23d637de4..b14f5c8a2 100755 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -40,67 +40,3 @@ export default { }, } - diff --git a/frontend/src/assets/scss/gradido.scss b/frontend/src/assets/scss/gradido.scss index e29538807..9bc3231c4 100644 --- a/frontend/src/assets/scss/gradido.scss +++ b/frontend/src/assets/scss/gradido.scss @@ -3,15 +3,13 @@ @import "~bootstrap/scss/functions"; - @import "custom/variables"; // @import "~bootstrap/scss/variables"; wird am // ende der custom/variables angehangen - -// Bootstrap (4.5.3) mixins - -@import "~bootstrap/scss/mixins"; +// Bootstrap (4.5.3) mixins +@import "~bootstrap/scss/mixins"; + // Bootstrap (4.5.3) components @import "~bootstrap/scss/alert"; @@ -20,11 +18,18 @@ @import "~bootstrap/scss/button-group"; @import "~bootstrap/scss/buttons"; @import "~bootstrap/scss/card"; +@import "~bootstrap/scss/carousel"; +@import "~bootstrap/scss/close"; +@import "~bootstrap/scss/code"; @import "~bootstrap/scss/custom-forms"; +@import "~bootstrap/scss/dropdown"; @import "~bootstrap/scss/forms"; +@import "~bootstrap/scss/functions"; @import "~bootstrap/scss/grid"; @import "~bootstrap/scss/input-group"; @import "~bootstrap/scss/list-group"; +@import "~bootstrap/scss/mixins"; +@import "~bootstrap/scss/modal"; @import "~bootstrap/scss/nav"; @import "~bootstrap/scss/navbar"; @import "~bootstrap/scss/pagination"; @@ -38,7 +43,99 @@ @import "~bootstrap/scss/type"; @import "~bootstrap/scss/utilities"; @import "~bootstrap/scss/variables"; - +@import "~bootstrap/scss/bootstrap-grid"; +@import "~bootstrap/scss/bootstrap-reboot"; +@import "~bootstrap/scss/bootstrap"; // Bootstrap-vue (2.21.1) scss -@import '~bootstrap-vue/src/index.scss'; \ No newline at end of file +@import '~bootstrap-vue/src/index.scss'; + + +.alert-success { + color: #155724; + background-color: #d4edda; + border-color: #c3e6cb; +} +.alert-danger { + color: #721c24; + background-color: #f8d7da; + border-color: #f5c6cb; +} + + +.b-toast-danger .toast .toast-header { + color: #721c24; + background-color: rgba(248,215,218,.85); + border-bottom-color: rgba(245,198,203,.85); +} +.b-toast-danger .toast .toast-body{ + background-color: rgba(252,237,238,.85); + border-color: rgba(245,198,203,.85); + color: #721c24; +} + +.b-toast-success .toast .toast-header { + color: #155724; + background-color: rgba(212,237,218,.58); + border-bottom-color: rgba(195,230,203,.85); +} +.b-toast-success .toast .toast-body{ + color: #155724; + background-color: rgba(212,237,218,.85); + border-bottom-color: rgba(195,230,203,.85); +} + + + .btn-primary pim { + background-color: #5a7b02; + border-color: #5e72e4; + } + a, + .copyright { + color: #5a7b02; + } + .font1_2em { + font-size: 1.2em; + } + .font2em { + font-size: 1.5em; + } + .gradido-global-color-text { + color: #3d443b; + } + .gradido-global-color-accent { + color: #047006; + } + .gradido-global-color-6e0a9c9e { + color: #000; + } + .gradido-global-color-2d0fb154 { + color: #047006; + } + .gradido-global-color-16efe88c { + color: #7ebc55; + } + .gradido-global-color-1939326 { + color: #f6fff6; + } + .gradido-global-color-9d79fc1 { + color: #047006; + } + .gradido-global-color-6347f4d { + color: #5a7b02; + } + .gradido-global-color-4fbc19a { + color: #014034; + } + .gradido-global-color-d341874 { + color: #b6d939; + } + .gradido-global-color-619d338 { + color: #8ebfb1; + } + .gradido-global-color-44819a9 { + color: #026873; + } + .gradido-global-color-gray { + color: #858383; + } \ No newline at end of file diff --git a/frontend/src/components/DecayInformation.vue b/frontend/src/components/DecayInformation.vue index 0daa45a18..9da5e4b2c 100644 --- a/frontend/src/components/DecayInformation.vue +++ b/frontend/src/components/DecayInformation.vue @@ -4,7 +4,7 @@ {{ decay ? ' − ' + $n(decay.balance, 'decimal') : '' }} -
+
@@ -56,17 +56,22 @@
{{ $t('decay.decay') }}
-
− {{ $n(decay.balance, 'decimal') }}
+
- {{ $n(decay.balance, 'decimal') }}
+
+ {{ $n(decay.balance + gddbalance, 'decimal') }} GDD - + {{ $n(decay.balance, 'decimal') }} GDD = + {{ $n(gddbalance, 'decimal') }} GDD +

- + {{ $t('decay.calculation_total') }} - +
{{ $t('decay.sent') }}
{{ $t('decay.received') }}
@@ -77,7 +82,7 @@
- +
{{ $t('decay.decay') }}
@@ -86,7 +91,7 @@
- +
{{ $t('decay.total') }}
@@ -109,6 +114,7 @@ export default { name: 'DecayInformation', props: { + gddbalance: { type: Number }, balance: { type: Number }, type: { type: String, default: '' }, decay: { diff --git a/frontend/src/components/Transaction.spec.js b/frontend/src/components/Transaction.spec.js index aaad023e0..ac80fefc8 100644 --- a/frontend/src/components/Transaction.spec.js +++ b/frontend/src/components/Transaction.spec.js @@ -31,8 +31,13 @@ describe('Transaction', () => { 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') + it('has a collapse icon bi-caret-down-square', () => { + expect(wrapper.find('div.gdt-transaction-list-item').findAll('svg').at(1).classes()).toEqual([ + 'bi-caret-down-square', + 'b-icon', + 'bi', + 'text-muted', + ]) }) describe('no valid GDT entry type', () => { diff --git a/frontend/src/components/Transaction.vue b/frontend/src/components/Transaction.vue index 1dcfee13a..649b81b4d 100644 --- a/frontend/src/components/Transaction.vue +++ b/frontend/src/components/Transaction.vue @@ -9,9 +9,10 @@
- - i - +
@@ -85,6 +86,16 @@ export default { gdt: { type: Number }, id: { type: Number }, }, + data() { + return { + collapseStatus: [], + } + }, + methods: { + getCollapseState(id) { + return this.collapseStatus.includes('gdt-collapse-' + id) + }, + }, computed: { collapseId() { return 'gdt-collapse-' + String(this.id) @@ -130,5 +141,14 @@ export default { } }, }, + mounted() { + this.$root.$on('bv::collapse::state', (collapseId, isJustShown) => { + if (isJustShown) { + this.collapseStatus.push(collapseId) + } else { + this.collapseStatus = this.collapseStatus.filter((id) => id !== collapseId) + } + }) + }, } diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index c833fb845..26ba8f489 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -75,6 +75,7 @@ export const transactionsQuery = gql` end duration } + firstTransaction } } } diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 0fdac973f..3bfad63e8 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -21,6 +21,7 @@ "switch-to-this-community": "zu dieser Gemeinschaft wechseln" }, "decay": { + "befor_startblock_transaction": "Diese Transaktion beinhaltet keine Vergänglichkeit.", "calculation_decay": "Berechnung der Vergänglichkeit", "calculation_total": "Berechnung der Gesamtsumme", "created": "Geschöpft", @@ -29,6 +30,7 @@ "decayStart": " - Startblock für Vergänglichkeit am: ", "decay_introduced": "Die Vergänglichkeit wurde eingeführt am ", "decay_since_last_transaction": "Vergänglichkeit seit der letzten Transaktion", + "first_transaction": "Die erste Transaktion beinhaltet keine Vergänglichkeit.", "hours": "Stunden", "last_transaction": "Letzte Transaktion", "minutes": "Minuten", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index fdbf37bd7..b06030947 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -21,6 +21,7 @@ "switch-to-this-community": "Switch to this community" }, "decay": { + "befor_startblock_transaction": "This transaction does not include decay.", "calculation_decay": "Calculation of Decay", "calculation_total": "Calculation of the total Amount", "created": "Created", @@ -29,6 +30,7 @@ "decayStart": " - Starting block for decay at: ", "decay_introduced": "Decay was introduced on", "decay_since_last_transaction": "Decay since the last transaction", + "first_transaction": "The first transaction does not include decay.", "hours": "Hours", "last_transaction": "Last transaction:", "minutes": "Minutes", diff --git a/frontend/src/mixins/toaster.js b/frontend/src/mixins/toaster.js index 704eaf1a7..4464a2cc9 100644 --- a/frontend/src/mixins/toaster.js +++ b/frontend/src/mixins/toaster.js @@ -16,7 +16,7 @@ export const toasters = { message = message.replace(/^GraphQL error: /, '') this.$bvToast.toast(message, { autoHideDelay: 5000, - appendToast: false, + appendToast: true, solid: true, toaster: 'b-toaster-top-right', headerClass: 'gdd-toaster-title', diff --git a/frontend/src/views/Pages/AccountOverview.vue b/frontend/src/views/Pages/AccountOverview.vue index b62481806..c0ba55155 100644 --- a/frontend/src/views/Pages/AccountOverview.vue +++ b/frontend/src/views/Pages/AccountOverview.vue @@ -15,6 +15,7 @@
{ decay: { balance: '1.5' }, }, { - balance: '1.07', + balance: 1.07, type: 'decay', }, ], @@ -135,12 +135,31 @@ describe('GddTransactionList', () => { transaction = wrapper.findAll('div.gdd-transaction-list-item').at(0) }) + it('has a bi-caret-down-square icon', () => { + expect(transaction.findAll('svg').at(0).classes()).toEqual([ + 'bi-caret-down-square', + 'b-icon', + 'bi', + 'text-muted', + ]) + }) + + // it('transaction is clicked', async () => { + // await transaction.trigger('click') + // expect(transaction.findAll('svg').at(0).classes()).toEqual([ + // 'bi-caret-up-square', + // 'b-icon', + // 'bi', + // 'text-muted', + // ]) + // }) + it('has a bi-arrow-left-circle icon', () => { - expect(transaction.find('svg').classes()).toContain('bi-arrow-left-circle') + expect(transaction.findAll('svg').at(1).classes()).toContain('bi-arrow-left-circle') }) it('has text-danger color', () => { - expect(transaction.find('svg').classes()).toContain('text-danger') + expect(transaction.findAll('svg').at(1).classes()).toContain('text-danger') }) it('has a minus operator', () => { @@ -186,12 +205,33 @@ describe('GddTransactionList', () => { transaction = wrapper.findAll('div.gdd-transaction-list-item').at(1) }) + it('has a bi-caret-down-square icon', () => { + expect(transaction.findAll('svg').at(0).classes()).toEqual([ + 'bi-caret-down-square', + 'b-icon', + 'bi', + 'text-muted', + ]) + }) + + // it('transaction is clicked', async () => { + // await transaction.trigger('click') + // expect(transaction.findAll('svg').at(0).classes()).toEqual([ + // 'bi-caret-up-square', + // 'b-icon', + // 'bi', + // 'text-muted', + // ]) + // }) + it('has a bi-gift icon', () => { - expect(transaction.find('svg').classes()).toContain('bi-gift') + expect(transaction.findAll('svg').at(1).classes()).toContain('bi-gift') }) it('has gradido-global-color-accent color', () => { - expect(transaction.find('svg').classes()).toContain('gradido-global-color-accent') + expect(transaction.findAll('svg').at(1).classes()).toContain( + 'gradido-global-color-accent', + ) }) it('has a plus operator', () => { @@ -225,12 +265,33 @@ describe('GddTransactionList', () => { transaction = wrapper.findAll('div.gdd-transaction-list-item').at(2) }) + it('has a bi-caret-down-square icon', () => { + expect(transaction.findAll('svg').at(0).classes()).toEqual([ + 'bi-caret-down-square', + 'b-icon', + 'bi', + 'text-muted', + ]) + }) + + // it('transaction is clicked', async () => { + // await transaction.trigger('click') + // expect(transaction.findAll('svg').at(0).classes()).toEqual([ + // 'bi-caret-up-square', + // 'b-icon', + // 'bi', + // 'text-muted', + // ]) + // }) + it('has a bi-arrow-right-circle icon', () => { - expect(transaction.find('svg').classes()).toContain('bi-arrow-right-circle') + expect(transaction.findAll('svg').at(1).classes()).toContain('bi-arrow-right-circle') }) it('has gradido-global-color-accent color', () => { - expect(transaction.find('svg').classes()).toContain('gradido-global-color-accent') + expect(transaction.findAll('svg').at(1).classes()).toContain( + 'gradido-global-color-accent', + ) }) it('has a plus operator', () => { @@ -276,12 +337,31 @@ describe('GddTransactionList', () => { transaction = wrapper.findAll('div.gdd-transaction-list-item').at(3) }) + it('has a bi-caret-down-square icon', () => { + expect(transaction.findAll('svg').at(0).classes()).toEqual([ + 'bi-caret-down-square', + 'b-icon', + 'bi', + 'text-muted', + ]) + }) + + // it('transaction is clicked', async () => { + // await transaction.trigger('click') + // expect(transaction.findAll('svg').at(0).classes()).toEqual([ + // 'bi-caret-up-square', + // 'b-icon', + // 'bi', + // 'text-muted', + // ]) + // }) + it('has a bi-droplet-half icon', () => { - expect(transaction.find('svg').classes()).toContain('bi-droplet-half') + expect(transaction.findAll('svg').at(1).classes()).toContain('bi-droplet-half') }) it('has gradido-global-color-gray color', () => { - expect(transaction.find('svg').classes()).toContain('gradido-global-color-gray') + expect(transaction.findAll('svg').at(1).classes()).toContain('gradido-global-color-gray') }) it('has a minus operator', () => { diff --git a/frontend/src/views/Pages/AccountOverview/GddTransactionList.vue b/frontend/src/views/Pages/AccountOverview/GddTransactionList.vue index 4e2df58d1..db24e90ba 100644 --- a/frontend/src/views/Pages/AccountOverview/GddTransactionList.vue +++ b/frontend/src/views/Pages/AccountOverview/GddTransactionList.vue @@ -2,35 +2,44 @@
- + {{ $t('error.no-transactionlist') }}
- + {{ $t('error.empty-transactionlist') }}
-
- - i - +
+
-
@@ -112,9 +121,13 @@
- - -
+ + +
+
+ {{ $t('decay.first_transaction') }} +
+ +
+ {{ $t('decay.befor_startblock_transaction') }} +
+
+ +
@@ -161,9 +198,11 @@ export default { data() { return { currentPage: 1, + collapseStatus: [], } }, props: { + gddbalance: { type: Number }, transactions: { default: () => [] }, pageSize: { type: Number, default: 25 }, timestamp: { type: Number, default: 0 }, @@ -191,6 +230,18 @@ export default { throwError(msg) { throw new Error(msg) }, + getCollapseState(transactionId) { + return this.collapseStatus.includes('decay-' + transactionId) + }, + }, + mounted() { + this.$root.$on('bv::collapse::state', (collapseId, isJustShown) => { + if (isJustShown) { + this.collapseStatus.push(collapseId) + } else { + this.collapseStatus = this.collapseStatus.filter((id) => id !== collapseId) + } + }) }, watch: { currentPage() { diff --git a/frontend/src/views/Pages/Register.vue b/frontend/src/views/Pages/Register.vue index 8d95c8197..03012cf34 100755 --- a/frontend/src/views/Pages/Register.vue +++ b/frontend/src/views/Pages/Register.vue @@ -108,7 +108,7 @@ v-if="showError" show dismissible - variant="warning" + variant="danger" @dismissed="closeAlert" > diff --git a/frontend/src/views/Pages/UserProfileTransactionList.vue b/frontend/src/views/Pages/UserProfileTransactionList.vue index 383e908b6..494819f05 100644 --- a/frontend/src/views/Pages/UserProfileTransactionList.vue +++ b/frontend/src/views/Pages/UserProfileTransactionList.vue @@ -5,6 +5,7 @@

{{ $t('transaction.gdd-text') }}