This commit is contained in:
Pauls Jakovels 2021-03-04 13:07:01 +02:00
commit 3e00e73386
49 changed files with 1022 additions and 660 deletions

12
.github/workflows/push.yml vendored Normal file
View File

@ -0,0 +1,12 @@
name: on-push
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build the stack
run: docker-compose up -d
- name: Test
run: docker run gradido-node-test
timeout-minutes: 2

View File

@ -47,3 +47,5 @@ session.timeout = 15
unsecure.allow_passwort_via_json_request = 1
unsecure.allow_auto_sign_transactions = 1
unsecure.allow_cors_all = 1
# default disable, passwords must contain a number, a lower character, a high character, special character, and be at least 8 characters long
unsecure.allow_all_passwords = 1

View File

@ -0,0 +1,20 @@
worker_count = 2
io_worker_count = 1
data_root_folder = /opt/instance/.gradido
hedera_mirror_endpoint = hcs.testnet.mirrornode.hedera.com:5600
sibling_node_file = /opt/instance/.gradido/sibling_nodes.txt
#group_requests_endpoint = 0.0.0.0:13701
#record_requests_endpoint = 0.0.0.0:13702
#manage_network_requests_endpoint = 0.0.0.0:13703
grpc_endpoint = 0.0.0.0:13701
json_rpc_port = 13702
# larger value, larger batch, less concurrency
blockchain_append_batch_size = 1000
#blochchain_init_batch_size = 1000
#block_record_outbound_batch_size = 100
general_batch_size = 1000
group_register_topic_id = 0.0.79574
topic_reset_allowed = 1

View File

@ -49,7 +49,7 @@ services:
container_name: phpmyadmin
environment:
- PMA_ARBITRARY=1
restart: always
#restart: always
ports:
- 8074:80
networks:

View File

