mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into login_build_alpine
This commit is contained in:
commit
06c420dc2c
121
CHANGELOG.md
121
CHANGELOG.md
@ -4,8 +4,129 @@ 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.0.1](https://github.com/gradido/gradido/compare/0.9.4...1.0.1)
|
||||
|
||||
- Send button only click [`#427`](https://github.com/gradido/gradido/pull/427)
|
||||
- use new function for balance overview in old frontend, update balance… [`#422`](https://github.com/gradido/gradido/pull/422)
|
||||
- thx.vue coloured background removed. design adapted to app [`#426`](https://github.com/gradido/gradido/pull/426)
|
||||
- translation password rules in Register.vue and ResetPasswort.vue fixed [`#424`](https://github.com/gradido/gradido/pull/424)
|
||||
- 06x style [`#419`](https://github.com/gradido/gradido/pull/419)
|
||||
- feat: Dash is Shown When Balance is Loading [`#396`](https://github.com/gradido/gradido/pull/396)
|
||||
- refactor: Split GddSend into Components [`#415`](https://github.com/gradido/gradido/pull/415)
|
||||
- fix: Set Maximum Transactions Loaded to 1000 [`#395`](https://github.com/gradido/gradido/pull/395)
|
||||
- BUG : preRELEASE : thx transaction false [`#394`](https://github.com/gradido/gradido/pull/394)
|
||||
- feat: Validation of Input Fields of GddSend [`#386`](https://github.com/gradido/gradido/pull/386)
|
||||
- add validation, check if user has tried to send themself gradidos [`#277`](https://github.com/gradido/gradido/pull/277)
|
||||
- fix link generation [`#347`](https://github.com/gradido/gradido/pull/347)
|
||||
- Community start decay [`#387`](https://github.com/gradido/gradido/pull/387)
|
||||
- transaction error message, translations [`#388`](https://github.com/gradido/gradido/pull/388)
|
||||
- docu: locales schöpfen-mysql befehl [`#392`](https://github.com/gradido/gradido/pull/392)
|
||||
- Fix: QR Scanner Hide [`#380`](https://github.com/gradido/gradido/pull/380)
|
||||
- change design- dark-blue of text-ligth [`#381`](https://github.com/gradido/gradido/pull/381)
|
||||
- spelling & translation [`#385`](https://github.com/gradido/gradido/pull/385)
|
||||
- 350 6 login [`#383`](https://github.com/gradido/gradido/pull/383)
|
||||
- fix: breakout error [`#375`](https://github.com/gradido/gradido/pull/375)
|
||||
- 233-Support-Button fix, and col error fix [`#343`](https://github.com/gradido/gradido/pull/343)
|
||||
- fix: membersarea open in a new tap [`#370`](https://github.com/gradido/gradido/pull/370)
|
||||
- 00x table footer componente [`#345`](https://github.com/gradido/gradido/pull/345)
|
||||
- clickevent from icon to button [`#364`](https://github.com/gradido/gradido/pull/364)
|
||||
- 404 link to login page fix [`#366`](https://github.com/gradido/gradido/pull/366)
|
||||
- bug: session_id vs sessionId [`#365`](https://github.com/gradido/gradido/pull/365)
|
||||
- eslint rule standard [`#344`](https://github.com/gradido/gradido/pull/344)
|
||||
- don't show decays smaller than 0,01 GDD [`#329`](https://github.com/gradido/gradido/pull/329)
|
||||
- 338 - mt-5 margin top 5 eingebunden [`#341`](https://github.com/gradido/gradido/pull/341)
|
||||
- feat: Update Transactions When GddTable Is Rendered [`#339`](https://github.com/gradido/gradido/pull/339)
|
||||
- my profile auskommentiert [`#337`](https://github.com/gradido/gradido/pull/337)
|
||||
- give balance as float value in GDD (not longer GDD cent) [`#273`](https://github.com/gradido/gradido/pull/273)
|
||||
- fix error with password reset email [`#276`](https://github.com/gradido/gradido/pull/276)
|
||||
- transaction.show_all in en.json hinzugefügt [`#335`](https://github.com/gradido/gradido/pull/335)
|
||||
- refactor: Add Paramerts to ListTransactions API Call [`#332`](https://github.com/gradido/gradido/pull/332)
|
||||
- css abstände vom rand in mobilen style [`#272`](https://github.com/gradido/gradido/pull/272)
|
||||
- error messages are displayed [`#304`](https://github.com/gradido/gradido/pull/304)
|
||||
- cancel to reset, form rest event added [`#334`](https://github.com/gradido/gradido/pull/334)
|
||||
- remove from error messages because its no longer exist [`#330`](https://github.com/gradido/gradido/pull/330)
|
||||
- xx deleted [`#333`](https://github.com/gradido/gradido/pull/333)
|
||||
- fix bug on Login group add host [`#274`](https://github.com/gradido/gradido/pull/274)
|
||||
- transactionslist load and icon [`#324`](https://github.com/gradido/gradido/pull/324)
|
||||
- THX changed to Thank you [`#305`](https://github.com/gradido/gradido/pull/305)
|
||||
- fix_bug_template [`#284`](https://github.com/gradido/gradido/pull/284)
|
||||
- feat: Restructure Overview [`#271`](https://github.com/gradido/gradido/pull/271)
|
||||
- fix: Dynamic Balance in User Profile [`#278`](https://github.com/gradido/gradido/pull/278)
|
||||
- refactor: Test and Clean Up Store [`#270`](https://github.com/gradido/gradido/pull/270)
|
||||
- remove links to not work [`#267`](https://github.com/gradido/gradido/pull/267)
|
||||
- change order of session_id [`#269`](https://github.com/gradido/gradido/pull/269)
|
||||
- bug: Dynamic Balance [`#260`](https://github.com/gradido/gradido/pull/260)
|
||||
- Fix problems with transactions in docker environment [`#261`](https://github.com/gradido/gradido/pull/261)
|
||||
- update skeema call to allow also for unsafe db updates [`#250`](https://github.com/gradido/gradido/pull/250)
|
||||
- turn registration on and off [`#266`](https://github.com/gradido/gradido/pull/266)
|
||||
- 243 vue loader component - varante 2 [`#257`](https://github.com/gradido/gradido/pull/257)
|
||||
- fix_issue_templates [`#262`](https://github.com/gradido/gradido/pull/262)
|
||||
- fix_nginx_docker [`#253`](https://github.com/gradido/gradido/pull/253)
|
||||
- 13_coverage [`#255`](https://github.com/gradido/gradido/pull/255)
|
||||
- add language as fields which will be returned with user-object [`#244`](https://github.com/gradido/gradido/pull/244)
|
||||
- add short description for target date in creation transaction [`#252`](https://github.com/gradido/gradido/pull/252)
|
||||
- fix error "Integrity constraint violation: 1052 Column 'id' in where … [`#251`](https://github.com/gradido/gradido/pull/251)
|
||||
- Clicks on button [`#246`](https://github.com/gradido/gradido/pull/246)
|
||||
- Change css [`#231`](https://github.com/gradido/gradido/pull/231)
|
||||
- feat: Reset Password [`#212`](https://github.com/gradido/gradido/pull/212)
|
||||
- fix bug #221 [`#228`](https://github.com/gradido/gradido/pull/228)
|
||||
- fix empty reply by empty group_id [`#227`](https://github.com/gradido/gradido/pull/227)
|
||||
- Bugfix 22 04 21 [`#226`](https://github.com/gradido/gradido/pull/226)
|
||||
- Rollback use prebuild dependencies [`#225`](https://github.com/gradido/gradido/pull/225)
|
||||
- Docu [`#199`](https://github.com/gradido/gradido/pull/199)
|
||||
- update login-server build [`#222`](https://github.com/gradido/gradido/pull/222)
|
||||
- Login add language [`#220`](https://github.com/gradido/gradido/pull/220)
|
||||
- User Object on Json Login [`#219`](https://github.com/gradido/gradido/pull/219)
|
||||
- refactor: Remove loginAPI Call from Store [`#215`](https://github.com/gradido/gradido/pull/215)
|
||||
- fix: Remove Rules for Password on Login [`#214`](https://github.com/gradido/gradido/pull/214)
|
||||
- Community 15 04 2021 [`#198`](https://github.com/gradido/gradido/pull/198)
|
||||
- refactor: Remove Right Menu [`#204`](https://github.com/gradido/gradido/pull/204)
|
||||
- feat: Raise Frontend Test Coverage to 12% [`#206`](https://github.com/gradido/gradido/pull/206)
|
||||
- refactor: Remove Cookies [`#202`](https://github.com/gradido/gradido/pull/202)
|
||||
- fix_docker_compose [`#205`](https://github.com/gradido/gradido/pull/205)
|
||||
- 62 pwd reset [`#203`](https://github.com/gradido/gradido/pull/203)
|
||||
- workflows_refactor [`#200`](https://github.com/gradido/gradido/pull/200)
|
||||
- feat: Link to Whitepaper in Content-Footer [`#196`](https://github.com/gradido/gradido/pull/196)
|
||||
- update code which produce error which last fix (._.); [`#197`](https://github.com/gradido/gradido/pull/197)
|
||||
- refactor: Redirects and Misuse of Children in Router [`#194`](https://github.com/gradido/gradido/pull/194)
|
||||
- fix: Gradido-Akademie in Footer Links to gradido.net [`#170`](https://github.com/gradido/gradido/pull/170)
|
||||
- fix register [`#160`](https://github.com/gradido/gradido/pull/160)
|
||||
- Login 14.04.21 [`#175`](https://github.com/gradido/gradido/pull/175)
|
||||
- coverage_no_report [`#176`](https://github.com/gradido/gradido/pull/176)
|
||||
- Community 14.04.21 [`#174`](https://github.com/gradido/gradido/pull/174)
|
||||
- feat: Add Coverage Check To GitHub Workflow [`#158`](https://github.com/gradido/gradido/pull/158)
|
||||
- Stage2 [`#49`](https://github.com/gradido/gradido/pull/49)
|
||||
- feat: Unit Test for KontoOverview [`#169`](https://github.com/gradido/gradido/pull/169)
|
||||
- fix: Remove Hashtag From Route [`#167`](https://github.com/gradido/gradido/pull/167)
|
||||
- documentation for reset password [`#166`](https://github.com/gradido/gradido/pull/166)
|
||||
- 90 show release version in frontend [`#153`](https://github.com/gradido/gradido/pull/153)
|
||||
- docu frontend menu page structur [`#159`](https://github.com/gradido/gradido/pull/159)
|
||||
- userstorry_button.txt example [`#157`](https://github.com/gradido/gradido/pull/157)
|
||||
- fix getBalance API call [`#147`](https://github.com/gradido/gradido/pull/147)
|
||||
- Locale clear list merge master [`#119`](https://github.com/gradido/gradido/pull/119)
|
||||
- fix-125-link-to-community [`#152`](https://github.com/gradido/gradido/pull/152)
|
||||
- feat: Test Dashboard Layout [`#154`](https://github.com/gradido/gradido/pull/154)
|
||||
- feat: Activate Coverage Report For Unit Tests In Frontend [`#156`](https://github.com/gradido/gradido/pull/156)
|
||||
- Docu [`#120`](https://github.com/gradido/gradido/pull/120)
|
||||
- Fix compose bug [`#138`](https://github.com/gradido/gradido/pull/138)
|
||||
- feat: Test Login Form [`#113`](https://github.com/gradido/gradido/pull/113)
|
||||
- at last, fix email-bug [`#134`](https://github.com/gradido/gradido/pull/134)
|
||||
- Api password reset [`#82`](https://github.com/gradido/gradido/pull/82)
|
||||
- Optimize login server build [`#101`](https://github.com/gradido/gradido/pull/101)
|
||||
- markdown of login server api [`#111`](https://github.com/gradido/gradido/pull/111)
|
||||
- Fix lineendings [`#112`](https://github.com/gradido/gradido/pull/112)
|
||||
- Background color change [`#117`](https://github.com/gradido/gradido/pull/117)
|
||||
- Delete unused files [`#116`](https://github.com/gradido/gradido/pull/116)
|
||||
- store aufräumen teil 1 [`#115`](https://github.com/gradido/gradido/pull/115)
|
||||
- add migrations table for automatic table data migration [`40a9a8c`](https://github.com/gradido/gradido/commit/40a9a8c2b587f5bef0fcc54136ed7bd13dd91b2b)
|
||||
- update yarn.lock after running yarn install [`7f38c80`](https://github.com/gradido/gradido/commit/7f38c801213ad886e9d34a8d43b00ae423f5f2a0)
|
||||
- use new function for balance overview in old frontend, update balance in session on every php-request [`97c570c`](https://github.com/gradido/gradido/commit/97c570c08cc51ed17a69eb8be8d987f95f3c2ce0)
|
||||
|
||||
#### [0.9.4](https://github.com/gradido/gradido/compare/0.9.3...0.9.4)
|
||||
|
||||
> 30 March 2021
|
||||
|
||||
- Vue with nginx [`#84`](https://github.com/gradido/gradido/pull/84)
|
||||
- Build on run [`#103`](https://github.com/gradido/gradido/pull/103)
|
||||
- update debug docker to use dependencies container pushed to docker hub [`1f002f4`](https://github.com/gradido/gradido/commit/1f002f4ed0b12d4b2bf63efceabe546d0c5b58ea)
|
||||
- removed email tasks complete [`8a143be`](https://github.com/gradido/gradido/commit/8a143be8423d7bd894d4f512848895df8b9694b0)
|
||||
|
||||
@ -21,7 +21,7 @@ use Cake\Routing\Router;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\I18n\Time;
|
||||
use Cake\I18n\I18n;
|
||||
use Cake\I18n\FrozenTime;
|
||||
|
||||
/**
|
||||
* Application Controller
|
||||
@ -174,6 +174,7 @@ class AppController extends Controller
|
||||
protected function requestLogin($sessionId = 0, $redirect = true)
|
||||
{
|
||||
$this->checkForMigration($redirect);
|
||||
$stateBalancesTable = TableRegistry::getTableLocator()->get('StateBalances');
|
||||
$session = $this->getRequest()->getSession();
|
||||
// check login
|
||||
// disable encryption for cookies
|
||||
@ -206,12 +207,15 @@ class AppController extends Controller
|
||||
$transactionPendings = $session->read('Transactions.pending');
|
||||
$transactionExecutings = $session->read('Transactions.executing');
|
||||
$transaction_can_signed = $session->read('Transactions.can_signed');
|
||||
|
||||
|
||||
|
||||
if ($session->read('session_id') != $session_id ||
|
||||
( $userStored && (!isset($userStored['id']) || !$userStored['email_checked'])) ||
|
||||
intval($transactionPendings) > 0 ||
|
||||
intval($transactionExecutings) > 0 ||
|
||||
intval($transaction_can_signed > 0)) {
|
||||
intval($transaction_can_signed > 0))
|
||||
{
|
||||
$http = new Client();
|
||||
|
||||
try {
|
||||
@ -242,6 +246,7 @@ class AppController extends Controller
|
||||
$session->write('Transactions.can_signed', $transaction_can_signed);
|
||||
$session->write('session_id', $session_id);
|
||||
$stateUserTable = TableRegistry::getTableLocator()->get('StateUsers');
|
||||
|
||||
|
||||
if (isset($json['user']['public_hex']) && $json['user']['public_hex'] != '') {
|
||||
$public_key_bin = hex2bin($json['user']['public_hex']);
|
||||
@ -270,11 +275,6 @@ class AppController extends Controller
|
||||
$this->Flash->error(__('error updating state user ' . json_encode($stateUser->errors())));
|
||||
}
|
||||
}
|
||||
//var_dump($stateUser);
|
||||
if (count($stateUser->state_balances) > 0) {
|
||||
|
||||
$session->write('StateUser.balance', $stateUser->state_balances[0]->decay);
|
||||
}
|
||||
$session->write('StateUser.id', $stateUser->id);
|
||||
//echo $stateUser['id'];
|
||||
} else {
|
||||
@ -326,6 +326,11 @@ class AppController extends Controller
|
||||
//continue;
|
||||
}
|
||||
}
|
||||
$state_balance = $stateBalancesTable->find()->where(['state_user_id' => $session->read('StateUser.id')])->first();
|
||||
if ($state_balance) {
|
||||
$now = new FrozenTime;
|
||||
$session->write('StateUser.balance', $stateBalancesTable->calculateDecay($state_balance->amount, $state_balance->record_date, $now));
|
||||
}
|
||||
} else {
|
||||
// no login
|
||||
//die("no login");
|
||||
|
||||
@ -360,7 +360,7 @@ class AppRequestsController extends AppController
|
||||
$body['decay'] = 0.0;
|
||||
} else {
|
||||
$body['balance'] = $state_balance->amount;
|
||||
$body['decay'] = $state_balance->partDecay($now);
|
||||
$body['decay'] = $stateBalancesTable->calculateDecay($state_balance->amount, $state_balance->record_date, $now);
|
||||
}
|
||||
|
||||
$this->set('body', $body);
|
||||
|
||||
@ -64,6 +64,7 @@ class MigrationsController extends AppController
|
||||
$commands = [
|
||||
[$blockchainTypesTable, 'fillWithDefault'],
|
||||
[$transactionTypesTable, 'fillWithDefault'],
|
||||
[$stateBalancesTable, 'truncate'],
|
||||
[$transactionsTable, 'fillStateUserTransactions'],
|
||||
[$stateBalancesTable, 'updateAllBalances']
|
||||
];
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\I18n\Time;
|
||||
use Cake\I18n\FrozenTime;
|
||||
|
||||
use Model\Navigation\NaviHierarchy;
|
||||
use Model\Navigation\NaviHierarchyEntry;
|
||||
@ -65,6 +65,7 @@ class StateBalancesController extends AppController
|
||||
if($update_balance_result['success'] !== true) {
|
||||
$this->addAdminError('StateBalances', 'overview', $update_balance_result, $user['id']);
|
||||
}
|
||||
|
||||
// sendRequestGDT
|
||||
// listPerEmailApi
|
||||
|
||||
@ -84,200 +85,68 @@ class StateBalancesController extends AppController
|
||||
//}
|
||||
//
|
||||
//
|
||||
$stateBalancesTable = TableRegistry::getTableLocator()->get('StateBalances');
|
||||
$stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
|
||||
|
||||
$creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations');
|
||||
$creationTransactions = $creationsTable
|
||||
->find('all')
|
||||
->where(['state_user_id' => $user['id']])
|
||||
->contain(['Transactions']);
|
||||
|
||||
$transferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins');
|
||||
$transferTransactions = $transferTable
|
||||
->find('all')
|
||||
->where(['OR' => ['state_user_id' => $user['id'], 'receiver_user_id' => $user['id']]])
|
||||
->contain(['Transactions']);
|
||||
|
||||
$involvedUserIds = [];
|
||||
|
||||
foreach ($transferTransactions as $sendCoins) {
|
||||
//var_dump($sendCoins);
|
||||
if ($sendCoins->state_user_id != $user['id']) {
|
||||
array_push($involvedUserIds, intval($sendCoins->state_user_id));
|
||||
} elseif ($sendCoins->receiver_user_id != $user['id']) {
|
||||
array_push($involvedUserIds, intval($sendCoins->receiver_user_id));
|
||||
}
|
||||
}
|
||||
|
||||
/*echo "state user from sendCoins: $sendCoins->state_user_id<br>";
|
||||
echo "receiver user from sendCoins: $sendCoins->receiver_user_id<br>";
|
||||
echo "user id from logged in user: ".$user['id']. '<br>';
|
||||
*/
|
||||
//var_dump($involvedUserIds);
|
||||
// exchange key with values and drop duplicates
|
||||
$involvedUser_temp = array_flip($involvedUserIds);
|
||||
// exchange back
|
||||
$involvedUserIds = array_flip($involvedUser_temp);
|
||||
$userTable = TableRegistry::getTableLocator()->get('StateUsers');
|
||||
$involvedUser = $userTable->find('all', [
|
||||
'contain' => false,
|
||||
'where' => ['id IN' => $involvedUserIds],
|
||||
'fields' => ['id', 'first_name', 'last_name', 'email']
|
||||
]);
|
||||
//var_dump($involvedUser->toArray());
|
||||
$involvedUserIndices = [];
|
||||
foreach ($involvedUser as $involvedUser) {
|
||||
$involvedUserIndices[$involvedUser->id] = $involvedUser;
|
||||
}
|
||||
|
||||
// sender or receiver when user has sended money
|
||||
// group name if creation
|
||||
// type: gesendet / empfangen / geschöpft
|
||||
// transaktion nr / id
|
||||
// date
|
||||
// balance
|
||||
|
||||
$transactions = [];
|
||||
foreach ($creationTransactions as $creation) {
|
||||
//var_dump($creation);
|
||||
array_push($transactions, [
|
||||
'name' => 'Gradido Akademie',
|
||||
'type' => 'creation',
|
||||
'transaction_id' => $creation->transaction_id,
|
||||
'date' => $creation->target_date,
|
||||
'balance' => $creation->amount,
|
||||
'memo' => $creation->transaction->memo
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($transferTransactions as $sendCoins) {
|
||||
$type = '';
|
||||
$otherUser = null;
|
||||
$other_user_public = '';
|
||||
if ($sendCoins->state_user_id == $user['id']) {
|
||||
$type = 'send';
|
||||
|
||||
if(isset($involvedUserIndices[$sendCoins->receiver_user_id])) {
|
||||
$otherUser = $involvedUserIndices[$sendCoins->receiver_user_id];
|
||||
}
|
||||
$other_user_public = bin2hex(stream_get_contents($sendCoins->receiver_public_key));
|
||||
} else if ($sendCoins->receiver_user_id == $user['id']) {
|
||||
$type = 'receive';
|
||||
if(isset($involvedUserIndices[$sendCoins->state_user_id])) {
|
||||
$otherUser = $involvedUserIndices[$sendCoins->state_user_id];
|
||||
}
|
||||
if($sendCoins->sender_public_key) {
|
||||
$other_user_public = bin2hex(stream_get_contents($sendCoins->sender_public_key));
|
||||
}
|
||||
}
|
||||
if(null == $otherUser) {
|
||||
$otherUser = $this->StateBalances->StateUsers->newEntity();
|
||||
}
|
||||
array_push($transactions, [
|
||||
'name' => $otherUser->first_name . ' ' . $otherUser->last_name,
|
||||
'email' => $otherUser->email,
|
||||
'type' => $type,
|
||||
'transaction_id' => $sendCoins->transaction_id,
|
||||
'date' => $sendCoins->transaction->received,
|
||||
'balance' => $sendCoins->amount,
|
||||
'memo' => $sendCoins->transaction->memo,
|
||||
'pubkey' => $other_user_public
|
||||
]);
|
||||
}
|
||||
uasort($transactions, array($this, 'sortTransactions'));
|
||||
$transactionsTable = TableRegistry::getTableLocator()->get('Transactions');
|
||||
|
||||
// add decay transactions
|
||||
$month_start_state_balance = null;
|
||||
$current_state_balance = null;
|
||||
$cursor = 0;
|
||||
$transactions_reversed = array_reverse($transactions);
|
||||
$decay_transactions = [];
|
||||
$maxI = count($transactions_reversed);
|
||||
|
||||
$stateBalancesTable->updateBalances($user['id']);
|
||||
|
||||
foreach($transactions_reversed as $i => $transaction) {
|
||||
if(!isset($transaction['transaction_id'])) {
|
||||
//echo "missing transaction<br>";
|
||||
continue;
|
||||
}
|
||||
$transaction_id = $transaction['transaction_id'];
|
||||
//echo "transaction id: $transaction_id <br>";
|
||||
$decay_transaction = NULL;
|
||||
$state_balance = $this->StateBalances->newEntity();
|
||||
|
||||
if($i > 0 && isset($transactions_reversed[$i-1]['transaction_id'])) {
|
||||
$prev_transaction = $transactions_reversed[$i-1];
|
||||
$stateUserTransactions = $stateUserTransactionsTable
|
||||
->find()
|
||||
->where([
|
||||
'transaction_id IN' => [$transaction_id, $prev_transaction['transaction_id']],
|
||||
'state_user_id' => $user['id']
|
||||
])
|
||||
->order(['balance_date ASC'])
|
||||
->toArray();
|
||||
|
||||
$prev = $stateUserTransactions[0];
|
||||
if($prev->balance > 0) {
|
||||
// var_dump($stateUserTransactions);
|
||||
$current = $stateUserTransactions[1];
|
||||
//echo "decay between " . $prev->transaction_id . " and " . $current->transaction_id . "<br>";
|
||||
$interval = $current->balance_date->diff($prev->balance_date);
|
||||
$state_balance->amount = $prev->balance;
|
||||
$state_balance->record_date = $prev->balance_date;
|
||||
$diff_amount = $state_balance->partDecay($current->balance_date);
|
||||
|
||||
//echo $interval->format('%R%a days');
|
||||
//echo "prev balance: " . $prev->balance . ", diff_amount: $diff_amount, summe: " . (-intval($prev->balance - $diff_amount)) . "<br>";
|
||||
$decay_transaction = [
|
||||
'type' => 'decay',
|
||||
'balance' => -intval($prev->balance - $diff_amount),
|
||||
'decay_duration' => $interval->format('%a days, %H hours, %I minutes, %S seconds'),
|
||||
'memo' => ''
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if($decay_transaction) {
|
||||
$decay_transactions[] = $decay_transaction;
|
||||
//array_splice($transactions_reversed, $i + $cursor, 0, [$decay_transaction]);
|
||||
//$cursor++;
|
||||
}
|
||||
if($i == $maxI-1) {
|
||||
$stateUserTransaction = $stateUserTransactionsTable
|
||||
->find()
|
||||
->where(['transaction_id' => $transaction_id, 'state_user_id' => $user['id']])
|
||||
->order(['transaction_id ASC'])->first();
|
||||
//var_dump($stateUserTransaction);
|
||||
$state_balance->amount = $stateUserTransaction->balance;
|
||||
$state_balance->record_date = $stateUserTransaction->balance_date;
|
||||
$decay_transactions[] = [
|
||||
//$transactions_reversed[] = [
|
||||
'type' => 'decay',
|
||||
'balance' => -intval($stateUserTransaction->balance - $state_balance->decay),
|
||||
'decay_duration' => $stateUserTransaction->balance_date->timeAgoInWords(),
|
||||
'memo' => ''
|
||||
];
|
||||
|
||||
}
|
||||
$gdtSum = 0;
|
||||
$gdtEntries = $this->JsonRequestClient->sendRequestGDT(['email' => $user['email']], 'GdtEntries' . DS . 'sumPerEmailApi');
|
||||
|
||||
if('success' == $gdtEntries['state'] && 'success' == $gdtEntries['data']['state']) {
|
||||
$gdtSum = intval($gdtEntries['data']['sum']);
|
||||
} else {
|
||||
$this->addAdminError('StateBalancesController', 'overview', $gdtEntries, $user['id'] ? $user['id'] : 0);
|
||||
}
|
||||
$final_transactions = [];
|
||||
foreach($transactions_reversed as $i => $transaction) {
|
||||
$final_transactions[] = $transaction;
|
||||
$final_transactions[] = $decay_transactions[$i];
|
||||
|
||||
|
||||
$stateUserTransactionsQuery = $stateUserTransactionsTable
|
||||
->find()
|
||||
->where(['state_user_id' => $user['id']])
|
||||
->order(['balance_date' => 'ASC'])
|
||||
->contain([])
|
||||
;
|
||||
$decay = true;
|
||||
$transactions = [];
|
||||
if($stateUserTransactionsQuery->count() > 0) {
|
||||
$transactions = $transactionsTable->listTransactionsHumanReadable($stateUserTransactionsQuery->toArray(), $user, $decay);
|
||||
}
|
||||
|
||||
$state_balance = $stateBalancesTable->find()->where(['state_user_id' => $user['id']])->first();
|
||||
|
||||
$body = [
|
||||
'state' => 'success',
|
||||
'transactions' => $transactions,
|
||||
'transactionExecutingCount' => $session->read('Transactions.executing'),
|
||||
'count' => count($transactions),
|
||||
'gdtSum' => $gdtSum,
|
||||
'timeUsed' => microtime(true) - $startTime
|
||||
];
|
||||
$now = new FrozenTime();
|
||||
$body['decay_date'] = $now;
|
||||
|
||||
if(!$state_balance) {
|
||||
$balance = 0.0;
|
||||
} else {
|
||||
$balance = $stateBalancesTable->calculateDecay($state_balance->amount, $state_balance->record_date, $now);
|
||||
//$balance = $state_balance->partDecay($now);
|
||||
}
|
||||
// for debugging
|
||||
$calculated_balance = 0;
|
||||
foreach($final_transactions as $tr) {
|
||||
if($tr['type'] == 'send') {
|
||||
$calculated_balance -= intval($tr['balance']);
|
||||
foreach($transactions as $transaction) {
|
||||
if($transaction['type'] == 'decay' || $transaction['type'] == 'send') {
|
||||
$calculated_balance -= $transaction['balance'];
|
||||
} else {
|
||||
$calculated_balance += intval($tr['balance']);
|
||||
$calculated_balance += $transaction['balance'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->set('calculated_balance', $calculated_balance);
|
||||
|
||||
$this->set('transactions', array_reverse($final_transactions));
|
||||
$this->set('transactions', array_reverse($transactions));
|
||||
$this->set('transactionExecutingCount', $session->read('Transactions.executing'));
|
||||
$this->set('balance', $session->read('StateUser.balance'));
|
||||
$this->set('balance', $balance);
|
||||
$this->set('timeUsed', microtime(true) - $startTime);
|
||||
$this->set('gdtSum', $gdtSum);
|
||||
}
|
||||
@ -301,151 +170,16 @@ class StateBalancesController extends AppController
|
||||
if(!$state_balance) {
|
||||
return $this->returnJson(['state' => 'success', 'balance' => 0]);
|
||||
}
|
||||
$now = new FrozenTime();
|
||||
|
||||
return $this->returnJson([
|
||||
'state' => 'success',
|
||||
'balance' => $state_balance->amount,
|
||||
'decay' => $state_balance->decay
|
||||
'decay' => $this->StateBalances->calculateDecay($state_balance->amount, $state_balance->record_date, $now),
|
||||
'decay_date' => $now
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function ajaxListTransactions($session_id, $page=1, $count=25)
|
||||
{
|
||||
if(!$session_id) {
|
||||
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session id']);
|
||||
}
|
||||
|
||||
$startTime = microtime(true);
|
||||
$login_result = $this->requestLogin($session_id, false);
|
||||
if($login_result !== true) {
|
||||
return $this->returnJson($login_result);
|
||||
}
|
||||
$session = $this->getRequest()->getSession();
|
||||
$user = $session->read('StateUser');
|
||||
|
||||
$this->StateBalances->updateBalances($user['id']);
|
||||
|
||||
$gdtSum = 0;
|
||||
$gdtEntries = $this->JsonRequestClient->sendRequestGDT(['email' => $user['email']], 'GdtEntries' . DS . 'sumPerEmailApi');
|
||||
|
||||
if('success' == $gdtEntries['state'] && 'success' == $gdtEntries['data']['state']) {
|
||||
$gdtSum = intval($gdtEntries['data']['sum']);
|
||||
} else {
|
||||
if($user) {
|
||||
$this->addAdminError('StateBalancesController', 'overview', $gdtEntries, $user['id']);
|
||||
} else {
|
||||
$this->addAdminError('StateBalancesController', 'overview', $gdtEntries, 0);
|
||||
}
|
||||
}
|
||||
|
||||
$creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations');
|
||||
$creationTransactions = $creationsTable
|
||||
->find('all')
|
||||
->where(['state_user_id' => $user['id']])
|
||||
->contain(['Transactions']);
|
||||
|
||||
$transferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins');
|
||||
$transferTransactions = $transferTable
|
||||
->find('all')
|
||||
->where(['OR' => ['state_user_id' => $user['id'], 'receiver_user_id' => $user['id']]])
|
||||
->contain(['Transactions']);
|
||||
|
||||
$involvedUserIds = [];
|
||||
|
||||
foreach ($transferTransactions as $sendCoins) {
|
||||
//var_dump($sendCoins);
|
||||
if ($sendCoins->state_user_id != $user['id']) {
|
||||
array_push($involvedUserIds, intval($sendCoins->state_user_id));
|
||||
} elseif ($sendCoins->receiver_user_id != $user['id']) {
|
||||
array_push($involvedUserIds, intval($sendCoins->receiver_user_id));
|
||||
}
|
||||
}
|
||||
|
||||
/*echo "state user from sendCoins: $sendCoins->state_user_id<br>";
|
||||
echo "receiver user from sendCoins: $sendCoins->receiver_user_id<br>";
|
||||
echo "user id from logged in user: ".$user['id']. '<br>';
|
||||
*/
|
||||
//var_dump($involvedUserIds);
|
||||
// exchange key with values and drop duplicates
|
||||
$involvedUser_temp = array_flip($involvedUserIds);
|
||||
// exchange back
|
||||
$involvedUserIds = array_flip($involvedUser_temp);
|
||||
$userTable = TableRegistry::getTableLocator()->get('StateUsers');
|
||||
$involvedUser = $userTable->find('all', [
|
||||
'contain' => false,
|
||||
'where' => ['id IN' => $involvedUserIds],
|
||||
'fields' => ['id', 'first_name', 'last_name', 'email']
|
||||
]);
|
||||
//var_dump($involvedUser->toArray());
|
||||
$involvedUserIndices = [];
|
||||
foreach ($involvedUser as $involvedUser) {
|
||||
$involvedUserIndices[$involvedUser->id] = $involvedUser;
|
||||
}
|
||||
|
||||
// sender or receiver when user has sended money
|
||||
// group name if creation
|
||||
// type: gesendet / empfangen / geschöpft
|
||||
// transaktion nr / id
|
||||
// date
|
||||
// balance
|
||||
|
||||
$transactions = [];
|
||||
foreach ($creationTransactions as $creation) {
|
||||
//var_dump($creation);
|
||||
array_push($transactions, [
|
||||
'name' => 'Gradido Akademie',
|
||||
'type' => 'creation',
|
||||
'transaction_id' => $creation->transaction_id,
|
||||
'date' => $creation->transaction->received,
|
||||
'balance' => $creation->amount,
|
||||
'memo' => $creation->transaction->memo
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($transferTransactions as $sendCoins) {
|
||||
$type = '';
|
||||
$otherUser = null;
|
||||
if ($sendCoins->state_user_id == $user['id']) {
|
||||
$type = 'send';
|
||||
|
||||
if(isset($involvedUserIndices[$sendCoins->receiver_user_id])) {
|
||||
$otherUser = $involvedUserIndices[$sendCoins->receiver_user_id];
|
||||
}
|
||||
} else if ($sendCoins->receiver_user_id == $user['id']) {
|
||||
$type = 'receive';
|
||||
if(isset($involvedUserIndices[$sendCoins->state_user_id])) {
|
||||
$otherUser = $involvedUserIndices[$sendCoins->state_user_id];
|
||||
}
|
||||
}
|
||||
if(null == $otherUser) {
|
||||
$otherUser = $this->StateBalances->StateUsers->newEntity();
|
||||
}
|
||||
array_push($transactions, [
|
||||
'name' => $otherUser->first_name . ' ' . $otherUser->last_name,
|
||||
'email' => $otherUser->email,
|
||||
'type' => $type,
|
||||
'transaction_id' => $sendCoins->transaction_id,
|
||||
'date' => $sendCoins->transaction->received,
|
||||
'balance' => $sendCoins->amount,
|
||||
'memo' => $sendCoins->transaction->memo
|
||||
]);
|
||||
}
|
||||
uasort($transactions, array($this, 'sortTransactions'));
|
||||
if($sort == 'DESC') {
|
||||
$transactions = array_reverse($transactions);
|
||||
}
|
||||
return $this->returnJson([
|
||||
'state' => 'success',
|
||||
'transactions' => $transactions,
|
||||
'transactionExecutingCount' => $session->read('Transactions.executing'),
|
||||
'count' => count($transactions),
|
||||
'gdtSum' => $gdtSum,
|
||||
'timeUsed' => microtime(true) - $startTime
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function ajaxGdtOverview()
|
||||
{
|
||||
|
||||
@ -22,6 +22,7 @@ class AppTable extends Table
|
||||
$this->getConnection()->query($truncateCommand);
|
||||
}
|
||||
$this->getConnection()->query('ALTER TABLE ' . $this->getSchema()->name() . ' AUTO_INCREMENT=1');
|
||||
return ['success' => true];
|
||||
}
|
||||
public function saveManyWithErrors($entities)
|
||||
{
|
||||
|
||||
@ -24,7 +24,7 @@ use Cake\I18n\FrozenTime;
|
||||
*
|
||||
* @mixin \Cake\ORM\Behavior\TimestampBehavior
|
||||
*/
|
||||
class StateBalancesTable extends Table
|
||||
class StateBalancesTable extends AppTable
|
||||
{
|
||||
private static $startDecayDate = null;
|
||||
/**
|
||||
|
||||
@ -426,6 +426,9 @@ class TransactionsTable extends Table
|
||||
}
|
||||
}
|
||||
}
|
||||
if(count($state_user_ids) < 1) {
|
||||
return ['success' => true];
|
||||
}
|
||||
//var_dump($entities);
|
||||
$stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers');
|
||||
$existingStateUsers = $stateUsersTable->find('all')->select(['id'])->where(['id IN' => $state_user_ids])->order(['id'])->all();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bootstrap-vue-gradido-wallet",
|
||||
"version": "0.9.4",
|
||||
"version": "1.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node run/server.js",
|
||||
|
||||
@ -1,20 +1,5 @@
|
||||
<template>
|
||||
<div id="app" class="font-sans text-gray-800">
|
||||
<header>
|
||||
<b-col class="text-center">
|
||||
<b-dropdown
|
||||
size="sm"
|
||||
split
|
||||
variant="secondary"
|
||||
:text="$t('language') + ' - ' + $i18n.locale"
|
||||
class="m-md-2"
|
||||
>
|
||||
<b-dropdown-divider></b-dropdown-divider>
|
||||
<b-dropdown-item @click.prevent="setLocale('de')">Deutsch</b-dropdown-item>
|
||||
<b-dropdown-item @click.prevent="setLocale('en')">English</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</b-col>
|
||||
</header>
|
||||
<div class="">
|
||||
<particles-bg type="custom" :config="config" :bg="true" />
|
||||
<component :is="$route.meta.requiresAuth ? 'DashboardLayout' : 'AuthLayoutGDD'" />
|
||||
@ -25,7 +10,6 @@
|
||||
<script>
|
||||
import { ParticlesBg } from 'particles-bg-vue'
|
||||
import icon from './icon.js'
|
||||
import { localeChanged } from 'vee-validate'
|
||||
import DashboardLayout from '@/views/Layout/DashboardLayout_gdd.vue'
|
||||
import AuthLayoutGDD from '@/views/Layout/AuthLayout_gdd.vue'
|
||||
|
||||
@ -54,13 +38,6 @@ export default {
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setLocale(locale) {
|
||||
this.$i18n.locale = locale
|
||||
this.$store.commit('language', this.$i18n.locale)
|
||||
localeChanged(locale)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
@ -51,14 +51,11 @@ const communityAPI = {
|
||||
}
|
||||
return apiPost(CONFIG.COMMUNITY_API__URL + 'createCoins/', payload)
|
||||
}, */
|
||||
send: async (sessionId, email, amount, memo, targetDate) => {
|
||||
send: async (sessionId, data) => {
|
||||
const payload = {
|
||||
session_id: sessionId,
|
||||
email,
|
||||
amount,
|
||||
memo,
|
||||
target_date: targetDate,
|
||||
auto_sign: true,
|
||||
...data,
|
||||
}
|
||||
return apiPost(CONFIG.COMMUNITY_API_URL + 'sendCoins/', payload)
|
||||
},
|
||||
|
||||
22
frontend/src/components/LanguageSwitch.vue
Normal file
22
frontend/src/components/LanguageSwitch.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div class="language-switch">
|
||||
<b-dropdown size="sm" :text="$t('language') + ' - ' + $i18n.locale">
|
||||
<b-dropdown-item @click.prevent="setLocale('de')">Deutsch</b-dropdown-item>
|
||||
<b-dropdown-item @click.prevent="setLocale('en')">English</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { localeChanged } from 'vee-validate'
|
||||
|
||||
export default {
|
||||
name: 'language-switch',
|
||||
methods: {
|
||||
setLocale(locale) {
|
||||
this.$i18n.locale = locale
|
||||
this.$store.commit('language', this.$i18n.locale)
|
||||
localeChanged(locale)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
123
frontend/src/components/SidebarPlugin/SideBar.spec.js
Normal file
123
frontend/src/components/SidebarPlugin/SideBar.spec.js
Normal file
@ -0,0 +1,123 @@
|
||||
import { mount, RouterLinkStub } from '@vue/test-utils'
|
||||
import SideBar from './SideBar'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
describe('SideBar', () => {
|
||||
let wrapper
|
||||
|
||||
const stubs = {
|
||||
RouterLink: RouterLinkStub,
|
||||
}
|
||||
|
||||
const propsData = {
|
||||
balance: 1234.56,
|
||||
}
|
||||
|
||||
const mocks = {
|
||||
$store: {
|
||||
state: {
|
||||
email: 'test@example.org',
|
||||
},
|
||||
},
|
||||
$i18n: {
|
||||
locale: 'en',
|
||||
},
|
||||
$t: jest.fn((t) => t),
|
||||
$n: jest.fn((n) => n),
|
||||
}
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(SideBar, { localVue, mocks, stubs, propsData })
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('renders the component', () => {
|
||||
expect(wrapper.find('#sidenav-main').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
describe('balance', () => {
|
||||
it('shows em-dash as balance while loading', () => {
|
||||
expect(wrapper.find('div.row.text-center').text()).toBe('— GDD')
|
||||
})
|
||||
|
||||
it('shows the when loaded', async () => {
|
||||
wrapper.setProps({
|
||||
pending: false,
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(wrapper.find('div.row.text-center').text()).toBe('1234.56 GDD')
|
||||
})
|
||||
})
|
||||
|
||||
describe('navbar button', () => {
|
||||
it('has a navbar button', () => {
|
||||
expect(wrapper.find('button.navbar-toggler').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('calls showSidebar when clicked', async () => {
|
||||
const spy = jest.spyOn(wrapper.vm.$sidebar, 'displaySidebar')
|
||||
wrapper.find('button.navbar-toggler').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(spy).toHaveBeenCalledWith(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('close siedbar', () => {
|
||||
it('calls closeSidebar when clicked', async () => {
|
||||
const spy = jest.spyOn(wrapper.vm.$sidebar, 'displaySidebar')
|
||||
wrapper.find('#sidenav-collapse-main').find('button.navbar-toggler').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(spy).toHaveBeenCalledWith(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('static menu items', () => {
|
||||
describe("member's area", () => {
|
||||
it('has a link to the elopage', () => {
|
||||
expect(wrapper.findAll('li').at(0).text()).toBe('members_area')
|
||||
})
|
||||
|
||||
it('links to the elopage', () => {
|
||||
expect(wrapper.findAll('li').at(0).find('a').attributes('href')).toBe(
|
||||
'https://elopage.com/s/gradido/sign_in?locale=en',
|
||||
)
|
||||
})
|
||||
|
||||
describe('with locale="de"', () => {
|
||||
beforeEach(() => {
|
||||
mocks.$i18n.locale = 'de'
|
||||
})
|
||||
|
||||
it('links to the German elopage when locale is set to de', () => {
|
||||
expect(wrapper.findAll('li').at(0).find('a').attributes('href')).toBe(
|
||||
'https://elopage.com/s/gradido/sign_in?locale=de',
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('logout', () => {
|
||||
it('has a logout button', () => {
|
||||
expect(wrapper.findAll('li').at(1).text()).toBe('logout')
|
||||
})
|
||||
|
||||
it('emits logout when logout is clicked', async () => {
|
||||
wrapper.findAll('li').at(1).find('a').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(wrapper.emitted('logout')).toEqual([[]])
|
||||
})
|
||||
})
|
||||
|
||||
describe('language-switch', () => {
|
||||
it('has a language-switch button', () => {
|
||||
expect(wrapper.find('div.language-switch').exists()).toBeTruthy()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -10,7 +10,7 @@
|
||||
<img :src="logo" class="navbar-brand-img" alt="..." />
|
||||
</div>
|
||||
<b-row class="text-center">
|
||||
<b-col>{{ $n(balance) }} GDD</b-col>
|
||||
<b-col>{{ pending ? '—' : $n(balance) }} GDD</b-col>
|
||||
</b-row>
|
||||
<slot name="mobile-right">
|
||||
<ul class="nav align-items-center d-md-none">
|
||||
@ -32,9 +32,7 @@
|
||||
<div class="navbar-collapse-header d-md-none">
|
||||
<div class="row">
|
||||
<div class="col-6 collapse-brand">
|
||||
<router-link to="/overview">
|
||||
<img :src="logo" />
|
||||
</router-link>
|
||||
<img :src="logo" />
|
||||
</div>
|
||||
<div class="col-6 collapse-close">
|
||||
<navbar-toggle-button @click.native="closeSidebar"></navbar-toggle-button>
|
||||
@ -44,26 +42,29 @@
|
||||
<ul class="navbar-nav">
|
||||
<slot name="links"></slot>
|
||||
</ul>
|
||||
<hr class="my-3" />
|
||||
<ul class="navbar-nav mb-md-3">
|
||||
<hr class="my-2" />
|
||||
<ul class="navbar-nav ml-3">
|
||||
<li class="nav-item">
|
||||
<a
|
||||
:href="`https://elopage.com/s/gradido/sign_in?locale=${$i18n.locale}`"
|
||||
class="nav-link text-lg"
|
||||
class="nav-link"
|
||||
target="_blank"
|
||||
>
|
||||
{{ $t('members_area') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<hr class="my-3" />
|
||||
<ul class="navbar-nav mb-md-3">
|
||||
|
||||
<ul class="navbar-nav ml-3">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-lg pointer" @click="logout">
|
||||
<a class="nav-link pointer" @click="logout">
|
||||
{{ $t('logout') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="mt-5 ml-4">
|
||||
<language-switch />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@ -71,12 +72,14 @@
|
||||
<script>
|
||||
import NavbarToggleButton from '@/components/NavbarToggleButton'
|
||||
import VueQrcode from 'vue-qrcode'
|
||||
import LanguageSwitch from '@/components/LanguageSwitch.vue'
|
||||
|
||||
export default {
|
||||
name: 'sidebar',
|
||||
components: {
|
||||
NavbarToggleButton,
|
||||
VueQrcode,
|
||||
LanguageSwitch,
|
||||
},
|
||||
props: {
|
||||
logo: {
|
||||
@ -93,6 +96,10 @@ export default {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
pending: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
|
||||
@ -57,7 +57,6 @@
|
||||
},
|
||||
"transaction":{
|
||||
"show_all":"View all <strong>{count}</strong> transactions.",
|
||||
"show_part": "The last <strong>{count}</strong> transactions.",
|
||||
"nullTransactions":"You don't have any transactions on your account yet.",
|
||||
"more": "more"
|
||||
},
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="main-content">
|
||||
<div class="main-content mt-4">
|
||||
<router-view></router-view>
|
||||
<language-switch class="text-center mb-5 mt-5" />
|
||||
<content-footer v-if="!$route.meta.hideFooter"></content-footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import ContentFooter from './ContentFooter.vue'
|
||||
import LanguageSwitch from '@/components/LanguageSwitch.vue'
|
||||
export default {
|
||||
components: {
|
||||
ContentFooter,
|
||||
LanguageSwitch,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -59,10 +59,6 @@ describe('DashboardLayoutGdd', () => {
|
||||
expect(wrapper.find('nav#sidenav-main').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('has a notifications component', () => {
|
||||
expect(wrapper.find('div.notifications').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('has a main content div', () => {
|
||||
expect(wrapper.find('div.main-content').exists()).toBeTruthy()
|
||||
})
|
||||
@ -79,31 +75,35 @@ describe('DashboardLayoutGdd', () => {
|
||||
})
|
||||
|
||||
it('has five items in the navbar', () => {
|
||||
expect(navbar.findAll('ul > li')).toHaveLength(2)
|
||||
expect(navbar.findAll('ul > a')).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('has first item "send" in navbar', () => {
|
||||
expect(navbar.findAll('ul > li').at(0).text()).toEqual('send')
|
||||
expect(navbar.findAll('ul > a').at(0).text()).toEqual('send')
|
||||
})
|
||||
|
||||
it('has first item "send" linked to overview in navbar', () => {
|
||||
navbar.findAll('ul > li').at(0).trigger('click')
|
||||
navbar.findAll('ul > a').at(0).trigger('click')
|
||||
expect(wrapper.findComponent(RouterLinkStub).props().to).toBe('/overview')
|
||||
})
|
||||
|
||||
it('has second item "transactions" in navbar', () => {
|
||||
expect(navbar.findAll('ul > li').at(1).text()).toEqual('transactions')
|
||||
expect(navbar.findAll('ul > a').at(1).text()).toEqual('transactions')
|
||||
})
|
||||
|
||||
// to do: get this working!
|
||||
it.skip('has second item "transactions" linked to transactions in navbar', async () => {
|
||||
navbar.findAll('ul > li > a').at(1).trigger('click')
|
||||
navbar.findAll('ul > a').at(1).trigger('click')
|
||||
await flushPromises()
|
||||
await jest.runAllTimers()
|
||||
await flushPromises()
|
||||
expect(wrapper.findComponent(RouterLinkStub).props().to).toBe('/transactions')
|
||||
})
|
||||
|
||||
// it('has tree items in the navbar', () => {
|
||||
// expect(navbar.findAll('ul > li')).toHaveLength(3)
|
||||
// })
|
||||
//
|
||||
// it('has third item "My profile" in navbar', () => {
|
||||
// expect(navbar.findAll('ul > li').at(2).text()).toEqual('site.navbar.my-profil')
|
||||
// })
|
||||
|
||||
@ -1,30 +1,35 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<notifications></notifications>
|
||||
<side-bar @logout="logout" :balance="balance">
|
||||
<side-bar @logout="logout" :balance="balance" :pending="pending">
|
||||
<template slot="links">
|
||||
<b-nav-item href="#!" to="/overview">
|
||||
<b-nav-text class="p-0 text-lg text-muted">{{ $t('send') }}</b-nav-text>
|
||||
</b-nav-item>
|
||||
<b-nav-item href="#!" to="/transactions">
|
||||
<b-nav-text class="p-0 text-lg text-muted">{{ $t('transactions') }}</b-nav-text>
|
||||
</b-nav-item>
|
||||
<sidebar-item
|
||||
:link="{
|
||||
name: $t('send'),
|
||||
path: '/overview',
|
||||
}"
|
||||
></sidebar-item>
|
||||
<sidebar-item
|
||||
:link="{
|
||||
name: $t('transactions'),
|
||||
path: '/transactions',
|
||||
}"
|
||||
></sidebar-item>
|
||||
|
||||
<!--
|
||||
<b-nav-item href="#!" to="/profile">
|
||||
<b-nav-text class="p-0 text-lg text-muted">{{ $t('site.navbar.my-profil') }}</b-nav-text>
|
||||
</b-nav-item>
|
||||
<b-nav-item href="#!" to="/profileedit">
|
||||
<b-nav-text class="p-0 text-lg text-muted">{{ $t('site.navbar.settings') }}</b-nav-text>
|
||||
</b-nav-item>
|
||||
<b-nav-item href="#!" to="/activity">
|
||||
<b-nav-text class="p-0 text-lg text-muted">{{ $t('site.navbar.activity') }}</b-nav-text>
|
||||
</b-nav-item>
|
||||
<b-nav-item href="#!" to="/profile">
|
||||
<b-nav-text class="p-0 text-lg text-muted">{{ $t('site.navbar.my-profil') }}</b-nav-text>
|
||||
</b-nav-item>
|
||||
<b-nav-item href="#!" to="/profileedit">
|
||||
<b-nav-text class="p-0 text-lg text-muted">{{ $t('site.navbar.settings') }}</b-nav-text>
|
||||
</b-nav-item>
|
||||
<b-nav-item href="#!" to="/activity">
|
||||
<b-nav-text class="p-0 text-lg text-muted">{{ $t('site.navbar.activity') }}</b-nav-text>
|
||||
</b-nav-item>
|
||||
-->
|
||||
</template>
|
||||
</side-bar>
|
||||
<div class="main-content">
|
||||
<dashboard-navbar :type="$route.meta.navbarType"></dashboard-navbar>
|
||||
|
||||
<div @click="$sidebar.displaySidebar(false)">
|
||||
<fade-transition :duration="200" origin="center top" mode="out-in">
|
||||
<!-- your content here -->
|
||||
@ -33,6 +38,7 @@
|
||||
:gdt-balance="GdtBalance"
|
||||
:transactions="transactions"
|
||||
:transactionCount="transactionCount"
|
||||
:pending="pending"
|
||||
@update-balance="updateBalance"
|
||||
@update-transactions="updateTransactions"
|
||||
></router-view>
|
||||
@ -83,6 +89,7 @@ export default {
|
||||
transactions: [],
|
||||
bookedBalance: 0,
|
||||
transactionCount: 0,
|
||||
pending: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -99,6 +106,7 @@ export default {
|
||||
this.$router.push('/login')
|
||||
},
|
||||
async updateTransactions() {
|
||||
this.pending = true
|
||||
const result = await communityAPI.transactions(this.$store.state.sessionId)
|
||||
if (result.success) {
|
||||
this.GdtBalance = Number(result.result.data.gdtSum)
|
||||
@ -106,7 +114,9 @@ export default {
|
||||
this.balance = Number(result.result.data.decay)
|
||||
this.bookedBalance = Number(result.result.data.balance)
|
||||
this.transactionCount = result.result.data.count
|
||||
this.pending = false
|
||||
} else {
|
||||
this.pending = true
|
||||
// what to do when loading balance fails?
|
||||
}
|
||||
},
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<li class="nav-item d-sm-none"></li>
|
||||
</b-navbar-nav>
|
||||
<b-navbar-nav class="align-items-center ml-auto ml-md-0">
|
||||
<a class="pr-1 nav-link" slot="title-container pointer">
|
||||
<div class="pr-1" slot="title-container ">
|
||||
<b-media no-body class="align-items-center">
|
||||
<span class="pb-2 text-lg font-weight-bold">
|
||||
{{ $store.state.email }}
|
||||
@ -21,7 +21,7 @@
|
||||
</span>
|
||||
</b-media-body>
|
||||
</b-media>
|
||||
</a>
|
||||
</div>
|
||||
</b-navbar-nav>
|
||||
</base-nav>
|
||||
</template>
|
||||
|
||||
@ -34,30 +34,5 @@ describe('AccountOverview', () => {
|
||||
it('has a transactions table', () => {
|
||||
expect(wrapper.find('gdd-table-stub').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
describe('updateBalance method', () => {
|
||||
beforeEach(async () => {
|
||||
wrapper.find('gdd-send-stub').vm.$emit('update-balance', {
|
||||
ammount: 42,
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('emmits updateBalance with correct value', () => {
|
||||
expect(wrapper.emitted('update-balance')).toEqual([[42]])
|
||||
})
|
||||
})
|
||||
|
||||
describe('toggleShowList method', () => {
|
||||
beforeEach(async () => {
|
||||
wrapper.setProps({ showTransactionList: false })
|
||||
wrapper.find('gdd-send-stub').vm.$emit('toggle-show-list', true)
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('changes the value of property showTransactionList', () => {
|
||||
expect(wrapper.vm.showTransactionList).toBeTruthy()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,25 +1,43 @@
|
||||
<template>
|
||||
<div>
|
||||
<base-header class="pb-4 pt-2 bg-transparent"></base-header>
|
||||
<b-container fluid class="p-2 mt-5">
|
||||
<gdd-status v-if="showTransactionList" :balance="balance" :gdt-balance="GdtBalance" />
|
||||
<br />
|
||||
<gdd-send
|
||||
<base-header class="pb-lg-4 pt-lg-2 bg-transparent"></base-header>
|
||||
<b-container fluid class="p-lg-2 mt-lg-5">
|
||||
<gdd-status
|
||||
v-if="showContext"
|
||||
:pending="pending"
|
||||
:balance="balance"
|
||||
:show-transaction-list="showTransactionList"
|
||||
@update-balance="updateBalance"
|
||||
@toggle-show-list="toggleShowList"
|
||||
:gdt-balance="GdtBalance"
|
||||
/>
|
||||
<br />
|
||||
<gdd-send :currentTransactionStep="currentTransactionStep">
|
||||
<template #transaction-form>
|
||||
<transaction-form :balance="balance" @set-transaction="setTransaction"></transaction-form>
|
||||
</template>
|
||||
<template #transaction-confirmation>
|
||||
<transaction-confirmation
|
||||
:email="transactionData.email"
|
||||
:amount="transactionData.amount"
|
||||
:memo="transactionData.memo"
|
||||
:date="transactionData.target_date"
|
||||
:loading="loading"
|
||||
@send-transaction="sendTransaction"
|
||||
@on-reset="onReset"
|
||||
></transaction-confirmation>
|
||||
</template>
|
||||
<template #transaction-result>
|
||||
<transaction-result :error="error" @on-reset="onReset"></transaction-result>
|
||||
</template>
|
||||
</gdd-send>
|
||||
<hr />
|
||||
<gdd-table
|
||||
v-if="showTransactionList"
|
||||
v-if="showContext"
|
||||
:transactions="transactions"
|
||||
:max="5"
|
||||
:timestamp="timestamp"
|
||||
:transactionCount="transactionCount"
|
||||
@update-transactions="updateTransactions"
|
||||
@update-transactions="$emit('update-transactions')"
|
||||
/>
|
||||
<gdd-table-footer :count="transactionCount" />
|
||||
<gdd-table-footer v-if="showContext" :count="transactionCount" />
|
||||
</b-container>
|
||||
</div>
|
||||
</template>
|
||||
@ -28,6 +46,17 @@ import GddStatus from './AccountOverview/GddStatus.vue'
|
||||
import GddSend from './AccountOverview/GddSend.vue'
|
||||
import GddTable from './AccountOverview/GddTable.vue'
|
||||
import GddTableFooter from './AccountOverview/GddTableFooter.vue'
|
||||
import TransactionForm from './AccountOverview/GddSend/TransactionForm.vue'
|
||||
import TransactionConfirmation from './AccountOverview/GddSend/TransactionConfirmation.vue'
|
||||
import TransactionResult from './AccountOverview/GddSend/TransactionResult.vue'
|
||||
import communityAPI from '../../apis/communityAPI.js'
|
||||
|
||||
const EMPTY_TRANSACTION_DATA = {
|
||||
email: '',
|
||||
amount: 0,
|
||||
memo: '',
|
||||
target_date: '',
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'Overview',
|
||||
@ -36,11 +65,17 @@ export default {
|
||||
GddSend,
|
||||
GddTable,
|
||||
GddTableFooter,
|
||||
TransactionForm,
|
||||
TransactionConfirmation,
|
||||
TransactionResult,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showTransactionList: true,
|
||||
timestamp: Date.now(),
|
||||
transactionData: EMPTY_TRANSACTION_DATA,
|
||||
error: false,
|
||||
currentTransactionStep: 0,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@ -50,16 +85,37 @@ export default {
|
||||
default: () => [],
|
||||
},
|
||||
transactionCount: { type: Number, default: 0 },
|
||||
pending: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
showContext() {
|
||||
return this.currentTransactionStep === 0
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleShowList(bool) {
|
||||
this.showTransactionList = bool
|
||||
setTransaction(data) {
|
||||
data.target_date = new Date(Date.now()).toISOString()
|
||||
this.transactionData = { ...data }
|
||||
this.currentTransactionStep = 1
|
||||
},
|
||||
updateBalance(data) {
|
||||
this.$emit('update-balance', data.ammount)
|
||||
async sendTransaction() {
|
||||
this.loading = true
|
||||
const result = await communityAPI.send(this.$store.state.sessionId, this.transactionData)
|
||||
if (result.success) {
|
||||
this.error = false
|
||||
this.$emit('update-balance', this.transactionData.amount)
|
||||
} else {
|
||||
this.error = true
|
||||
}
|
||||
this.currentTransactionStep = 2
|
||||
this.loading = false
|
||||
},
|
||||
updateTransactions() {
|
||||
this.$emit('update-transactions')
|
||||
onReset() {
|
||||
this.transactionData = EMPTY_TRANSACTION_DATA
|
||||
this.currentTransactionStep = 0
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,29 +1,18 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import GddSend from './GddSend'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
describe('GddSend', () => {
|
||||
let wrapper
|
||||
|
||||
const state = {
|
||||
user: {
|
||||
balance: 1234,
|
||||
balance_gdt: 9876,
|
||||
},
|
||||
}
|
||||
|
||||
const store = new Vuex.Store({
|
||||
state,
|
||||
})
|
||||
|
||||
const mocks = {
|
||||
// $n: jest.fn((n) => n),
|
||||
$t: jest.fn((t) => t),
|
||||
$moment: jest.fn((m) => ({
|
||||
format: () => m,
|
||||
})),
|
||||
$store: {
|
||||
state: {
|
||||
sessionId: 1234,
|
||||
},
|
||||
},
|
||||
$i18n: {
|
||||
locale: jest.fn(() => 'en'),
|
||||
},
|
||||
@ -31,7 +20,7 @@ describe('GddSend', () => {
|
||||
}
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(GddSend, { localVue, store, mocks })
|
||||
return mount(GddSend, { localVue, mocks })
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
@ -42,88 +31,5 @@ describe('GddSend', () => {
|
||||
it('renders the component', () => {
|
||||
expect(wrapper.find('div.gdd-send').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
describe('warning messages', () => {
|
||||
it('has a warning message', () => {
|
||||
expect(wrapper.find('div.alert-default').find('span').text()).toBe('form.attention')
|
||||
})
|
||||
})
|
||||
|
||||
describe('transaction form', () => {
|
||||
describe('email field', () => {
|
||||
it('has an input field of type email', () => {
|
||||
expect(wrapper.find('#input-group-1').find('input').attributes('type')).toBe('email')
|
||||
})
|
||||
|
||||
it('has an envelope icon', () => {
|
||||
expect(wrapper.find('#input-group-1').find('svg').attributes('aria-label')).toBe(
|
||||
'envelope',
|
||||
)
|
||||
})
|
||||
|
||||
it('has a label form.receiver', () => {
|
||||
expect(wrapper.findAll('div.text-left').at(0).text()).toBe('form.receiver')
|
||||
})
|
||||
|
||||
it('has a placeholder "E-Mail"', () => {
|
||||
expect(wrapper.find('#input-group-1').find('input').attributes('placeholder')).toBe(
|
||||
'E-Mail',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('ammount field', () => {
|
||||
it('has an input field of type number', () => {
|
||||
expect(wrapper.find('#input-group-2').find('input').attributes('type')).toBe('number')
|
||||
})
|
||||
|
||||
it('has an GDD text icon', () => {
|
||||
expect(wrapper.find('#input-group-2').find('div.h3').text()).toBe('GDD')
|
||||
})
|
||||
|
||||
it('has a label form.amount', () => {
|
||||
expect(wrapper.findAll('div.text-left').at(1).text()).toBe('form.amount')
|
||||
})
|
||||
|
||||
it('has a placeholder "0.01"', () => {
|
||||
expect(wrapper.find('#input-group-2').find('input').attributes('placeholder')).toBe(
|
||||
'0.01',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('message text box', () => {
|
||||
it('has an textarea field', () => {
|
||||
expect(wrapper.find('#input-group-3').find('textarea').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('has an chat-right-text icon', () => {
|
||||
expect(wrapper.find('#input-group-3').find('svg').attributes('aria-label')).toBe(
|
||||
'chat right text',
|
||||
)
|
||||
})
|
||||
|
||||
it('has a label form.memo', () => {
|
||||
expect(wrapper.findAll('div.text-left').at(2).text()).toBe('form.memo')
|
||||
})
|
||||
})
|
||||
|
||||
describe('cancel button', () => {
|
||||
it('has a cancel button', () => {
|
||||
expect(wrapper.find('button[type="reset"]').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('has the text "form.cancel"', () => {
|
||||
expect(wrapper.find('button[type="reset"]').text()).toBe('form.reset')
|
||||
})
|
||||
|
||||
it.skip('clears the email field on click', async () => {
|
||||
wrapper.find('#input-group-1').find('input').setValue('someone@watches.tv')
|
||||
wrapper.find('button[type="reset"]').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(wrapper.vm.form.email).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,346 +1,18 @@
|
||||
<template>
|
||||
<div class="gdd-send">
|
||||
<b-row v-show="showTransactionList">
|
||||
<b-col xl="12" md="12">
|
||||
<b-alert show dismissible variant="default" class="text-center">
|
||||
<span class="alert-text h3 text-light" v-html="$t('form.attention')"></span>
|
||||
</b-alert>
|
||||
<b-card class="p-0 p-md-3" style="background-color: #ebebeba3 !important">
|
||||
<!--
|
||||
<b-alert show variant="secondary">
|
||||
<span class="alert-text" v-html="$t('form.scann_code')"></span>
|
||||
<b-col v-show="!scan" lg="12" class="text-right">
|
||||
<a @click="toggle" class="nav-link pointer">
|
||||
<img src="img/icons/gradido/qr-scan-pure.png" height="50" />
|
||||
</a>
|
||||
</b-col>
|
||||
|
||||
<div v-if="scan">
|
||||
<b-row>
|
||||
<qrcode-capture @detect="onDetect" capture="user" ></qrcode-capture>
|
||||
</b-row>
|
||||
|
||||
<qrcode-stream class="mt-3" @decode="onDecode" @detect="onDetect"></qrcode-stream>
|
||||
|
||||
<b-container>
|
||||
<b-row>
|
||||
<b-col lg="8">
|
||||
<b-alert show variant="secondary">
|
||||
<span class="alert-text" v-html="$t('form.scann_code')"></span>
|
||||
</b-alert>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-container>
|
||||
</div>
|
||||
<div @click="toggle">
|
||||
<b-alert v-show="scan" show variant="primary" class="pointer text-center">
|
||||
<span class="alert-text">
|
||||
<strong>{{ $t('form.cancel') }}</strong>
|
||||
</span>
|
||||
</b-alert>
|
||||
</div>
|
||||
</b-alert>
|
||||
-->
|
||||
|
||||
<validation-observer v-slot="{ handleSubmit }" ref="formValidator">
|
||||
<b-form
|
||||
role="form"
|
||||
@submit.prevent="handleSubmit(onSubmit)"
|
||||
@reset="onReset"
|
||||
v-if="show"
|
||||
>
|
||||
<!-- <div>
|
||||
<qrcode-drop-zone id="input-0" v-model="form.img"></qrcode-drop-zone>
|
||||
</div>
|
||||
<br />
|
||||
-->
|
||||
<div>
|
||||
<validation-provider
|
||||
name="Email"
|
||||
:rules="{
|
||||
required: true,
|
||||
email: true,
|
||||
is_not: $store.state.email,
|
||||
}"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<b-row>
|
||||
<b-col class="text-left p-3 p-sm-1">{{ $t('form.receiver') }}</b-col>
|
||||
<b-col v-if="errors" class="text-right p-3 p-sm-1">
|
||||
<span v-for="error in errors" :key="error" class="errors">{{ error }}</span>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-input-group
|
||||
id="input-group-1"
|
||||
label="Empfänger:"
|
||||
label-for="input-1"
|
||||
description="We'll never share your email with anyone else."
|
||||
size="lg"
|
||||
class="mb-3"
|
||||
>
|
||||
<b-input-group-prepend class="p-3 d-none d-md-block">
|
||||
<b-icon icon="envelope" class="display-3"></b-icon>
|
||||
</b-input-group-prepend>
|
||||
<b-form-input
|
||||
id="input-1"
|
||||
v-model="form.email"
|
||||
type="email"
|
||||
placeholder="E-Mail"
|
||||
style="font-size: xx-large; padding-left: 20px"
|
||||
></b-form-input>
|
||||
</b-input-group>
|
||||
</validation-provider>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<validation-provider
|
||||
:name="$t('form.amount')"
|
||||
:rules="{
|
||||
required: true,
|
||||
double: [2, $i18n.locale === 'de' ? ',' : '.'],
|
||||
between: [0.01, balance],
|
||||
}"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<b-row>
|
||||
<b-col class="text-left p-3 p-sm-1">{{ $t('form.amount') }}</b-col>
|
||||
<b-col v-if="errors" class="text-right p-3 p-sm-1">
|
||||
<span v-for="error in errors" class="errors" :key="error">{{ error }}</span>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-input-group
|
||||
id="input-group-2"
|
||||
label="Betrag:"
|
||||
label-for="input-2"
|
||||
size="lg"
|
||||
class="mb-3"
|
||||
>
|
||||
<b-input-group-prepend class="p-2 d-none d-md-block">
|
||||
<div class="h3 pt-3 pr-3">GDD</div>
|
||||
</b-input-group-prepend>
|
||||
<b-form-input
|
||||
id="input-2"
|
||||
v-model="form.amount"
|
||||
type="number"
|
||||
:lang="$i18n.locale"
|
||||
:placeholder="$n(0.01)"
|
||||
step="0.01"
|
||||
style="font-size: xx-large; padding-left: 20px"
|
||||
></b-form-input>
|
||||
</b-input-group>
|
||||
<b-col class="text-left p-3 p-sm-1">{{ $t('form.memo') }}</b-col>
|
||||
<b-input-group id="input-group-3">
|
||||
<b-input-group-prepend class="p-3 d-none d-md-block">
|
||||
<b-icon icon="chat-right-text" class="display-3"></b-icon>
|
||||
</b-input-group-prepend>
|
||||
<b-form-textarea
|
||||
rows="3"
|
||||
v-model="form.memo"
|
||||
class="pl-3"
|
||||
style="font-size: x-large"
|
||||
></b-form-textarea>
|
||||
</b-input-group>
|
||||
</validation-provider>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-button type="reset" variant="secondary" @click="onReset">
|
||||
{{ $t('form.reset') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
<b-col class="text-right">
|
||||
<b-button type="submit" variant="success">
|
||||
{{ $t('form.send_now') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<br />
|
||||
</b-form>
|
||||
</validation-observer>
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row v-show="row_check">
|
||||
<b-col>
|
||||
<div class="display-4 p-4">{{ $t('form.send_check') }}</div>
|
||||
|
||||
<b-list-group>
|
||||
<b-list-group-item class="d-flex justify-content-between align-items-center">
|
||||
{{ ajaxCreateData.email }}
|
||||
<b-badge variant="primary" pill>{{ $t('form.receiver') }}</b-badge>
|
||||
</b-list-group-item>
|
||||
|
||||
<b-list-group-item class="d-flex justify-content-between align-items-center">
|
||||
{{ ajaxCreateData.amount }} GDD
|
||||
<b-badge variant="primary" pill>{{ $t('form.amount') }}</b-badge>
|
||||
</b-list-group-item>
|
||||
|
||||
<b-list-group-item class="d-flex justify-content-between align-items-center">
|
||||
{{ ajaxCreateData.memo ? ajaxCreateData.memo : '-' }}
|
||||
<b-badge variant="primary" pill>{{ $t('form.message') }}</b-badge>
|
||||
</b-list-group-item>
|
||||
<b-list-group-item class="d-flex justify-content-between align-items-center">
|
||||
{{ $moment(ajaxCreateData.target_date).format('DD.MM.YYYY - HH:mm:ss') }}
|
||||
<b-badge variant="primary" pill>{{ $t('form.date') }}</b-badge>
|
||||
</b-list-group-item>
|
||||
</b-list-group>
|
||||
<hr />
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-button @click="onReset">{{ $t('form.cancel') }}</b-button>
|
||||
</b-col>
|
||||
<b-col class="text-right">
|
||||
<b-button variant="success" @click="sendTransaction">
|
||||
{{ $t('form.send_now') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row v-show="row_thx">
|
||||
<b-col>
|
||||
<b-card class="p-0 p-md-3" style="background-color: #ebebeba3 !important">
|
||||
<div class="display-2 p-4">
|
||||
{{ $t('form.thx') }}
|
||||
<hr />
|
||||
{{ $t('form.send_transaction_success') }}
|
||||
</div>
|
||||
|
||||
<p class="text-center">
|
||||
<b-button variant="success" @click="onReset">{{ $t('form.close') }}</b-button>
|
||||
</p>
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row v-show="row_error">
|
||||
<b-col>
|
||||
<b-card class="p-0 p-md-3" style="background-color: #ebebeba3 !important">
|
||||
<div class="display-2 p-4">
|
||||
{{ $t('form.sorry') }}
|
||||
<hr />
|
||||
{{ $t('form.send_transaction_error') }}
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<b-button variant="success" @click="onReset">{{ $t('form.close') }}</b-button>
|
||||
</p>
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<slot :name="transactionSteps[currentTransactionStep]" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import { QrcodeStream, QrcodeDropZone } from 'vue-qrcode-reader'
|
||||
import { BIcon } from 'bootstrap-vue'
|
||||
import communityAPI from '../../../apis/communityAPI.js'
|
||||
|
||||
export default {
|
||||
name: 'GddSent',
|
||||
components: {
|
||||
// QrcodeStream,
|
||||
// QrcodeDropZone,
|
||||
BIcon,
|
||||
},
|
||||
props: {
|
||||
balance: { type: Number, default: 0 },
|
||||
showTransactionList: { type: Boolean, default: true },
|
||||
},
|
||||
name: 'GddSend',
|
||||
data() {
|
||||
return {
|
||||
// scan: false,
|
||||
show: true,
|
||||
form: {
|
||||
img: '',
|
||||
email: '',
|
||||
amount: '',
|
||||
memo: '',
|
||||
},
|
||||
ajaxCreateData: {
|
||||
email: '',
|
||||
amount: 0,
|
||||
target_date: '',
|
||||
memo: '',
|
||||
auto_sign: true,
|
||||
},
|
||||
send: false,
|
||||
row_check: false,
|
||||
row_thx: false,
|
||||
row_error: false,
|
||||
transactionSteps: ['transaction-form', 'transaction-confirmation', 'transaction-result'],
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
// toggle() {
|
||||
// this.scan = !this.scan
|
||||
// },
|
||||
// async onDecode(decodedString) {
|
||||
// const arr = JSON.parse(decodedString)
|
||||
// this.form.email = arr[0].email
|
||||
// this.form.amount = arr[0].amount
|
||||
// this.scan = false
|
||||
// },
|
||||
async onSubmit() {
|
||||
// event.preventDefault()
|
||||
this.ajaxCreateData.email = this.form.email
|
||||
this.ajaxCreateData.amount = this.form.amount
|
||||
const now = new Date(Date.now()).toISOString()
|
||||
this.ajaxCreateData.target_date = now
|
||||
this.ajaxCreateData.memo = this.form.memo
|
||||
this.$emit('toggle-show-list', false)
|
||||
this.row_check = true
|
||||
this.row_thx = false
|
||||
this.row_error = false
|
||||
},
|
||||
async sendTransaction() {
|
||||
const result = await communityAPI.send(
|
||||
this.$store.state.sessionId,
|
||||
this.ajaxCreateData.email,
|
||||
this.ajaxCreateData.amount,
|
||||
this.ajaxCreateData.memo,
|
||||
this.ajaxCreateData.target_date,
|
||||
)
|
||||
if (result.success) {
|
||||
this.$emit('toggle-show-list', false)
|
||||
this.row_check = false
|
||||
this.row_thx = true
|
||||
this.row_error = false
|
||||
this.$emit('update-balance', { ammount: this.ajaxCreateData.amount })
|
||||
} else {
|
||||
this.$emit('toggle-show-list', true)
|
||||
this.row_check = false
|
||||
this.row_thx = false
|
||||
this.row_error = true
|
||||
}
|
||||
},
|
||||
onReset(event) {
|
||||
event.preventDefault()
|
||||
this.form.email = ''
|
||||
this.form.amount = ''
|
||||
this.form.memo = ''
|
||||
this.show = false
|
||||
this.$emit('toggle-show-list', true)
|
||||
this.row_check = false
|
||||
this.row_thx = false
|
||||
this.row_error = false
|
||||
this.$nextTick(() => {
|
||||
this.show = true
|
||||
})
|
||||
},
|
||||
props: {
|
||||
currentTransactionStep: { type: Number, default: 0 },
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
video {
|
||||
max-height: 665px;
|
||||
max-width: 665px;
|
||||
}
|
||||
span.errors {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
65
frontend/src/views/Pages/AccountOverview/GddSend/QrCode.vue
Normal file
65
frontend/src/views/Pages/AccountOverview/GddSend/QrCode.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<b-alert show variant="secondary">
|
||||
<span class="alert-text" v-html="$t('form.scann_code')"></span>
|
||||
<b-col v-show="!scan" lg="12" class="text-right">
|
||||
<a @click="toggle" class="nav-link pointer">
|
||||
<img src="img/icons/gradido/qr-scan-pure.png" height="50" />
|
||||
</a>
|
||||
</b-col>
|
||||
|
||||
<div v-if="scan">
|
||||
<b-row>
|
||||
<qrcode-capture @detect="onDetect" capture="user"></qrcode-capture>
|
||||
</b-row>
|
||||
|
||||
<qrcode-stream class="mt-3" @decode="onDecode" @detect="onDetect"></qrcode-stream>
|
||||
|
||||
<b-container>
|
||||
<b-row>
|
||||
<b-col lg="8">
|
||||
<b-alert show variant="secondary">
|
||||
<span class="alert-text" v-html="$t('form.scann_code')"></span>
|
||||
</b-alert>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-container>
|
||||
</div>
|
||||
<div @click="toggle">
|
||||
<b-alert v-show="scan" show variant="primary" class="pointer text-center">
|
||||
<span class="alert-text">
|
||||
<strong>{{ $t('form.cancel') }}</strong>
|
||||
</span>
|
||||
</b-alert>
|
||||
</div>
|
||||
</b-alert>
|
||||
</template>
|
||||
<script>
|
||||
import { QrcodeStream } from 'vue-qrcode-reader'
|
||||
|
||||
export default {
|
||||
name: 'QrCode',
|
||||
components: {
|
||||
QrcodeStream,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scan: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.scan = !this.scan
|
||||
},
|
||||
async onDecode(decodedString) {
|
||||
const arr = JSON.parse(decodedString)
|
||||
this.$emit('set-transaction', { email: arr[0].email, amount: arr[0].amount })
|
||||
this.scan = false
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<div class="display-4 p-4">{{ $t('form.send_check') }}</div>
|
||||
<b-list-group>
|
||||
<b-list-group-item class="d-flex justify-content-between align-items-center">
|
||||
{{ email }}
|
||||
<b-badge variant="primary" pill>{{ $t('form.receiver') }}</b-badge>
|
||||
</b-list-group-item>
|
||||
<b-list-group-item class="d-flex justify-content-between align-items-center">
|
||||
{{ amount }} GDD
|
||||
<b-badge variant="primary" pill>{{ $t('form.amount') }}</b-badge>
|
||||
</b-list-group-item>
|
||||
<b-list-group-item class="d-flex justify-content-between align-items-center">
|
||||
{{ memo ? memo : '-' }}
|
||||
<b-badge variant="primary" pill>{{ $t('form.message') }}</b-badge>
|
||||
</b-list-group-item>
|
||||
<b-list-group-item class="d-flex justify-content-between align-items-center">
|
||||
{{ date }}
|
||||
{{ $moment(date).format('DD.MM.YYYY - HH:mm:ss') }}
|
||||
<b-badge variant="primary" pill>{{ $t('form.date') }}</b-badge>
|
||||
</b-list-group-item>
|
||||
</b-list-group>
|
||||
<hr />
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-button @click="$emit('on-reset')">{{ $t('form.cancel') }}</b-button>
|
||||
</b-col>
|
||||
<b-col class="text-right">
|
||||
<b-button variant="success" :disabled="loading" @click="$emit('send-transaction')">
|
||||
{{ $t('form.send_now') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'TransactionConfirmation',
|
||||
props: {
|
||||
email: { type: String, default: '' },
|
||||
amount: { type: String, default: '' },
|
||||
memo: { type: String, default: '' },
|
||||
date: { type: String, default: '' },
|
||||
loading: { type: Boolean, default: false },
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,121 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import TransactionForm from './TransactionForm'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
describe('GddSend', () => {
|
||||
let wrapper
|
||||
|
||||
const mocks = {
|
||||
$t: jest.fn((t) => t),
|
||||
$moment: jest.fn((m) => ({
|
||||
format: () => m,
|
||||
})),
|
||||
$i18n: {
|
||||
locale: jest.fn(() => 'en'),
|
||||
},
|
||||
$n: jest.fn((n) => String(n)),
|
||||
$store: {
|
||||
state: {
|
||||
email: 'user@example.org',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(TransactionForm, { localVue, mocks })
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('renders the component', () => {
|
||||
expect(wrapper.find('div.transaction-form').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
describe('warning messages', () => {
|
||||
it('has a warning message', () => {
|
||||
expect(wrapper.find('div.alert-default').find('span').text()).toBe('form.attention')
|
||||
})
|
||||
})
|
||||
|
||||
describe('transaction form', () => {
|
||||
describe('email field', () => {
|
||||
it('has an input field of type email', () => {
|
||||
expect(wrapper.find('#input-group-1').find('input').attributes('type')).toBe('email')
|
||||
})
|
||||
|
||||
it('has an envelope icon', () => {
|
||||
expect(wrapper.find('#input-group-1').find('svg').attributes('aria-label')).toBe(
|
||||
'envelope',
|
||||
)
|
||||
})
|
||||
|
||||
it('has a label form.receiver', () => {
|
||||
expect(wrapper.findAll('div.text-left').at(0).text()).toBe('form.receiver')
|
||||
})
|
||||
|
||||
it('has a placeholder "E-Mail"', () => {
|
||||
expect(wrapper.find('#input-group-1').find('input').attributes('placeholder')).toBe(
|
||||
'E-Mail',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('ammount field', () => {
|
||||
it('has an input field of type number', () => {
|
||||
expect(wrapper.find('#input-group-2').find('input').attributes('type')).toBe('number')
|
||||
})
|
||||
|
||||
it('has an GDD text icon', () => {
|
||||
expect(wrapper.find('#input-group-2').find('div.h3').text()).toBe('GDD')
|
||||
})
|
||||
|
||||
it('has a label form.amount', () => {
|
||||
expect(wrapper.findAll('div.text-left').at(1).text()).toBe('form.amount')
|
||||
})
|
||||
|
||||
it('has a placeholder "0.01"', () => {
|
||||
expect(wrapper.find('#input-group-2').find('input').attributes('placeholder')).toBe(
|
||||
'0.01',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('message text box', () => {
|
||||
it('has an textarea field', () => {
|
||||
expect(wrapper.find('#input-group-3').find('textarea').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('has an chat-right-text icon', () => {
|
||||
expect(wrapper.find('#input-group-3').find('svg').attributes('aria-label')).toBe(
|
||||
'chat right text',
|
||||
)
|
||||
})
|
||||
|
||||
it('has a label form.memo', () => {
|
||||
expect(wrapper.findAll('div.text-left').at(2).text()).toBe('form.memo')
|
||||
})
|
||||
})
|
||||
|
||||
describe('cancel button', () => {
|
||||
it('has a cancel button', () => {
|
||||
expect(wrapper.find('button[type="reset"]').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('has the text "form.cancel"', () => {
|
||||
expect(wrapper.find('button[type="reset"]').text()).toBe('form.reset')
|
||||
})
|
||||
|
||||
it.skip('clears the email field on click', async () => {
|
||||
wrapper.find('#input-group-1').find('input').setValue('someone@watches.tv')
|
||||
wrapper.find('button[type="reset"]').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(wrapper.vm.form.email).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<b-row class="transaction-form">
|
||||
<b-col xl="12" md="12">
|
||||
<b-alert show dismissible variant="default" class="text-center">
|
||||
<span class="alert-text h3 text-light" v-html="$t('form.attention')"></span>
|
||||
</b-alert>
|
||||
<b-card class="p-0 p-md-3" style="background-color: #ebebeba3 !important">
|
||||
<!-- -<QrCode @set-transaction="setTransaction"></QrCode> -->
|
||||
<validation-observer v-slot="{ handleSubmit }" ref="formValidator">
|
||||
<b-form role="form" @submit.prevent="handleSubmit(onSubmit)" @reset="onReset">
|
||||
<!-- <div>
|
||||
<qrcode-drop-zone id="input-0" v-model="form.img"></qrcode-drop-zone>
|
||||
</div>
|
||||
<br />
|
||||
-->
|
||||
<div>
|
||||
<validation-provider
|
||||
name="Email"
|
||||
:rules="{
|
||||
required: true,
|
||||
email: true,
|
||||
is_not: $store.state.email,
|
||||
}"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<b-row>
|
||||
<b-col class="text-left p-3 p-sm-1">{{ $t('form.receiver') }}</b-col>
|
||||
<b-col v-if="errors" class="text-right p-3 p-sm-1">
|
||||
<span v-for="error in errors" :key="error" class="errors">{{ error }}</span>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-input-group
|
||||
id="input-group-1"
|
||||
label="Empfänger:"
|
||||
label-for="input-1"
|
||||
description="We'll never share your email with anyone else."
|
||||
size="lg"
|
||||
class="mb-3"
|
||||
>
|
||||
<b-input-group-prepend class="p-3 d-none d-md-block">
|
||||
<b-icon icon="envelope" class="display-3"></b-icon>
|
||||
</b-input-group-prepend>
|
||||
<b-form-input
|
||||
id="input-1"
|
||||
v-model="form.email"
|
||||
type="email"
|
||||
placeholder="E-Mail"
|
||||
style="font-size: xx-large; padding-left: 20px"
|
||||
></b-form-input>
|
||||
</b-input-group>
|
||||
</validation-provider>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<validation-provider
|
||||
:name="$t('form.amount')"
|
||||
:rules="{
|
||||
required: true,
|
||||
double: [2, $i18n.locale === 'de' ? ',' : '.'],
|
||||
between: [0.01, balance],
|
||||
}"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<b-row>
|
||||
<b-col class="text-left p-3 p-sm-1">{{ $t('form.amount') }}</b-col>
|
||||
<b-col v-if="errors" class="text-right p-3 p-sm-1">
|
||||
<span v-for="error in errors" class="errors" :key="error">{{ error }}</span>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-input-group
|
||||
id="input-group-2"
|
||||
label="Betrag:"
|
||||
label-for="input-2"
|
||||
size="lg"
|
||||
class="mb-3"
|
||||
>
|
||||
<b-input-group-prepend class="p-2 d-none d-md-block">
|
||||
<div class="h3 pt-3 pr-3">GDD</div>
|
||||
</b-input-group-prepend>
|
||||
<b-form-input
|
||||
id="input-2"
|
||||
v-model="form.amount"
|
||||
type="number"
|
||||
:lang="$i18n.locale"
|
||||
:placeholder="$n(0.01)"
|
||||
step="0.01"
|
||||
style="font-size: xx-large; padding-left: 20px"
|
||||
></b-form-input>
|
||||
</b-input-group>
|
||||
<b-col class="text-left p-3 p-sm-1">{{ $t('form.memo') }}</b-col>
|
||||
<b-input-group id="input-group-3">
|
||||
<b-input-group-prepend class="p-3 d-none d-md-block">
|
||||
<b-icon icon="chat-right-text" class="display-3"></b-icon>
|
||||
</b-input-group-prepend>
|
||||
<b-form-textarea
|
||||
rows="3"
|
||||
v-model="form.memo"
|
||||
class="pl-3"
|
||||
style="font-size: x-large"
|
||||
></b-form-textarea>
|
||||
</b-input-group>
|
||||
</validation-provider>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-button type="reset" variant="secondary" @click="onReset">
|
||||
{{ $t('form.reset') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
<b-col class="text-right">
|
||||
<b-button type="submit" variant="success">
|
||||
{{ $t('form.send_now') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<br />
|
||||
</b-form>
|
||||
</validation-observer>
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</template>
|
||||
<script>
|
||||
// import QrCode from './QrCode'
|
||||
// import { QrcodeDropZone } from 'vue-qrcode-reader'
|
||||
import { BIcon } from 'bootstrap-vue'
|
||||
|
||||
export default {
|
||||
name: 'TransactionForm',
|
||||
components: {
|
||||
BIcon,
|
||||
// QrCode,
|
||||
// QrcodeDropZone,
|
||||
},
|
||||
props: {
|
||||
balance: { type: Number, default: 0 },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
email: '',
|
||||
amount: '',
|
||||
memo: '',
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSubmit() {
|
||||
this.$emit('set-transaction', {
|
||||
email: this.form.email,
|
||||
amount: this.form.amount,
|
||||
memo: this.form.memo,
|
||||
})
|
||||
},
|
||||
onReset(event) {
|
||||
event.preventDefault()
|
||||
this.form.email = ''
|
||||
this.form.amount = ''
|
||||
this.form.memo = ''
|
||||
},
|
||||
setTransaction(data) {
|
||||
this.form.email = data.email
|
||||
this.form.amount = data.amount
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
span.errors {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<b-row v-if="!error">
|
||||
<b-col>
|
||||
<b-card class="p-0 p-md-3" style="background-color: #ebebeba3 !important">
|
||||
<div class="display-2 p-4">
|
||||
{{ $t('form.thx') }}
|
||||
<hr />
|
||||
{{ $t('form.send_transaction_success') }}
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<b-button variant="success" @click="$emit('on-reset')">{{ $t('form.close') }}</b-button>
|
||||
</p>
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row v-else>
|
||||
<b-col>
|
||||
<b-card class="p-0 p-md-3" style="background-color: #ebebeba3 !important">
|
||||
<div class="display-2 p-4">
|
||||
{{ $t('form.sorry') }}
|
||||
<hr />
|
||||
{{ $t('form.send_transaction_error') }}
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<b-button variant="success" @click="$emit('on-reset')">{{ $t('form.close') }}</b-button>
|
||||
</p>
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'TransactionResult',
|
||||
props: {
|
||||
error: { type: Boolean, default: true },
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -24,12 +24,30 @@ describe('GddStatus', () => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('it displays the ammount of GDD', () => {
|
||||
expect(wrapper.findAll('div.card-body').at(0).text()).toEqual('1234 GDD')
|
||||
describe('balance is loading', () => {
|
||||
it('it displays em-dash as the ammount of GDD', () => {
|
||||
expect(wrapper.findAll('div.card-body').at(0).text()).toEqual('— GDD')
|
||||
})
|
||||
|
||||
it('it displays em-dash as the ammount of GDT', () => {
|
||||
expect(wrapper.findAll('div.card-body').at(1).text()).toEqual('— GDT')
|
||||
})
|
||||
})
|
||||
|
||||
it('it displays the ammount of GDT', () => {
|
||||
expect(wrapper.findAll('div.card-body').at(1).text()).toEqual('9876 GDT')
|
||||
describe('balance is loaded', () => {
|
||||
beforeEach(() => {
|
||||
wrapper.setProps({
|
||||
pending: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('it displays the ammount of GDD', () => {
|
||||
expect(wrapper.findAll('div.card-body').at(0).text()).toEqual('1234 GDD')
|
||||
})
|
||||
|
||||
it('it displays the ammount of GDT', () => {
|
||||
expect(wrapper.findAll('div.card-body').at(1).text()).toEqual('9876 GDT')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -2,24 +2,14 @@
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<stats-card
|
||||
type="gradient-red"
|
||||
sub-title="balance_gdd"
|
||||
class="mb-4 h1"
|
||||
style="background-color: #ebebeba3 !important"
|
||||
>
|
||||
{{ $n(balance) }} GDD
|
||||
</stats-card>
|
||||
<b-card style="background-color: #ebebeba3 !important">
|
||||
{{ pending ? '—' : $n(balance) }} GDD
|
||||
</b-card>
|
||||
</b-col>
|
||||
<b-col>
|
||||
<stats-card
|
||||
type="gradient-orange"
|
||||
sub-title="balance_gdt"
|
||||
class="mb-4 h1"
|
||||
style="background-color: #ebebeba3 !important"
|
||||
>
|
||||
{{ $n(GdtBalance) }} GDT
|
||||
</stats-card>
|
||||
<b-card class="lg-h2 text-right" style="background-color: #ebebeba3 !important">
|
||||
{{ pending ? '—' : $n(GdtBalance) }} GDT
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
@ -31,6 +21,10 @@ export default {
|
||||
props: {
|
||||
balance: { type: Number, default: 0 },
|
||||
GdtBalance: { type: Number, default: 0 },
|
||||
pending: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -88,11 +88,9 @@
|
||||
</b-card>
|
||||
</b-collapse>
|
||||
</b-list-group-item>
|
||||
<b-list-group-item>
|
||||
<b-alert v-if="transactions.length === 0" show variant="secondary">
|
||||
<span class="alert-text">{{ $t('transaction.nullTransactions') }}</span>
|
||||
</b-alert>
|
||||
</b-list-group-item>
|
||||
<div v-if="transactions.length === 0" class="mt-lg-4 text-center">
|
||||
<span>{{ $t('transaction.nullTransactions') }}</span>
|
||||
</div>
|
||||
</b-list-group>
|
||||
</div>
|
||||
</template>
|
||||
@ -102,7 +100,7 @@ export default {
|
||||
name: 'GddTable',
|
||||
props: {
|
||||
transactions: { default: [] },
|
||||
max: { type: Number, default: 25 },
|
||||
max: { type: Number, default: 1000 },
|
||||
timestamp: { type: Number, default: 0 },
|
||||
transactionCount: { type: Number, default: 0 },
|
||||
},
|
||||
|
||||
@ -97,7 +97,6 @@
|
||||
</p>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<b-row class="my-4">
|
||||
<b-col cols="12">
|
||||
<base-input
|
||||
@ -164,12 +163,7 @@ export default {
|
||||
email: '',
|
||||
agree: false,
|
||||
},
|
||||
rules: [
|
||||
{ message: this.$t('site.signup.lowercase'), regex: /[a-z]+/ },
|
||||
{ message: this.$t('site.signup.uppercase'), regex: /[A-Z]+/ },
|
||||
{ message: this.$t('site.signup.minimum'), regex: /.{8,}/ },
|
||||
{ message: this.$t('site.signup.one_number'), regex: /[0-9]+/ },
|
||||
],
|
||||
|
||||
password: '',
|
||||
checkPassword: '',
|
||||
passwordVisible: false,
|
||||
@ -231,6 +225,14 @@ export default {
|
||||
emailFilled() {
|
||||
return this.model.email !== ''
|
||||
},
|
||||
rules() {
|
||||
return [
|
||||
{ message: this.$t('site.signup.lowercase'), regex: /[a-z]+/ },
|
||||
{ message: this.$t('site.signup.uppercase'), regex: /[A-Z]+/ },
|
||||
{ message: this.$t('site.signup.minimum'), regex: /.{8,}/ },
|
||||
{ message: this.$t('site.signup.one_number'), regex: /[0-9]+/ },
|
||||
]
|
||||
},
|
||||
passwordValidation() {
|
||||
const errors = []
|
||||
for (const condition of this.rules) {
|
||||
|
||||
@ -90,12 +90,6 @@ export default {
|
||||
name: 'reset',
|
||||
data() {
|
||||
return {
|
||||
rules: [
|
||||
{ message: this.$t('site.signup.lowercase'), regex: /[a-z]+/ },
|
||||
{ message: this.$t('site.signup.uppercase'), regex: /[A-Z]+/ },
|
||||
{ message: this.$t('site.signup.minimum'), regex: /.{8,}/ },
|
||||
{ message: this.$t('site.signup.one_number'), regex: /[0-9]+/ },
|
||||
],
|
||||
password: '',
|
||||
checkPassword: '',
|
||||
passwordVisible: false,
|
||||
@ -137,6 +131,14 @@ export default {
|
||||
passwordsFilled() {
|
||||
return this.password !== '' && this.checkPassword !== ''
|
||||
},
|
||||
rules() {
|
||||
return [
|
||||
{ message: this.$t('site.signup.lowercase'), regex: /[a-z]+/ },
|
||||
{ message: this.$t('site.signup.uppercase'), regex: /[A-Z]+/ },
|
||||
{ message: this.$t('site.signup.minimum'), regex: /.{8,}/ },
|
||||
{ message: this.$t('site.signup.one_number'), regex: /[0-9]+/ },
|
||||
]
|
||||
},
|
||||
passwordValidation() {
|
||||
const errors = []
|
||||
for (const condition of this.rules) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
class="header pb-8 pt-5 pt-lg-8 d-flex align-items-center profile-header"
|
||||
class="header pb-8 pt-lg-4 d-flex align-items-center profile-header"
|
||||
style="max-height: 200px"
|
||||
></div>
|
||||
<b-container fluid class="mt--6">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Header -->
|
||||
<div class="header bg-gradient-info py-7 py-lg-8 pt-lg-9">
|
||||
<div class="header py-7 py-lg-8 pt-lg-9">
|
||||
<b-container>
|
||||
<div class="header-body text-center mb-7">
|
||||
<p class="h1">{{ $t('site.thx.title') }}</p>
|
||||
@ -10,18 +10,6 @@
|
||||
<b-button to="/login">{{ $t('login') }}</b-button>
|
||||
</div>
|
||||
</b-container>
|
||||
<div class="separator separator-bottom separator-skew zindex-100">
|
||||
<svg
|
||||
x="0"
|
||||
y="0"
|
||||
viewBox="0 0 2560 100"
|
||||
preserveAspectRatio="none"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon class="fill-default" points="2560 0 2560 100 0 100"></polygon>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Page content -->
|
||||
</div>
|
||||
|
||||
@ -134,6 +134,9 @@ int Gradido_LoginServer::main(const std::vector<std::string>& args)
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
log_Path = "./";
|
||||
#endif
|
||||
if (mConfigPath != "") {
|
||||
log_Path = "./";
|
||||
}
|
||||
|
||||
// init speed logger
|
||||
Poco::AutoPtr<Poco::SimpleFileChannel> speedLogFileChannel(new Poco::SimpleFileChannel(log_Path + "speedLog.txt"));
|
||||
@ -165,10 +168,14 @@ int Gradido_LoginServer::main(const std::vector<std::string>& args)
|
||||
createConsoleFileAsyncLogger("emailLog", log_Path + "emailLog.txt");
|
||||
|
||||
// *************** load from config ********************************************
|
||||
|
||||
|
||||
std::string cfg_Path = Poco::Path::config() + "grd_login/";
|
||||
try {
|
||||
loadConfiguration(cfg_Path + "grd_login.properties");
|
||||
if(mConfigPath != "") {
|
||||
loadConfiguration(mConfigPath);
|
||||
} else {
|
||||
loadConfiguration(cfg_Path + "grd_login.properties");
|
||||
}
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
errorLog.error("error loading config: %s", ex.displayText());
|
||||
@ -295,4 +302,4 @@ int Gradido_LoginServer::main(const std::vector<std::string>& args)
|
||||
|
||||
}
|
||||
return Application::EXIT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,6 +382,7 @@ int HandleElopageRequestTask::run()
|
||||
DataTypeConverter::strToInt(mRequestData.get("noEmail", "0"), noEMail);
|
||||
|
||||
if (noEMail != 1) {
|
||||
emailVerification->setBaseUrl(ServerConfig::g_serverPath + "/checkEmail");
|
||||
em->addEmail(new model::Email(emailVerification, newUser, model::EMAIL_USER_VERIFICATION_CODE));
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include "Poco/DeflatingStream.h"
|
||||
|
||||
|
||||
#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 6 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
|
||||
#include "../SingletonManager/LanguageManager.h"
|
||||
#include "../SingletonManager/SessionManager.h"
|
||||
@ -20,7 +20,7 @@ enum PageState {
|
||||
PAGE_WAIT_ADMIN,
|
||||
PAGE_EMAIL_ALREADY_SEND
|
||||
};
|
||||
#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 1 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
|
||||
#include "../ServerConfig.h"
|
||||
|
||||
@ -33,7 +33,7 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
if (_compressResponse) response.set("Content-Encoding", "gzip");
|
||||
|
||||
Poco::Net::HTMLForm form(request, request.stream());
|
||||
#line 20 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 20 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
|
||||
PageState state = PAGE_EMAIL_ASK;
|
||||
auto lm = LanguageManager::getInstance();
|
||||
@ -95,7 +95,7 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
// send reset password email
|
||||
int result = 0;
|
||||
if(user_exist) {
|
||||
result = session->sendResetPasswordEmail(user, sendUserEmail, getBaseUrl());
|
||||
result = session->sendResetPasswordEmail(user, sendUserEmail, ServerConfig::g_serverPath + "/checkEmail");
|
||||
}
|
||||
|
||||
if(2 == result) {
|
||||
@ -116,7 +116,7 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
}
|
||||
|
||||
|
||||
#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 3 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
|
||||
bool withMaterialIcons = false;
|
||||
std::ostream& _responseStream = response.send();
|
||||
@ -131,20 +131,20 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
responseStream << "<meta charset=\"UTF-8\">\n";
|
||||
responseStream << "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n";
|
||||
responseStream << "<title>Gradido Login Server: ";
|
||||
#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 11 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
responseStream << ( pageName );
|
||||
responseStream << "</title>\n";
|
||||
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"";
|
||||
#line 12 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 12 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "css/main.css\">\n";
|
||||
#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 13 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
if(withMaterialIcons) { responseStream << "\n";
|
||||
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"";
|
||||
#line 14 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 14 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "css/materialdesignicons.min.css\">\n";
|
||||
#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 15 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
} responseStream << "\n";
|
||||
responseStream << "</head>\n";
|
||||
responseStream << "<body>\n";
|
||||
@ -152,20 +152,20 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
responseStream << " <div class=\"center-form-single\">\n";
|
||||
responseStream << " <div class=\"center-form-header\">\n";
|
||||
responseStream << " <a href=\"";
|
||||
#line 21 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 21 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "\" class=\"center-logo\">\n";
|
||||
responseStream << " <picture>\n";
|
||||
responseStream << " <source srcset=\"";
|
||||
#line 23 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 23 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "img/logo_schrift.webp\" type=\"image/webp\">\n";
|
||||
responseStream << " <source srcset=\"";
|
||||
#line 24 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 24 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "img/logo_schrift.png\" type=\"image/png\">\n";
|
||||
responseStream << " <img src=\"";
|
||||
#line 25 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
|
||||
#line 25 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "img/logo_schrift.png\" alt=\"logo\" />\n";
|
||||
responseStream << " </picture>\n";
|
||||
@ -174,7 +174,7 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
// end include header.cpsp
|
||||
responseStream << "\n";
|
||||
responseStream << " ";
|
||||
#line 103 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 103 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( getErrorsHtml() );
|
||||
responseStream << "\n";
|
||||
responseStream << "\t <div class=\"center-form-container\">\n";
|
||||
@ -182,36 +182,36 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
responseStream << "\t <h1>Passwort zurücksetzen</h1>\n";
|
||||
responseStream << "\t </div>\n";
|
||||
responseStream << " ";
|
||||
#line 108 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 108 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
if(state == PAGE_EMAIL_ASK) { responseStream << "\n";
|
||||
responseStream << " <div class=\"center-form-form\">\n";
|
||||
responseStream << "\t\t\t\t<form action=\"";
|
||||
#line 110 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 110 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( getBaseUrl() );
|
||||
responseStream << "/resetPassword\">\n";
|
||||
responseStream << "\t\t\t\t\t<div class=\"item-wrapper\">\n";
|
||||
responseStream << "\t\t\t\t\t <div class=\"form-group\">\n";
|
||||
responseStream << "\t\t\t\t\t\t<label class=\"form-label\" for=\"email\">";
|
||||
#line 113 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 113 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Gib bitte hier deine E-Mail Adresse an:") );
|
||||
responseStream << "</label>\n";
|
||||
responseStream << "\t\t\t\t\t\t<input class=\"form-control\" type=\"text\" class=\"";
|
||||
#line 114 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 114 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( emailInputClass );
|
||||
responseStream << "\" name=\"email\" id=\"email\" placeholder=\"E-Mail\" value=\"";
|
||||
#line 114 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 114 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( email );
|
||||
responseStream << "\">\n";
|
||||
responseStream << "\t\t\t\t\t </div>\n";
|
||||
responseStream << "\t\t\t\t\t <button type=\"submit\" class=\"center-form-submit form-button\" >";
|
||||
#line 116 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 116 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Bestätigen") );
|
||||
responseStream << "</button>\n";
|
||||
responseStream << "\t\t\t\t\t</div>\n";
|
||||
responseStream << "\t\t\t\t</form>\n";
|
||||
responseStream << "\t\t\t</div>\n";
|
||||
responseStream << "\t";
|
||||
#line 120 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 120 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
} else if(state == PAGE_ASK) { responseStream << "\n";
|
||||
responseStream << " <div class=\"center-form-form\">\n";
|
||||
responseStream << "\t\t\t\t";
|
||||
@ -219,22 +219,22 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
responseStream << "<div class=\"center-form-selectors\">\n";
|
||||
responseStream << "<form method=\"GET\" action=\"\">\n";
|
||||
responseStream << "\t<button id=\"flag-england\" name=\"lang\" value=\"en\" title=\"English\" type=\"submit\" ";
|
||||
#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\flags.cpsp"
|
||||
#line 3 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
|
||||
if(lang != LANG_EN) { responseStream << "class=\"flag-btn\"";
|
||||
#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\flags.cpsp"
|
||||
#line 3 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
|
||||
}
|
||||
else { responseStream << "class=\"flag-btn\" disabled";
|
||||
#line 4 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\flags.cpsp"
|
||||
#line 4 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
|
||||
} responseStream << ">\n";
|
||||
responseStream << "\t <span class=\"flag flag-england\"></span>\n";
|
||||
responseStream << "\t</button>\n";
|
||||
responseStream << "\t<button id=\"flag-germany\" name=\"lang\" value=\"de\" title=\"Deutsch\" type=\"submit\" ";
|
||||
#line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\flags.cpsp"
|
||||
#line 7 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
|
||||
if(lang != LANG_DE) { responseStream << "class=\"flag-btn\"";
|
||||
#line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\flags.cpsp"
|
||||
#line 7 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
|
||||
}
|
||||
else { responseStream << "class=\"flag-btn\" disabled";
|
||||
#line 8 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\flags.cpsp"
|
||||
#line 8 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
|
||||
} responseStream << ">\n";
|
||||
responseStream << "\t <span class=\"flag flag-germany\"></span>\n";
|
||||
responseStream << "\t</button>\n";
|
||||
@ -243,33 +243,33 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
// end include flags.cpsp
|
||||
responseStream << "\n";
|
||||
responseStream << "\t\t\t\t<form action=\"";
|
||||
#line 123 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 123 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( getBaseUrl() );
|
||||
responseStream << "/resetPassword\">\n";
|
||||
responseStream << "\t\t\t\t\t<label class=\"form-label\" for=\"email\">";
|
||||
#line 124 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 124 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Gib bitte hier deine E-Mail Adresse an:") );
|
||||
responseStream << "</label>\n";
|
||||
responseStream << "\t\t\t\t\t<input class=\"form-control\" type=\"text\" class=\"";
|
||||
#line 125 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 125 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( emailInputClass );
|
||||
responseStream << "\" name=\"email\" id=\"email\" placeholder=\"E-Mail\" value=\"";
|
||||
#line 125 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 125 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( email );
|
||||
responseStream << "\">\n";
|
||||
responseStream << "\t\t\t\t\t<label>";
|
||||
#line 126 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 126 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Hast du dir deine Passphrase notiert oder gemerkt?") );
|
||||
responseStream << "</label>\n";
|
||||
responseStream << "\t\t\t\t\t<input class=\"form-control\" type=\"hidden\" name=\"ask_passphrase\" value=\"true\">\n";
|
||||
responseStream << "\t\t\t\t\t<div class=\"";
|
||||
#line 128 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 128 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( passphraseRadioClass );
|
||||
responseStream << "\">\n";
|
||||
responseStream << "\t\t\t\t\t\t<div class=\"radio\">\n";
|
||||
responseStream << "\t\t\t\t\t\t <label class=\"form-label\" class=\"radio-label mr-4\">\n";
|
||||
responseStream << "\t\t\t\t\t\t\t<input class=\"form-control\" name=\"passphrase_memorized\" onclick=\"removeGroupInvalidClass()\" type=\"radio\" value=\"true\">";
|
||||
#line 131 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 131 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Ja") );
|
||||
responseStream << " <i class=\"input-frame\"></i>\n";
|
||||
responseStream << "\t\t\t\t\t\t </label>\n";
|
||||
@ -277,53 +277,53 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
responseStream << "\t\t\t\t\t\t<div class=\"radio\">\n";
|
||||
responseStream << "\t\t\t\t\t\t <label class=\"form-label\" class=\"radio-label\">\n";
|
||||
responseStream << "\t\t\t\t\t\t\t<input class=\"form-control\" name=\"passphrase_memorized\" onclick=\"removeGroupInvalidClass()\" type=\"radio\" value=\"false\">";
|
||||
#line 136 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 136 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Nein") );
|
||||
responseStream << " <i class=\"input-frame\"></i>\n";
|
||||
responseStream << "\t\t\t\t\t\t </label>\n";
|
||||
responseStream << "\t\t\t\t\t\t</div>\n";
|
||||
responseStream << "\t\t\t\t\t</div>\n";
|
||||
responseStream << "\t\t\t\t\t <button type=\"submit\" class=\"center-form-submit form-button\" name=\"ask\" >";
|
||||
#line 140 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 140 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Absenden") );
|
||||
responseStream << "</button>\n";
|
||||
responseStream << "\t\t\t\t\t</div>\n";
|
||||
responseStream << "\t\t\t\t</form>\n";
|
||||
responseStream << "\t\t\t</div>\n";
|
||||
responseStream << "\t ";
|
||||
#line 144 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 144 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
} else if(state == PAGE_WAIT_EMAIL) { responseStream << "\n";
|
||||
responseStream << "\t\t\t";
|
||||
#line 145 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 145 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Dir wird eine E-Mail zugeschickt um dein Passwort zurückzusetzen.") );
|
||||
responseStream << "\n";
|
||||
responseStream << "\t ";
|
||||
#line 146 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 146 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
} else if(state == PAGE_WAIT_ADMIN) { responseStream << "\n";
|
||||
responseStream << "\t\t\t";
|
||||
#line 147 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 147 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Der Admin hat eine E-Mail bekommen und wird sich bei dir melden.") );
|
||||
responseStream << "\n";
|
||||
responseStream << "\t ";
|
||||
#line 148 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 148 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
} else if(state == PAGE_EMAIL_ALREADY_SEND) { responseStream << "\n";
|
||||
responseStream << "\t\t\t<p>";
|
||||
#line 149 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 149 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Du hast bereits eine E-Mail bekommen. Bitte schau auch in dein Spam-Verzeichnis nach. ") );
|
||||
responseStream << "</p>\n";
|
||||
responseStream << "\t\t\t<p>";
|
||||
#line 150 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 150 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Du hast wirklich keine E-Mail erhalten und auch schon ein paar Minuten gewartet?") );
|
||||
responseStream << "</p>\n";
|
||||
responseStream << "\t\t\t<p><b><a href=\"mailto:";
|
||||
#line 151 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 151 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( adminReceiver );
|
||||
responseStream << "?subject=Error Reset Password email&body=Hallo Dario,%0D%0A%0D%0Aich habe keine Passwort zurücksetzen E-Mail erhalten,%0D%0Akannst du das prüfen?%0D%0A%0D%0AMit freundlichen Grüßen%0D%0A\">";
|
||||
#line 151 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 151 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
responseStream << ( langCatalog->gettext("E-Mail an Support schicken"));
|
||||
responseStream << "</a></b></p>\n";
|
||||
responseStream << "\t ";
|
||||
#line 152 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
#line 152 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\resetPassword.cpsp"
|
||||
} responseStream << "\n";
|
||||
responseStream << " </div>\n";
|
||||
responseStream << " </div>\n";
|
||||
@ -345,14 +345,14 @@ void ResetPassword::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::N
|
||||
responseStream << " </div>\n";
|
||||
responseStream << " <div class=\"bottomleft\">\n";
|
||||
responseStream << " ";
|
||||
#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp"
|
||||
#line 6 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\footer.cpsp"
|
||||
responseStream << ( mTimeProfiler.string() );
|
||||
responseStream << "\n";
|
||||
responseStream << " </div>\n";
|
||||
responseStream << " <div class=\"bottomright\">\n";
|
||||
responseStream << " <p>Login Server in Entwicklung</p>\n";
|
||||
responseStream << " <p>Alpha ";
|
||||
#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp"
|
||||
#line 10 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\footer.cpsp"
|
||||
responseStream << ( ServerConfig::g_versionString );
|
||||
responseStream << "</p>\n";
|
||||
responseStream << " </div>\n";
|
||||
|
||||
@ -100,7 +100,9 @@ Poco::JSON::Object* JsonAdminEmailVerificationResend::handle(Poco::Dynamic::Var
|
||||
if (emailVerification.isNull()) {
|
||||
return stateError("no email verification code found");
|
||||
}
|
||||
|
||||
emailVerification->getModel()->insertIntoDB(false);
|
||||
emailVerification->setBaseUrl(ServerConfig::g_serverPath + "/checkEmail");
|
||||
em->addEmail(new model::Email(emailVerification, receiverUser, model::EMAIL_ADMIN_USER_VERIFICATION_CODE_RESEND));
|
||||
return stateSuccess();
|
||||
|
||||
|
||||
@ -109,7 +109,7 @@ Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params)
|
||||
emailOptInModel->sendErrorsAsEmail();
|
||||
return stateError("insert emailOptIn failed");
|
||||
}
|
||||
emailOptIn->setBaseUrl(mServerHost + "/" + ServerConfig::g_frontend_checkEmailPath);
|
||||
emailOptIn->setBaseUrl(user->getGroupBaseUrl() + ServerConfig::g_frontend_checkEmailPath);
|
||||
em->addEmail(new model::Email(emailOptIn, user, model::Email::convertTypeFromInt(emailType)));
|
||||
|
||||
if (login_after_register && session) {
|
||||
|
||||
@ -69,8 +69,8 @@ namespace controller {
|
||||
|
||||
using namespace Poco::Data::Keywords;
|
||||
Poco::Data::Statement select(session);
|
||||
// typedef Poco::Tuple<std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, int> UserTuple;
|
||||
select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked, disabled FROM " << db->getTableName();
|
||||
// typedef Poco::Tuple<int, std::string, std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, Poco::DateTime, int, int, int> UserTuple;
|
||||
select << "SELECT id, first_name, last_name, email, username, pubkey, created, email_checked, disabled, group_id FROM " << db->getTableName();
|
||||
select << " where email_checked = 0 ";
|
||||
select, into(resultFromDB);
|
||||
if (searchString != "") {
|
||||
|
||||
@ -78,7 +78,7 @@ enum PageState {
|
||||
// send reset password email
|
||||
int result = 0;
|
||||
if(user_exist) {
|
||||
result = session->sendResetPasswordEmail(user, sendUserEmail, getBaseUrl());
|
||||
result = session->sendResetPasswordEmail(user, sendUserEmail, ServerConfig::g_serverPath + "/checkEmail");
|
||||
}
|
||||
|
||||
if(2 == result) {
|
||||
|
||||
@ -3,12 +3,12 @@ COLOR_GREEN="\033[0;32m"
|
||||
COLOR_YELLOW="\e[33m"
|
||||
COLOR_NONE="\033[0m"
|
||||
|
||||
LOGIN_DB_USER=gradido_login
|
||||
LOGIN_DB_NAME=gradido_login
|
||||
LOGIN_DB_USER=gradido_login_live
|
||||
LOGIN_DB_NAME=gradido_login_live
|
||||
LOGIN_DB_PASSWD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo);
|
||||
|
||||
COMMUNITY_DB_USER=gradido_community
|
||||
COMMUNITY_DB_NAME=gradido_community
|
||||
COMMUNITY_DB_USER=gradido_community_live
|
||||
COMMUNITY_DB_NAME=gradido_community_live
|
||||
COMMUNITY_DB_PASSWD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo);
|
||||
|
||||
# create table
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gradido",
|
||||
"version": "0.9.4",
|
||||
"version": "1.0.1",
|
||||
"description": "Gradido",
|
||||
"main": "index.js",
|
||||
"repository": "git@github.com:gradido/gradido.git",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user