@ -47,13 +47,20 @@ Registrieren kannst du einen neuen Benutzer mit:
POST http://localhost/login_api/createUser
```json
data: {"email":"max.musterman@gmail.de", "first_name":"Max", "last_name":"Musterman" ,
"emailType": 2, "password":"123abcDE&"}
data: {
"email":"max.musterman@gmail.de",
"first_name":"Max",
"last_name":"Musterman" ,
"emailType": 2,
"password":"123abcDE&"
"login_after_register":true
}
```
- emailType: control email-text sended with email verification code
- 2: default, if user has registered directly
- 5: if user was registered by an admin
- login_after_register: if set to true auto-login after create user was successfull, means session cookie is set and session_id returned
Wenn alles okay ist erhältst du:
```json

View File

@ -1,14 +1,14 @@
# Vue Gradido Wallet
## install mit npm
## install mit yarn
```bash
cd frontend
npm install
npm run serve
yarn install
yarn run serve
# build
npm run build
yarn run build
```
## install mit docker

View File

@ -42,7 +42,9 @@
"vue-flatpickr-component": "^8.1.2",
"vue-good-table": "^2.21.3",
"vue-i18n": "^8.22.4",
"qrcode": "^1.4.4",
"vue-qrcode-reader": "^2.3.16",
"vue-qrcode": "^0.3.5",
"vue-router": "^3.0.6",
"vue2-transitions": "^0.2.3",
"vuex": "^3.6.0"
@ -52,6 +54,7 @@
"@vue/cli-plugin-eslint": "^3.7.0",
"@vue/cli-service": "^3.7.0",
"@vue/eslint-config-prettier": "^4.0.1",
"babel-eslint": "^10.1.0",
"babel-plugin-component": "^1.1.0",
"node-sass": "^4.12.0",
"sass-loader": "^7.1.0",

View File

@ -13,43 +13,14 @@
export default {
name: 'app',
created () {
if (this.$cookies.get('gdd_is_auth') == 'true' && this.$store.state.is_auth == true) {
this.$store.state.user.email = this.$cookies.get('gdd_email')
// if ( this.$store.state.is_auth == false && this.$store.state.is_admin == false) {
// this.$router.push("/Landing")
// } else {
this.$router.push('/KontoOverview')
// }
}else {
this.$router.push("/Landing")
}
//var user = { id:1, name:'Journal',session:'25j_7Sl6xDq2Kc3ym0fmrSSk2xV2XkUkX' };
//this.$cookies.set('user',user);
//// print user name
//console.log("APP.vue START created get cookie is_auth=>",this.$cookies.get('gdd_is_auth'))
},
methods: {
/*
login() {
//console.log("app.vue user login() : " + this.$store.state.is_auth)
this.$store.commit('login')
//this.$router.push('/KontoOverview')
},
loginAsAdmin () {
// console.log("app.vue admin login(): " + this.$store.state.is_admin)
this.$store.state.modals = true
//this.$store.commit('loginAsAdmin')
//this.$router.push('/AdminOverview')
},
logout(){
// console.log("app.vue user logout() : ")
this.$store.commit('logout')
}
*/
//console.log("this.$cookies.get('gdd_session_id') ", this.$cookies.get('gdd_session_id') )
//console.log(" $cookies.isKey('gdd_session_id') == true", this.$cookies.isKey("gdd_session_id") == true )
if ( this.$cookies.get('gdd_session_id') == this.$store.state.session_id ) {
//this.$store.state.email = this.$cookies.get('gdd_u')
this.$router.push('/KontoOverview')
}else {
this.$router.push("/Login")
}
}
}
</script>

View File

@ -0,0 +1,57 @@
import axios from 'axios';
// TODO move this
const COMMUNITY_API_STATE_BALANCE_URL = 'http://localhost/state-balances/'
const COMMUNITY_API_TRANSACTION_CREATION_URL = 'http://localhost/transaction-creations/'
const apiGet = async (url) => {
try {
const result = await axios.get(url);
if(result.status !== 200){
throw new Error('HTTP Status Error '+result.status)
}
if(result.data.state !== 'success'){
throw new Error(result.data.msg)
}
return { success: true, result }
} catch(error){
return { success: false, result: error}
}
}
const apiPost = async (url, payload) => {
try {
const result = await axios.post(url, payload);
if(result.status !== 200){
throw new Error('HTTP Status Error '+result.status)
}
if(result.data.state !== 'success'){
throw new Error(result.data.msg)
}
return { success: true, result }
} catch(error){
return { success: false, result: error}
}
}
const communityAPI = {
balance: async (session_id) => {
return apiGet(COMMUNITY_API_STATE_BALANCE_URL + 'ajaxGetBalance/' + session_id)
},
transactions: async (session_id) => {
return apiGet(COMMUNITY_API_STATE_BALANCE_URL + 'ajaxListTransactions/' + session_id)
},
create: async (session_id, email, amount, memo, target_date = new Date() ) => {
const payload = {
session_id,
email,
amount,
target_date,
memo,
auto_sign: true
}
return apiPost(COMMUNITY_API_TRANSACTION_CREATION_URL + 'ajaxCreate/', payload)
}
}
export default communityAPI

View File

@ -0,0 +1,52 @@
import axios from 'axios';
// TODO move this
const LOGIN_API_URL = 'http://localhost/login_api/'
// control email-text sended with email verification code
const EMAIL_TYPE = {
DEFAULT: 2, // if user has registered directly
ADMIN: 5, // if user was registered by an admin
}
const apiPost = async (url, payload) => {
try {
const result = await axios.post(url, payload);
if(result.status !== 200){
throw new Error('HTTP Status Error '+result.status)
}
if(result.data.state !== 'success'){
throw new Error(result.data.msg)
}
return { success: true, result }
} catch(error){
return { success: false, result: error}
}
}
const loginAPI = {
login: async (email, password) => {
const payload = {
email,
password,
}
return apiPost(LOGIN_API_URL + 'unsecureLogin', payload)
},
logout: async (session_id) => {
const payload= { session_id }
return apiPost(LOGIN_API_URL + 'logout', payload)
},
create : async (email, first_name, last_name, password) => {
const payload = {
email,
first_name,
last_name,
password,
emailType: EMAIL_TYPE.DEFAULT,
login_after_register: true
}
return apiPost(LOGIN_API_URL + 'createUser', payload)
},
}
export default loginAPI

View File

@ -13,7 +13,6 @@
<td
v-for="(column, index) in columns"
:key="index"
v-if="hasValue(item, column)"
>
{{ itemValue(item, column) }}
</td>

View File

@ -66,6 +66,7 @@
if (this.inline) {
return `form-check-inline`;
}
return ''
}
},
created() {

View File

@ -159,10 +159,10 @@
},
setLocale(locale) {
this.$i18n.locale = locale
this.$router.push({
params: { lang: locale }
})
this.hideDropdown()
//this.$router.push({
// params: { lang: locale }
//})
//this.hideDropdown()
}
},
beforeDestroy() {

View File

@ -116,6 +116,7 @@ export default {
let words = this.link.name.split(' ');
return words.map(word => word.substring(0, 1)).join('');
}
return ''
},
isMenu() {
return this.children.length > 0 || this.menu === true;

View File

@ -1,126 +0,0 @@
<template>
<div class="relative">
<button
href="#"
class="flex items-center"
@click="toggleVisibility"
@keydown.space.exact.prevent="toggleVisibility"
@keydown.esc.exact="hideDropdown"
@keydown.shift.tab="hideDropdown"
@keydown.up.exact.prevent="startArrowKeys"
@keydown.down.exact.prevent="startArrowKeys"
>
<img :src="`/flag_${$i18n.locale}.svg`" alt="flag" class="w-8 h-8">
<span class="ml-2">{{ $i18n.locale.toUpperCase() }}</span>
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path class="heroicon-ui" d="M15.3 9.3a1 1 0 0 1 1.4 1.4l-4 4a1 1 0 0 1-1.4 0l-4-4a1 1 0 0 1 1.4-1.4l3.3 3.29 3.3-3.3z"></path></svg>
</button>
<transition name="dropdown-fade">
<ul v-on-clickaway="hideDropdown" v-if="isVisible" ref="dropdown" class="absolute normal-case z-30 font-normal xs:left-0 lg:right-0 bg-white shadow overflow-hidden rounded w-48 border mt-2 py-1 lg:z-20">
<li>
<a
href="#"
@click.prevent="setLocale('en')"
ref="account"
class="flex items-center px-3 py-3 hover:bg-gray-200"
@keydown.up.exact.prevent=""
@keydown.tab.exact="focusNext(false)"
@keydown.down.exact.prevent="focusNext(true)"
@keydown.esc.exact="hideDropdown"
>
<img src="/flag_en.svg" alt="english flag" class="h-8 w-8">
<span class="ml-2">English</span>
</a>
</li>
<!-- <li>
<a
href="#"
class="flex items-center px-3 py-3 hover:bg-gray-200"
@keydown.tab.exact="focusNext(false)"
@keydown.shift.tab="focusPrevious(false)"
@keydown.up.exact.prevent="focusPrevious(true)"
@keydown.down.exact.prevent="focusNext(true)"
@keydown.esc.exact="hideDropdown"
>
<svg fill="currentColor" class="text-gray-600" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path class="heroicon-ui" d="M12 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm1-11v2h1a3 3 0 0 1 0 6h-1v1a1 1 0 0 1-2 0v-1H8a1 1 0 0 1 0-2h3v-2h-1a3 3 0 0 1 0-6h1V6a1 1 0 0 1 2 0v1h3a1 1 0 0 1 0 2h-3zm-2 0h-1a1 1 0 1 0 0 2h1V9zm2 6h1a1 1 0 0 0 0-2h-1v2z"></path></svg>
<span class="ml-2">Billing</span>
</a>
</li> -->
<li>
<a
href="#"
@click.prevent="setLocale('de')"
class="flex items-center px-3 py-3 hover:bg-gray-200"
@keydown.shift.tab="focusPrevious(false)"
@keydown.up.exact.prevent="focusPrevious(true)"
@keydown.down.exact.prevent=""
@keydown.tab.exact="hideDropdown"
@keydown.esc.exact="hideDropdown"
>
<img src="/flag_de.svg" alt="english flag" class="h-8 w-8">
<span class="ml-2">Deutsch</span>
</a>
</li>
</ul>
</transition>
</div>
</template>
<script>
import { mixin as clickaway } from 'vue-clickaway'
export default {
mixins: [ clickaway ],
data() {
return {
isVisible: false,
focusedIndex: 0,
}
},
methods: {
toggleVisibility() {
this.isVisible = !this.isVisible
},
hideDropdown() {
this.isVisible = false
this.focusedIndex = 0
},
startArrowKeys() {
if (this.isVisible) {
// this.$refs.account.focus()
this.$refs.dropdown.children[0].children[0].focus()
}
},
focusPrevious(isArrowKey) {
this.focusedIndex = this.focusedIndex - 1
if (isArrowKey) {
this.focusItem()
}
},
focusNext(isArrowKey) {
this.focusedIndex = this.focusedIndex + 1
if (isArrowKey) {
this.focusItem()
}
},
focusItem() {
this.$refs.dropdown.children[this.focusedIndex].children[0].focus()
},
setLocale(locale) {
this.$i18n.locale = locale
this.$router.push({
params: { lang: locale }
})
this.hideDropdown()
}
}
}
</script>
<style scoped>
.dropdown-fade-enter-active, .dropdown-fade-leave-active {
transition: all .1s ease-in-out;
}
.dropdown-fade-enter, .dropdown-fade-leave-to {
opacity: 0;
transform: translateY(-12px);
}
</style>

View File

@ -16,8 +16,23 @@ function loadLocaleMessages () {
return messages
}
const numberFormats = {
'en-US': {
currency: {
style: 'currency'
}
},
'de-DE': {
currency: {
style: 'currency'
}
}
}
export default new VueI18n({
locale: 'en',
fallbackLocale: 'en',
messages: loadLocaleMessages()
messages: loadLocaleMessages(),
numberFormats
})

View File

@ -1,19 +0,0 @@
// TODO move this
const LOGIN_API_URL = 'http://localhost/login_api/'
// define a mixin object
const loginAPI = {
mutations: {
login: async () => {
return axios.post(LOGIN_API_URL + 'unsecureLogin', data);
},
creatUser : async () => {
return axios.post(LOGIN_API_URL + 'createUser', data);
},
logout: async () => {
return axios.post(LOGIN_API_URL + 'logout', data);
},
}
}
export default loginAPI

View File

@ -27,6 +27,7 @@ import * as rules from 'vee-validate/dist/rules';
import { messages } from 'vee-validate/dist/locale/en.json';
import VueQrcodeReader from "vue-qrcode-reader";
import VueQrcode from "vue-qrcode";
import VueGoodTablePlugin from 'vue-good-table';
@ -50,6 +51,7 @@ export default {
Vue.use(IconsPlugin);
Vue.use(VueGoodTablePlugin);
Vue.use(VueQrcodeReader);
Vue.use(VueQrcode);
configure({
classes: {
valid: 'is-valid',

View File

@ -1,7 +1,6 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes'
import {store} from '../store/store';
Vue.use(VueRouter)
@ -26,22 +25,7 @@ router.beforeEach((to, from, next) => {
if (!language) {
language = 'de'
}
//console.log("----------------")
//("ROUTER.js to", to)
//console.log("ROUTER.js store.state.is_auth", store.state.is_auth)
//console.log("ROUTER.js store.commit('isActive')", store.commit('isActive'))
//if (store.commit('isActive') ) {
// next()
//} else {
// next("/login")
//}
//console.log(from)
//console.log(next)
next()
next()
})
export default router
export default router

View File

@ -8,20 +8,24 @@ import NotFound from '@/views/NotFoundPage.vue'
const routes = [
{
path: '/',
redirect: 'landing',
redirect: 'login',
component: AuthLayoutGDD,
children: [
{
path: '/Landing',
name: 'Landing',
component: () => import(/* webpackChunkName: "demo" */ '../views/Landing.vue')
},
{
path: '/login',
name: 'login',
component: () => import(/* webpackChunkName: "demo" */ '../views/Pages/Login.vue')
component: () => import('../views/Pages/Login.vue')
},
{
path: '/thx',
name: 'Thanks',
component: () => import('../views/Pages/thx.vue')
},
{
path: '/register',
name: 'register',
component: () => import('../views/Pages/Register.vue')
},
]
},
{
@ -32,7 +36,7 @@ const routes = [
{
path: '/KontoOverview',
name: 'Kontoübersicht',
component: () => import(/* webpackChunkName: "demo" */ '../views/KontoOverview.vue'),
component: () => import('../views/KontoOverview.vue'),
meta: {
requiresAuth: true
}
@ -40,13 +44,18 @@ const routes = [
{
path: '/profile',
name: 'profile',
component: () => import(/* webpackChunkName: "demo" */ '../views/Pages/UserProfile.vue')
},
component: () => import('../views/Pages/UserProfileCard.vue')
},
{
path: '/register',
name: 'register',
component: () => import(/* webpackChunkName: "demo" */ '../views/Pages/Register.vue')
},
path: '/profileedit',
name: 'profileedit',
component: () => import('../views/Pages/UserProfileEdit.vue')
},
{
path: '/activity',
name: 'activity',
component: () => import('../views/Pages/UserProfileActivity.vue')
}
]
},
,
@ -58,7 +67,7 @@ const routes = [
{
path: '/AdminOverview',
name: 'Adminübersicht',
component: () => import(/* webpackChunkName: "demo" */ '../views/AdminOverview.vue'),
component: () => import('../views/AdminOverview.vue'),
meta: {
requiresAuth: true
}

View File

@ -1,92 +1,133 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import axios from 'axios';
import VueCookies from 'vue-cookies';
import router from '../routes/router.js';
import router from '../routes/router.js'
import loginAPI from '../apis/loginAPI'
import communityAPI from '../apis/communityAPI'
import axios from 'axios'
export const store = new Vuex.Store({
state: {
path: 'http://192.168.0.89/account/',
is_auth: false,
is_admin: false,
active: false,
modals: false,
session_id: null,
email: null,
user : {
name:"",
email:""
balance: 0,
balance_gdt: 0
},
dataLogout: {"session_id": -127182}
ajaxCreateData: {
session_id : '',
email: "",
amount: 0,
target_date:"2021-02-19T13:25:36+00:00",
memo:"",
auto_sign: true
},
transactions: [],
modals: false
},
mutations: {
isActive(state) {
//("Im Store PRÜFEN PRÜFEN" )
return true
// Retrieve a state variable
getters: {
//isLoggedIn: (state /*, getters */) => {
// return state.session_id !== null;
//}
},
// Syncronous mutation of the state
mutations: {
email: (state, email) => {
//console.log('mutation: email')
state.email = email
},
login (state, logindata) {
//console.log("Im Store LOGIN() start " )
//console.log("logon state =>", state )
//console.log("logon TEST =>", logindata )
axios.post("http://localhost/login_api/unsecureLogin", logindata).then((ldata) => {
//console.log("Im Store LOGIN() axios then.statusText ", ldata.statusText);
if (ldata.statusText === "OK") {
console.log("STORE login() ldatasession_id", ldata.data.session_id)
state.is_auth = true
state.active = true
$cookies.set('gdd_is_auth','true');
$cookies.set('gdd_session_id', ldata.data.session_id);
$cookies.set('gdd_email',logindata.email);
state.user.email = logindata.email
//console.log("STORE login() to " + state.is_auth)
router.push('/KontoOverview')
}
return true
}, (error) => {
console.log(error);
});
//console.log("STORE login() from" + state.is_auth)
//if (state.is_auth) {
// state.is_auth = false
// state.active = false
//} else {
// state.is_auth = true
// state.active = true
//}
// console.log("STORE login() to " + state.is_auth)
session_id: (state,session_id) => {
//console.log('mutation: session_id')
state.session_id = session_id
},
creatUser( state, formdata) {
//console.log("Im Store creatUser() start " )
axios.post("http://localhost/login_api/createUser", formdata).then((ldata) => {
console.log("Im Store creatUser() axios then ", ldata);
// this.ldata = ldata.data;
return true
}, (error) => {
console.log(error);
});
},
logout(state){
axios.post("http://localhost/login_api/logout", this.dataLogout).then((ldata) => {
//console.log("Im Store logout() axios then ", ldata);
// this.ldata = ldata.data;
//return true
state.is_auth = false
state.is_admin = false
state.active = false
$cookies.set('gdd_is_auth','false');
$cookies.remove('gdd_email');
$cookies.remove('gdd_session_id');
router.push('/Landing')
}, (error) => {
console.log(error);
});
user_balance: (state,balance) => {
//console.log('mutation: user_balance')
state.user.balance = (balance)/10000
},
user_balance_gdt: (state,balance) => {
//console.log('mutation: user_balance_gdt')
state.user.balance_gdt = (balance)/10000
},
transactions: (state,transactions) => {
//console.log('mutation: transactions')
state.transactions = transactions
}
}
},
// Asyncronous actions - used for api calls
actions: {
login: async ({ dispatch, commit }, data) => {
//console.log('action: login')
const result = await loginAPI.login(data.email,data.password)
if( result.success ){
commit('session_id', result.result.data.session_id)
commit('email', data.email)
$cookies.set('gdd_session_id', result.result.data.session_id);
$cookies.set('gdd_u', data.email);
router.push('/KontoOverview')
} else {
// Register failed, we perform a logout
dispatch('logout')
}
},
createUser: async ({ commit, dispatch }, data) => {
console.log('action: createUser')
const result = await loginAPI.create(data.email,data.first_name,data.last_name,data.password)
if( result.success ){
commit('session_id', result.result.data.session_id)
commit('email', data.email)
$cookies.set('gdd_session_id', result.result.data.session_id);
$cookies.set('gdd_u', data.email);
router.push('/KontoOverview')
} else {
// Register failed, we perform a logout
dispatch('logout')
}
},
logout: async ({ commit , state }) => {
console.log('action: logout')
// Are we actually logged in?
if(state.session_id){
const result = await loginAPI.logout(state.session_id)
// The result can be error, but thats ok with us
}
commit('session_id', null)
commit('email', null)
$cookies.remove('gdd_session_id');
$cookies.remove('gdd_u');
router.push('/Login')
},
ajaxCreate: async ({ dispatch, state }) => {
//console.log('action: ajaxCreate')
axios.post("http://localhost/transaction-creations/ajaxCreate", state.ajaxCreateData).then((result) => {
console.log("store ajaxCreate result", result)
if( result.success ){
// TODO
} else {
//dispatch('logout')
}
}, (error) => {
console.log(error);
});
},
ajaxListTransactions: async ({commit, dispatch, state}) => {
// console.log('action: ajaxListTransactions', state.session_id)
// const result = await communityAPI.transactions(state.session_id)
},
accountBalance: async ({ commit, dispatch, state }) => {
//console.log('action: accountBalance')
const result = await communityAPI.balance(state.session_id)
//console.log(result)
if(result.success) {
commit('user_balance', result.result.data.balance)
} else {
dispatch('logout')
}
}
}
})

View File

@ -232,12 +232,12 @@
components: {
LineChart,
BarChart,
BaseProgress,
//BaseProgress,
StatsCard,
PageVisitsTable,
//PageVisitsTable,
AdminUserSearch,
AdminUserCreation,
SearchUser
//SearchUser
},
data() {
return {

View File

@ -153,7 +153,7 @@
components: {
LineChart,
BarChart,
BaseProgress,
//BaseProgress,
StatsCard,
PageVisitsTable,
SocialTrafficTable

View File

@ -8,52 +8,31 @@
<!-- Card sent GDD-->
<gdd-sent />
<br>
<br>
<hr>
<!-- Card table -->
<div>
<gdd-table />
</div>
<br>
<br>
<!-- Card table -->
<!-- Card table
<hr>
<div>
<gdd-add-work />
</div>
<br>
<br>
<!-- Card table -->
-->
<!-- Card table
<div>
<gdd-work-table />
</div>
-->
</base-header>
<hr>
<h3>User Data</h3>
<small>/public/json-example/userdata.json</small>
<p>
{{userdata}}
</p>
<hr>
<h3>User Transactions List</h3>
<small>/public/json-example/usertransactions.json</small>
<p>
{{usertransactions}}
</p>
<hr>
<h3>User Participation List</h3>
<small>/public/json-example/userparticipation.json</small>
<p>
{{userparticipation}}
</p>
</div>
</div>
</template>
<script>
@ -61,71 +40,20 @@
import GddStatus from './KontoOverview/GddStatus.vue';
import GddSent from './KontoOverview/GddSent.vue';
import GddTable from './KontoOverview/GddTable.vue';
import GddAddWork from './KontoOverview/GddAddWork.vue';
import GddWorkTable from './KontoOverview/GddWorkTable.vue';
import axios from 'axios';
//import GddAddWork from './KontoOverview/GddAddWork.vue';
// import GddWorkTable from './KontoOverview/GddWorkTable.vue';
export default {
data(){
return {
usertransactions: {},
userdata: {},
userparticipation: {}
}
},
export default {
components: {
GddStatus,
GddSent,
GddTable,
GddAddWork,
GddWorkTable,
axios
GddTable
//GddAddWork
//GddWorkTable
},
methods: {
UserData() {
axios.get("/json-example/userdata.json").then((d) => {
console.log(d);
this.userdata = d.data;
}, (error) => {
console.log(error);
});
},
UserTransactions() {
axios.get("/json-example/usertransactions.json").then((transactions) => {
console.log(transactions);
this.usertransactions = transactions.data;
}, (error) => {
console.log(error);
});
},
UserParticitions() {
axios.get("/json-example/userparticipation.json").then((participation) => {
console.log(participation);
this.userparticipation = participation.data;
}, (error) => {
console.log(error);
});
}
created() {
this.$store.dispatch('accountBalance')
},
created() {
// Simple GET request using axios
// axios.get("https://api.npms.io/v2/search?q=vue").then((response) => {
// console.log(response);
// this.totalVuePackages = response.data.total;
// this.dataVuePackages = response.data;
// }, (error) => {
// console.log(error);
// });
/////////////////////////
},
mounted() {
this.UserData();
this.UserTransactions();
this.UserParticitions();
},
};
</script>

View File

@ -19,9 +19,7 @@
</b-col>
</b-row>
<b-form @submit="onSubmit" @reset="onReset" v-if="show">
<br>
<qrcode-drop-zone id="input-0" v-model="form.img" ></qrcode-drop-zone>
<br>
<div>
<b-row class="form-group">
@ -58,10 +56,7 @@ export default {
return {
show: true,
form: {
img: '',
email: '',
amount1: '',
amount2: ''
}
};
},
@ -69,28 +64,18 @@ export default {
onSubmit(event) {
event.preventDefault()
alert(JSON.stringify(this.form))
this.modal = true
this.modal.h4 = 'TODO 1'
},
onReset(event) {
event.preventDefault()
// Reset our form values
this.form.email = ''
this.form.amount1 = ''
this.form.amount2 = ''
// Trick to reset/clear native browser form validation state
this.show = false
this.$nextTick(() => {
this.show = true
})
},
adressbook() {
this.modal = true
this.modaldata.h4 = 'Adressbuch'
this.modaldata.p = 'TODO ADRESSBUCH LISTE'
}
},
watch: {
}
};
</script>

View File

@ -1,83 +1,107 @@
<template>
<div>
<b-row>
<b-col xl="12" md="12">
<base-button icon type="primary" size="lg" v-b-toggle.collapse-1>
<b-row>
<b-col xl="12" md="12">
<base-button icon type="primary" size="lg" v-b-toggle.collapse-1>
<span class="btn-inner--icon"><i class="ni ni-curved-next"></i></span>
<span class="btn-inner--text">{{ $t('site.overview.send_gradido') }} </span>
</base-button>
<b-collapse id="collapse-1" class="mt-2">
<b-card>
<p class="card-text">
<b-row>
<b-col>
<qrcode-capture @detect="onDetect" capture="user" ></qrcode-capture>
</b-col>
<b-col>
<span v-if="scan">
<qrcode-stream @decode="onDecode" @detect="onDetect" ></qrcode-stream>
<b-iconstack font-scale="5" @click="scan=false">
<b-icon stacked icon="upc-scan" variant="info" scale="0.75"></b-icon>
<b-icon stacked icon="slash-circle" variant="danger"></b-icon>
</b-iconstack>
</span>
<span v-else >
<img src="img/icons/gradido/qr-scan-pure.png" width="90" @click="scan=true"/>
scan jetzt
</span>
</b-col>
</b-row>
<b-form @submit="onSubmit" @reset="onReset" v-if="show">
<br>
<qrcode-drop-zone id="input-0" v-model="form.img" ></qrcode-drop-zone>
<br>
<div>
<b-input-group
id="input-group-1"
label="Empfänger:"
label-for="input-1"
description="We'll never share your email with anyone else.">
<b-form-input
id="input-1"
v-model="form.email"
type="email"
placeholder="E-Mail"
required></b-form-input>
<b-input-group-append>
<b-button variant="outline-primary" @click="adressbook">Adressbuch</b-button>
</b-input-group-append>
</b-input-group>
</div>
<br>
<div>
<b-input-group id="input-group-2" label="Betrag:" label-for="input-2">
<b-form-input id="input-2"
v-model="form.amount1"
type="number"
required
min="0" placeholder="0">
</b-form-input>.<h1>GDD.</h1>
<b-form-input id="input-3"
v-model="form.amount2"
type="number"
min="00" placeholder="00">
<b-collapse id="collapse-1" class="mt-2">
<b-card >
<div v-if="scan">
<b-row>
<qrcode-capture @detect="onDetect" capture="user" ></qrcode-capture>
</b-row>
<b-row>
<qrcode-stream @decode="onDecode" @detect="onDetect" ></qrcode-stream>
<b-alert show variant="secondary">
<span class="alert-text"><strong>QR Code Scanner</strong> - Scanne den QR Code deines Partners</span>
</b-alert>
<b-alert show variant="warning" >
<span class="alert-text" @click="scan=false"><strong>abrechen!</strong></span>
</b-alert>
</b-row>
</div>
<validation-observer v-slot="{handleSubmit}" ref="formValidator">
<b-form role="form" @submit.prevent="handleSubmit(onSubmit)" @reset="onReset" v-if="show">
<br>
<qrcode-drop-zone id="input-0" v-model="form.img"></qrcode-drop-zone>
<br>
<div>
<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>
<b-button variant="outline-primary">
<img src="img/icons/gradido/qr-scan-pure.png" width="50" @click="scan=true"/></b-button>
</b-input-group-prepend>
<b-form-input
id="input-1"
v-model="form.email"
type="email"
placeholder="E-Mail"
:rules="{required: true, email: true}"
required
style="font-size: xx-large; padding-left:20px"></b-form-input>
</b-input-group>
</div>
<br>
<div>
<b-input-group id="input-group-2" label="Betrag:" label-for="input-2"
size="lg"
class="mb-3">
<b-input-group-prepend>
<b-button variant="outline-primary">
<img src="img/icons/gradido/plus.png" width="50">
</b-button>
</b-input-group-prepend>
<b-form-input
id="input-2"
v-model="form.amount"
type="number"
placeholder="0.01"
step="0.01"
min="0.01"
max="1000"
style="font-size: xx-large; padding-left:20px">
</b-form-input>
</b-input-group>
</div>
<br>
<b-button type="submit" variant="primary">jetzt versenden</b-button>
<b-button type="reset" variant="danger">Cancel</b-button>
<br>
</b-form>
</p>
</b-card>
</b-collapse>
<b-input-group-prepend>
<b-button >
<div class="h1">GDD</div>
</b-button>
</b-input-group-prepend>
</b-input-group>
<b-input-group>
<b-input-group-prepend>
<b-button >
<h1><b-icon icon="chat-right-text"></b-icon></h1>
</b-button>
</b-input-group-prepend>
<b-form-textarea v-model="form.memo"></b-form-textarea>
</b-input-group>
</div>
<br>
<b-button type="submit" variant="primary">jetzt versenden</b-button>
<b-button type="reset" variant="danger">Cancel</b-button>
<br>
</b-form>
</validation-observer>
</b-card>
</b-collapse>
</b-col>
</b-row>
</b-row>
</div>
</template>
@ -100,8 +124,8 @@ export default {
form: {
img: '',
email: '',
amount1: '',
amount2: ''
amount: '',
memo:''
}
}
},
@ -135,28 +159,32 @@ export default {
// ...
}
},
onSubmit(event) {
event.preventDefault()
alert(JSON.stringify(this.form))
this.modal = true
this.modal.h4 = 'TODO 1'
async onSubmit() {
//event.preventDefault()
console.log("onSubmit", this.form)
//console.log("this.form.img", this.form.img)
//console.log("this.form.email", this.form.email)
//console.log("this.form.amount", this.form.amount)
//console.log("this.form.memo", this.form.memo)
this.$store.state.ajaxCreateData.session_id = this.$cookies.get('gdd_session_id')
this.$store.state.ajaxCreateData.email = this.form.email
this.$store.state.ajaxCreateData.amount = this.form.amount
this.$store.state.ajaxCreateData.memo = this.form.memo
this.$store.state.ajaxCreateData.target_date = Date.now()
this.$store.dispatch('ajaxCreate')
},
onReset(event) {
event.preventDefault()
// Reset our form values
this.form.email = ''
this.form.amount1 = ''
this.form.amount2 = ''
this.form.amount = ''
// Trick to reset/clear native browser form validation state
this.show = false
this.$nextTick(() => {
this.show = true
})
},
adressbook() {
this.modal = true
this.modaldata.h4 = 'Adressbuch'
this.modaldata.p = 'TODO ADRESSBUCH LISTE'
}
},
computed: {

View File

@ -4,35 +4,38 @@
<b-col xl="6" md="6">
<stats-card :title="$t('site.overview.current_balance')"
type="gradient-red"
sub-title="3500,897 GDD"
img="img/icons/gradido/my_gradido.png"
sub-title="balance_gdd"
class="mb-4">
{{ $n($store.state.user.balance) }} GDD
<template slot="footer">
<span class="text-success mr-2">+ 3.48%</span>
<span class="text-nowrap">{{ $t('site.overview.since_last_month') }}</span>
<span class="text-success mr-2">Wird immer angezeigt</span>
</template>
</stats-card>
</b-col>
<b-col xl="6" md="6">
<stats-card :title="$t('site.overview.gradido_received')"
type="gradient-orange"
sub-title="2,356 GDD"
img="img/icons/gradido/plus.png"
sub-title="balance_gdt"
class="mb-4">
<template slot="footer">
<span class="text-success mr-2">+ 12.18%</span>
<span class="text-nowrap">{{ $t('site.overview.since_last_month') }}</span>
{{ $n($store.state.user.balance_gdt) }} GDT
<template slot="footer">
<span class="text-nowrap">Wird nur angezeigt wenn user GDT besitzt.</span>
</template>
</stats-card>
</b-col>
</b-row>
</div>
</template>
<script>
export default {
name: 'GddStatus',
data(){
return {
balance_gdd: this.$store.state.user.balance,
balance_gdt: this.$store.state.user.balance_gdt,
}
}
};
</script>

View File

@ -1,86 +1,87 @@
<template>
<div>
<!--
<b-table striped hover :items="items" :fields="fields" :tbody-tr-class="rowClass" responsive="true" >
<template #cell(status)="row">
<img v-if="row.item.status === 'sent' " src="img/icons/gradido/minus.png" width="50" />
<img v-else src="img/icons/gradido/plus-low.png" width="50" />
</template>
<template #cell(details)="row">
<b-button size="md" @click="row.toggleDetails" class="mr-2">
{{ row.detailsShowing ? $t('site.overview.table.hide') : $t('site.overview.table.view') }}
</b-button>
</template>
<-- Table details -- >
<template #row-details="row">
<b-card>
<b-row class="mb-2">
<b-col sm="3" class="text-sm-right"><b>{{ $t('site.overview.table.amount') }}:</b></b-col>
<b-col>{{ row.item.amount }} GDD</b-col>
</b-row>
<b-row class="mb-2">
<b-col sm="3" class="text-sm-right"><b>{{ $t('site.overview.table.decay') }}: </b></b-col>
<b-col>{{ row.item.isActive }}0.0032 GDD</b-col>
</b-row>
<b-row class="mb-2">
<b-col sm="3" class="text-sm-right"><b>{{ $t('site.overview.table.sender') }}: </b></b-col>
<b-col>{{ row.item.name }}</b-col>
<b-col>{{ row.item.date }}</b-col>
</b-row>
<b-button size="sm" @click="row.toggleDetails">{{ $t('site.overview.table.hide_details') }}</b-button>
</b-card>
</template>
</b-table>
-->
<hr>
<b-list-group >
<b-list-group-item v-for="item in items" :key="item.id">
<div class="d-flex w-100 justify-content-between" @click="toogle(item)" >
<b-icon v-if="item.status === 'sent'" icon="box-arrow-left" class="m-1" font-scale="2" style="color:red"></b-icon>
<b-icon v-if="item.type === 'send'" icon="box-arrow-left" class="m-1" font-scale="2" style="color:red"></b-icon>
<b-icon v-else icon="box-arrow-right" class="m-1" font-scale="2" style="color:green" ></b-icon>
<h1 class="mb-1">{{item.betrag}} <small>GDD</small></h1>
<h2 class="text-muted"><small>{{item.datum}}</small> - {{item.name}}</h2>
<h1 class="mb-1">{{ $n((item.balance)/10000) }} <small>GDD</small></h1>
<h2 class="text-muted">{{item.name}}</h2>
<b-button v-b-toggle="'a'+item.transaction_id" variant="primary"><b>i</b></b-button>
</div>
<b-collapse :id="'a'+item.transaction_id" class="mt-2">
<b-card>
<p class="card-text">{{item}}</p>
<b-button v-b-toggle="'collapse-1-inner'+ item.transaction_id" size="sm">\i/ more</b-button>
<b-collapse :id="'collapse-1-inner'+ item.transaction_id" class="mt-2">
<b-card>{{item}}</b-card>
</b-collapse>
</b-card>
</b-collapse>
</b-list-group-item>
<b-list-group-item>
<b-alert v-if="count < 5" show variant="secondary">
Die letzten <strong>{{count}}</strong> Transaktionen
</b-alert>
<router-link to="/activity" > mehr (+ {{count}})</router-link>
</b-list-group-item>
</b-list-group>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'GddTable',
data(){
return {
form: [],
fields: [ 'status', 'betrag', 'name', 'datum', 'details'],
items: [
{ id: 1, betrag: 1000, name: 'Dickerson', datum: '12.12.20', datel: '12.12.2020 14:04', status: 'received' },
{ id: 2, betrag: 302, name: 'Larsen', datum: '22.06.20', datel: '22.06.2020 22:23', status: 'sent' },
{ id: 3, betrag: 89, name: 'Geneva', datum: '15.04.20', datel: '15.04.2020 12:55', status: 'sent' },
{ id: 4, betrag: 1000, name: 'Community', datum: '10.03.20', datel: '10.03.2020 18:20', status: 'received'}
]
fields: [ 'balance', 'date', 'memo', 'name', 'transaction_id', 'type','details'],
items: [],
count: 0
};
},
created() {
axios.get("http://localhost/state-balances/ajaxListTransactions/"+ this.$store.state.session_id).then((result) => {
//console.log("result",result)
//console.log("result.state",result.data.state)
//
//console.log("result.data.state == 'success'",result.data.state == "success")
//console.log("result.count",result.data.count)
// console.log("result.gdtSum",result.data.gdtSum)
console.log("result.transactions",result.data.transactions)
//commit('transactions', result.data.transactions)
this.$store.state.user.balance_gdt = result.data.gdtSum
this.items = result.data.transactions
this.count = result.data.count
}, (error) => {
console.log(error);
});
},
methods: {
rowClass(item, type) {
if (!item || type !== 'row') return
if (item.status === 'received') return 'table-success'
if (item.status === 'sent') return 'table-warning'
if (item.status === 'earned') return 'table-primary'
if (item.type === 'receive') return 'table-success'
if (item.type === 'send') return 'table-warning'
if (item.type === 'creation') return 'table-primary'
},
toogle(item) {
const temp = '<b-collapse visible v-bind:id="item.id">xxx <small class="text-muted">porta</small></b-collapse>'
}
},
watch: {
}
}
};
</script>
<style>

View File

@ -81,7 +81,7 @@
</b-col>
</b-row>
</form>
<b-button block type="submit" @click="creatUser()">Anmelden</b-button>
<b-button block type="submit" @click="createUser()">Anmelden</b-button>
</b-col>
</b-row>
@ -114,25 +114,12 @@ export default {
},
methods: {
login() {
if (this.lemail != '' || this.lpwd != '') {
//console.log("landingpage login() ")
//console.log("landingpage login() lemail ", this.lemail)
//console.log("landingpage login() lpwd ", this.lpwd)
this.$store.commit('login', {"email": this.lemail, "password": this.lpwd})
}
//this.$router.push('/KontoOverview')
//if (this.lemail !== '' || this.lpwd !== '') { // TODO this should be done via form validation
this.$store.dispatch('login', {email: this.lemail, password: this.lpwd})
//}
},
creatUser() {
console.log("landingpage creatUser() ")
console.log("landingpage login() remail ", this.remail)
console.log("landingpage login() rfname ", this.rfname)
console.log("landingpage login() rlname ", this.rlname)
console.log("landingpage login() rpwd ", this.rpwd)
this.$store.commit('creatUser', {"email":this.remail, "first_name":this.rfname, "last_name":this.rlname , "emailType": 2, "password":this.rpwd})
//this.$router.push('/KontoOverview')
createUser() {
this.$store.dispatch('createUser', {email:this.remail, first_name:this.rfname, last_name:this.rlname, password:this.rpwd})
},
loginAsAdmin () {
console.log("app.vue admin login(): " + this.$store.state.is_admin)

View File

@ -98,7 +98,7 @@
components: {
DashboardNavbar,
ContentFooter,
DashboardContent,
//DashboardContent,
FadeTransition
},
methods: {

View File

@ -45,8 +45,8 @@
export default {
components: {
BaseNav,
ZoomCenterTransition
//BaseNav,
//ZoomCenterTransition
},
props: {
backgroundColor: {

View File

@ -8,16 +8,16 @@
</b-col>
<b-col lg="6">
<b-nav class="nav-footer justify-content-center justify-content-lg-end">
<b-nav-item ref="https://www.creative-tim.com" target="_blank">
<b-nav-item ref="https://gradido.net/" target="_blank">
Gradido
</b-nav-item>
<b-nav-item href="https://www.creative-tim.com/presentation" target="_blank">
<b-nav-item href="https://gradido.net/" target="_blank">
Impressum
</b-nav-item>
<b-nav-item href="http://blog.creative-tim.com" target="_blank">
<b-nav-item href="https://gradido.net/" target="_blank">
Datenschutzerklärung
</b-nav-item>
<b-nav-item href="https://www.creative-tim.com/license" target="_blank">
<b-nav-item href="https://gradido.net/" target="_blank">
License
</b-nav-item>
</b-nav>

View File

@ -17,6 +17,20 @@
path: '/profile',
icon: 'ni ni-single-02 text-yellow'
}">
</sidebar-item>
<sidebar-item
:link="{
name: 'Settings',
path: '/profileedit',
icon: 'ni ni-single-02 text-yellow'
}">
</sidebar-item>
<sidebar-item
:link="{
name: 'Activity',
path: '/activity',
icon: 'ni ni-single-02 text-yellow'
}">
</sidebar-item>
<b-nav-item href="#!" @click="logout">
<i class="ni ni-palette"></i>
@ -88,7 +102,7 @@
components: {
DashboardNavbar,
ContentFooter,
DashboardContent,
// DashboardContent,
FadeTransition
},
methods: {
@ -100,7 +114,7 @@
},
logout(){
//console.log("DashboardLayout.vue user logout() : ")
this.$store.commit('logout')
this.$store.dispatch('logout')
}
},
mounted() {

View File

@ -38,10 +38,10 @@
<b-media no-body class="align-items-center">
<span class="avatar avatar-sm rounded-circle">
<img alt="Image placeholder" src="img/theme/team-4.jpg">
<vue-qrcode :value="$store.state.email" />
</span>
<b-media-body class="ml-2 d-none d-lg-block">
<span class="mb-0 text-sm font-weight-bold">{{this.$store.state.user.email}}</span>
<span class="mb-0 text-sm font-weight-bold">{{this.$store.state.email}}</span>
</b-media-body>
</b-media>
</a>
@ -51,11 +51,15 @@
<b-dropdown-header class="noti-title">
<h6 class="text-overflow m-0"> {{ $t('site.welcome') }}</h6>
</b-dropdown-header>
<b-dropdown-item href="#!">
<b-dropdown-item href="#!" to="/KontoOverview">
<i class="ni ni-single-02"></i>
<span>{{ $t('site.overview.account_overview')}}</span>
</b-dropdown-item>
<b-dropdown-item href="#!" to="/profile">
<i class="ni ni-single-02"></i>
<span>{{ $t('site.navbar.my-profil')}}</span>
</b-dropdown-item>
<b-dropdown-item href="#!">
<b-dropdown-item href="#!" to="/profileedit">
<i class="ni ni-settings-gear-65"></i>
<span>{{ $t('site.navbar.settings') }}</span>
</b-dropdown-item>
@ -80,13 +84,14 @@
</template>
<script>
import { CollapseTransition } from 'vue2-transitions';
import { BaseNav, Modal } from '@/components';
import { BaseNav } from '@/components';
import VueQrcode from 'vue-qrcode'
export default {
components: {
CollapseTransition,
CollapseTransition,
BaseNav,
Modal
VueQrcode
},
props: {
type: {
@ -121,7 +126,7 @@ export default {
},
logout(){
//console.log("DashboardNavbar.vue user logout() : ")
this.$store.commit('logout')
this.$store.dispatch('logout')
}
}
};

View File

@ -1,13 +1,23 @@
<template>
<div>
<!-- Header -->
<div class="header bg-gradient-success py-7 py-lg-8 pt-lg-9">
<div class="header bg-gradient-success py-7 py-lg-5 pt-lg-1">
<b-container class="container">
<div class="header-body text-center mb-7">
<b-row class="justify-content-center">
<b-col xl="5" lg="6" md="8" class="px-5">
<h1 class="text-white">Gradido Wallet</h1>
<p class="text-lead text-white">Du bist die Community</p>
</b-col>
</b-row>
</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 -->
@ -15,21 +25,12 @@
<b-row class="justify-content-center">
<b-col lg="5" md="7">
<b-card no-body class="bg-secondary border-0 mb-0">
<b-card-header class="pb-1" >
<video width="450" height="300" autoplay loop>
<source src="/img/brand/cube.webm" type="video/webm">
Your browser does not support the video tag.
</video>
</b-card-header>
<b-card-body class="px-lg-5 py-lg-5">
<div class="text-center text-muted mb-4">
<h2>Login Gradido Wallet</h2>
<div class="text-center text-muted mb-4">
<small>login</small>
</div>
<div class="text-center text-muted mb-4">
<h4>Login Server 1</h4>
</div>
<!--<validation-observer v-slot="{handleSubmit}" ref="formValidator">
<validation-observer v-slot="{handleSubmit}" ref="formValidator">
<b-form role="form" @submit.prevent="handleSubmit(onSubmit)">
<base-input alternative
class="mb-3"
@ -55,7 +56,7 @@
<base-button type="primary" native-type="submit" class="my-4">Sign in</base-button>
</div>
</b-form>
</validation-observer> -->
</validation-observer>
</b-card-body>
</b-card>
<b-row class="mt-3">
@ -73,6 +74,7 @@
</template>
<script>
export default {
name: "login",
data() {
return {
model: {
@ -82,10 +84,10 @@
}
};
},
methods: {
methods: {
onSubmit() {
// this will be called only after form is valid. You can do api call here to login
this.$store.dispatch('login', {"email": this.model.email, "password": this.model.password})
}
}
};
}
</script>

View File

@ -1,12 +1,12 @@
<template>
<div>
<!-- Header -->
<div class="header bg-gradient-success py-7 py-lg-8 pt-lg-9">
<div class="header bg-gradient-success py-7 py-lg-5 pt-lg-1">
<b-container class="container">
<div class="header-body text-center mb-7">
<b-row class="justify-content-center">
<b-col xl="5" lg="6" md="8" class="px-5">
<h1 class="text-white">Erstelle eine Gradido Wallet</h1>
<h1 class="text-white">Erstelle deine Gradido Wallet</h1>
<p class="text-lead text-white">Werde teil der Community</p>
</b-col>
</b-row>
@ -25,23 +25,28 @@
<b-row class="justify-content-center">
<b-col lg="6" md="8" >
<b-card no-body class="bg-secondary border-0">
<b-card-header class="bg-transparent pb-5">
<div class="text-muted text-center mt-2 mb-4"><small>Sign up with</small></div>
</b-card-header>
<b-card-body class="px-lg-5 py-lg-5">
<div class="text-center text-muted mb-4">
<small>Or sign up with credentials</small>
<small>sign up </small>
</div>
<validation-observer v-slot="{handleSubmit}" ref="formValidator">
<b-form role="form" @submit.prevent="handleSubmit(onSubmit)">
<base-input alternative
class="mb-3"
prepend-icon="ni ni-hat-3"
placeholder="Name"
name="Name"
placeholder="Vorname"
name="Vorname"
:rules="{required: true}"
v-model="model.name">
v-model="model.firstname">
</base-input>
<base-input alternative
class="mb-3"
prepend-icon="ni ni-hat-3"
placeholder="Nachname"
name="Nachname"
:rules="{required: true}"
v-model="model.lastname">
</base-input>
<base-input alternative
@ -82,6 +87,14 @@
</b-card>
</b-col>
</b-row>
<div class="text-center py-lg-5" >
<b-button type="button" variant="success" class="mt-4" to="/Login">zurück</b-button>
</div>
<div>
</div>
</b-container>
</div>
</template>
@ -92,19 +105,26 @@
data() {
return {
model: {
name: '',
firstname: '',
lastname: '',
email: '',
password: '',
agree: false
agree: false
}
}
},
methods: {
onSubmit() {
// this will be called only after form is valid. You can do an api call here to register users
}
// console.log("this.modals =>", this.modals)
this.$store.dispatch('createUser', {"email":this.model.email, "first_name":this.model.firstname, "last_name":this.model.lastname , "emailType": 2, "password":this.model.password})
this.model.email = ""
this.model.firstname = ""
this.model.lastname = ""
this.model.password = ""
this.$router.push('/thx')
}
}
};
</script>
<style></style>

View File

@ -9,7 +9,7 @@
<b-container fluid class="d-flex align-items-center">
<b-row >
<b-col lg="7" md="10">
<h1 class="display-2 text-white">Hello {{this.$store.state.user.email}}</h1>
<h1 class="display-2 text-white">Hello {{this.$store.state.email}}</h1>
<p class="text-white mt-0 mb-5">This is your profile page. You can see the progress you've made with your
work and manage your projects or assigned tasks</p>
<a href="#!" class="btn btn-info">Edit profile</a>

View File

@ -0,0 +1,71 @@
<template>
<div>
<!-- slot for parent component to activate the file changer -->
<div @click="launchFilePicker()">
<slot name="activator"></slot>
</div>
<!-- image input: style is set to hidden and assigned a ref so that it can be triggered -->
<input type="file"
ref="file"
:name="uploadFieldName"
@change="onFileChange(
$event.target.name, $event.target.files)"
style="display:none">
<!-- error dialog displays any potential errors -->
<v-dialog v-model="errorDialog" max-width="300">
<v-card>
<v-card-text class="subheading">{{errorText}}</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn @click="errorDialog = false" flat>Got it!</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
export default {
name: 'avatar-uploader',
data: ()=> ({
errorDialog: null,
errorText: '',
uploadFieldName: 'file',
maxSize: 1024
}),
props: {
// Use "value" here to enable compatibility with v-model
value: Object,
},
methods: {
launchFilePicker(){
this.$refs.file.click();
},
onFileChange(fieldName, file) {
const { maxSize } = this
let imageFile = file[0]
//check if user actually selected a file
if (file.length>0) {
let size = imageFile.size / maxSize / maxSize
if (!imageFile.type.match('image.*')) {
// check whether the upload is an image
this.errorDialog = true
this.errorText = 'Please choose an image file'
} else if (size>1) {
// check whether the size is greater than the size limit
this.errorDialog = true
this.errorText = 'Your file is too big! Please select an image under 1MB'
} else {
// Append file into FormData & turn file into image URL
let formData = new FormData()
let imageURL = URL.createObjectURL(imageFile)
formData.append(fieldName, imageFile)
// Emit FormData & image URL to the parent component
this.$emit('input', { formData, imageURL })
}
}
}
}
}
</script>
<style></style>

View File

@ -4,7 +4,7 @@
<b-col lg="3" class="order-lg-2">
<div class="card-profile-image">
<a href="#">
<b-img src="img/theme/team-4.jpg" rounded="circle" />
<vue-qrcode :value="$store.state.email" />
</a>
</div>
</b-col>
@ -12,8 +12,7 @@
<b-card-header class="text-center border-0 pt-8 pt-md-4 pb-0 pb-md-4">
<div class="d-flex justify-content-between">
<a href="#" class="btn btn-sm btn-info mr-4">Connect</a>
<a href="#" class="btn btn-sm btn-default float-right">Message</a>
<br>
</div>
</b-card-header>
@ -23,22 +22,22 @@
<div class="card-profile-stats d-flex justify-content-center mt-md-5">
<div>
<span class="heading">22</span>
<span class="description">Friends</span>
<span class="description">Transactions</span>
</div>
<div>
<span class="heading">10</span>
<span class="description">Photos</span>
<span class="description">Community</span>
</div>
<div>
<span class="heading">89</span>
<span class="description">Comments</span>
<span class="heading"> {{ $n(this.$store.state.user.balance) }} </span>
<span class="description">GDD</span>
</div>
</div>
</b-col>
</b-row>
<div class="text-center">
<h5 class="h3">
{{this.$store.state.user.email}}<span class="font-weight-light"></span>
{{this.$store.state.email}}<span class="font-weight-light"></span>
</h5>
<div class="h5 font-weight-300">
<i class="ni location_pin mr-2"></i>Bucharest, Romania
@ -58,6 +57,13 @@
</b-card>
</template>
<script>
export default {};
import VueQrcode from 'vue-qrcode'
export default {
name: "profilecard",
components: {
VueQrcode,
}
};
</script>
<style></style>

View File

@ -0,0 +1,47 @@
<template>
<div>
<div class="header pb-8 pt-5 pt-lg-8 d-flex align-items-center profile-header" style="max-height:200px">
<b-container fluid>
<!-- Mask -->
<span class="mask bg-gradient-success opacity-8"></span>
<!-- Header container -->
<b-container fluid class="d-flex align-items-center">
<b-row >
<b-col lg="7" md="10">
<h1 class="display-2 text-white">{{this.$store.state.email}} </h1>
</b-col>
</b-row>
</b-container>
</b-container>
</div>
<b-container fluid class="mt--6">
<b-row>
<b-col xl="4" class="order-xl-2 mb-5">
community
<gdd-work-table></gdd-work-table>
</b-col>
<b-col xl="8" class="order-xl-1">
transactions
<gdd-table></gdd-table>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
import GddTable from '../../views/KontoOverview/GddTable.vue';
import GddWorkTable from '../../views/KontoOverview/GddWorkTable.vue';
export default {
components: {
GddTable,
GddWorkTable
}
};
</script>
<style>
</style>

View File

@ -0,0 +1,38 @@
<template>
<div>
<div class="header pb-8 pt-5 pt-lg-8 d-flex align-items-center profile-header">
<b-container fluid>
<!-- Mask -->
<span class="mask bg-gradient-success opacity-8"></span>
<!-- Header container -->
<b-container fluid class="d-flex align-items-center">
<b-row >
<base-button><router-link to="/profileedit" > Edit Profil</router-link> </base-button>
</b-row>
</b-container>
</b-container>
</div>
<b-container fluid class="mt--6">
<b-row>
<b-col xl="12" class="order-xl-2 mb-5">
<user-card></user-card>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
import BaseButton from '../../components/BaseButton.vue';
import UserCard from './UserProfile/UserCard.vue';
export default {
components: {
UserCard,
BaseButton
}
};
</script>
<style>
</style>

View File

@ -0,0 +1,44 @@
<template>
<div>
<div class="header pb-8 pt-5 pt-lg-8 d-flex align-items-center profile-header">
<b-container fluid>
<!-- Mask -->
<span class="mask bg-gradient-success opacity-8"></span>
<!-- Header container -->
<b-container fluid class="d-flex align-items-center">
<b-row >
<base-button><router-link to="/profile" > mein Profil</router-link> </base-button>
</b-row>
</b-container>
</b-container>
</div>
<b-container fluid class="mt--6">
<b-row>
<b-col xl="12" class="order-xl-1">
<edit-profile-form></edit-profile-form>
</b-col>
</b-row>
<b-row>
<b-col xl="12" class="order-xl-1">
<image-uploader-avatar> </image-uploader-avatar>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
import EditProfileForm from './UserProfile/EditProfileForm.vue';
import ImageUploaderAvatar from './UserProfile/ImageUploaderAvatar.vue';
export default {
components: {
EditProfileForm,
ImageUploaderAvatar
}
};
</script>
<style>
</style>

View File

@ -0,0 +1,23 @@
<template>
<div>
<!-- Header -->
<div class="header bg-gradient-info py-7 py-lg-8 pt-lg-9">
<b-container>
<div class="header-body text-center mb-7">
<p class="h1">Danke für die Anmeldung</p>
<p class="h4">Bitte prüfe deine Mail und bestäige diese Anmeldung letztmalig. Dann kannst du dich in deiner Gradido Wallet einloggen. </p>
<b-button to="/login"> zum 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>
</template>

View File

@ -2,7 +2,7 @@
<div class="wrapper">
<notifications></notifications>
<side-bar>
<template slot-scope="props" slot="links">
<template slot-scope="" slot="links">
<sidebar-item
:link="{
name: 'Dashboards',
@ -56,7 +56,7 @@ export default {
components: {
DashboardNavbar,
ContentFooter,
DashboardContent,
//DashboardContent,
FadeTransition,
},
methods: {

View File

@ -90,9 +90,9 @@
export default {
components: {
CollapseTransition,
//CollapseTransition,
BaseNav,
Modal
//Modal
},
computed: {
routeName() {

View File

@ -1600,7 +1600,7 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
esutils "^2.0.2"
js-tokens "^3.0.2"
babel-eslint@^10.0.1:
babel-eslint@^10.0.1, babel-eslint@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==
@ -1689,7 +1689,7 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
base64-js@^1.0.2:
base64-js@^1.0.2, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
@ -1950,12 +1950,30 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4
escalade "^3.1.1"
node-releases "^1.1.70"
buffer-alloc-unsafe@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
buffer-alloc@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
dependencies:
buffer-alloc-unsafe "^1.1.0"
buffer-fill "^1.0.0"
buffer-equal@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b"
integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=
buffer-from@^1.0.0:
buffer-fill@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
buffer-from@^1.0.0, buffer-from@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
@ -1979,6 +1997,14 @@ buffer@^4.3.0:
ieee754 "^1.1.4"
isarray "^1.0.0"
buffer@^5.4.3:
version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
dependencies:
base64-js "^1.3.1"
ieee754 "^1.1.13"
builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
@ -3407,6 +3433,11 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"
dijkstrajs@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.1.tgz#d3cd81221e3ea40742cfcde556d4e99e98ddc71b"
integrity sha1-082BIh4+pAdCz83lVtTpnpjdxxs=
dir-glob@^2.0.0, dir-glob@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4"
@ -5075,7 +5106,7 @@ icss-utils@^2.1.0:
dependencies:
postcss "^6.0.1"
ieee754@^1.1.4:
ieee754@^1.1.13, ieee754@^1.1.4:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
@ -7098,6 +7129,11 @@ pluralize@^7.0.0:
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==
pngjs@^3.3.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
popper.js@^1.16.1:
version "1.16.1"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
@ -7595,6 +7631,19 @@ q@^1.1.2:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
qrcode@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83"
integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==
dependencies:
buffer "^5.4.3"
buffer-alloc "^1.2.0"
buffer-from "^1.1.1"
dijkstrajs "^1.0.1"
isarray "^2.0.1"
pngjs "^3.3.0"
yargs "^13.2.4"
qs@6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
@ -9538,6 +9587,11 @@ vue-qrcode-reader@^2.3.16:
vue "^2.6.11"
webrtc-adapter "7.7.0"
vue-qrcode@^0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/vue-qrcode/-/vue-qrcode-0.3.5.tgz#d95bd81fea0c7f007f4e69244203d0eee2d573a5"
integrity sha512-AZJ+HzhOFokHuMVVwUIjG1FCWT1vJqn/Ro8XnQbyNlZTlQ8l4040JawVqUvTql3AdjJnI9bXaCTPplN502SnFw==
vue-router@^3.0.6:
version "3.5.1"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.1.tgz#edf3cf4907952d1e0583e079237220c5ff6eb6c9"
@ -9892,7 +9946,7 @@ yargs-parser@^20.2.2:
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.6.tgz#69f920addf61aafc0b8b89002f5d66e28f2d8b20"
integrity sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA==
yargs@^13.2.2, yargs@^13.3.2:
yargs@^13.2.2, yargs@^13.2.4, yargs@^13.3.2:
version "13.3.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==

@ -1 +1 @@
Subproject commit 2a033c34e4657e84a4387ecfda1cd6102032e95e
Subproject commit 9b9115290c8d2ead756d64b70ae63a6571aa4693

View File

@ -0,0 +1,75 @@
#!/bin/bash
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_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_PASSWD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo);
# create table
mysql <<EOFMYSQL
create database $LOGIN_DB_NAME
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
create database $COMMUNITY_DB_NAME
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
create database IF NOT EXISTS _skeema_tmp
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
CREATE USER '$LOGIN_DB_USER'@'localhost' IDENTIFIED BY '$LOGIN_DB_PASSWD';
GRANT ALL PRIVILEGES ON $LOGIN_DB_NAME.* TO '$LOGIN_DB_USER'@'localhost';
GRANT ALL PRIVILEGES ON _skeema_tmp.* TO '$LOGIN_DB_USER'@'localhost';
CREATE USER '$COMMUNITY_DB_USER'@'localhost' IDENTIFIED BY '$COMMUNITY_DB_PASSWD';
GRANT ALL PRIVILEGES ON $COMMUNITY_DB_NAME.* TO '$COMMUNITY_DB_USER'@'localhost';
GRANT ALL PRIVILEGES ON _skeema_tmp.* TO '$COMMUNITY_DB_USER'@'localhost';
FLUSH PRIVILEGES;
EOFMYSQL
# populate db of login-server
cd ../login_server/skeema
sudo cat << EOF > .skeema
[production]
flavor=mariadb:10.1.47
host=127.0.0.1
port=3306
user=$LOGIN_DB_USER
EOF
cd gradido_login
sudo cat << EOF > .skeema
default-character-set=utf8mb4
default-collation=utf8mb4_unicode_ci
schema=$LOGIN_DB_NAME
EOF
source $HOME/.gvm/scripts/gvm
gvm use go1.14.4
skeema push -p$LOGIN_DB_PASSWD
cd ../../..
# populate db of community-server
cd community_server/skeema
sudo cat << EOF > .skeema
[production]
flavor=mariadb:10.1.47
host=127.0.0.1
port=3306
user=$COMMUNITY_DB_USER
EOF
cd gradido_community
sudo cat << EOF > .skeema
default-character-set=utf8mb4
default-collation=utf8mb4_unicode_ci
schema=$COMMUNITY_DB_NAME
EOF
skeema push -p$COMMUNITY_DB_PASSWD
echo -e "${COLOR_YELLOW}Login-Server db password: $LOGIN_DB_PASSWD${COLOR_NONE}"
echo -e "${COLOR_YELLOW}Community-Server db password: $COMMUNITY_DB_PASSWD${COLOR_NONE}"