diff --git a/functions/scheduled/dailyMembership.f.js b/functions/scheduled/dailyMembership.f.js index bd9c1925..268680ba 100644 --- a/functions/scheduled/dailyMembership.f.js +++ b/functions/scheduled/dailyMembership.f.js @@ -39,10 +39,10 @@ exports=module.exports=functions.runWith(runtimeOpts).pubsub.schedule('every 24 }) const results=await Promise.all(verifyMessageBatch) results.forEach((result)=>{ - if (result.wallet.shareBalance>0)statistics.emailsContributorsAuth.push(result.emails.auth) - statistics.wallet.shareBalance=((statistics.wallet||{}).shareBalance||0)+result.wallet.shareBalance + if (result.wallet.balance>0)statistics.emailsContributorsAuth.push(result.emails.auth) + statistics.wallet.balance=((statistics.wallet||{}).balance||0)+result.wallet.balance statistics.interest.amount=((statistics.interest||{}).amount||0)+result.interest.amount - statistics.interest.rateDay=statistics.wallet.shareBalance*(Math.exp(result.interest.rateYear/365)-1) + statistics.interest.rateDay=statistics.wallet.balance*(Math.exp(result.interest.rateYear/365)-1) statistics.interest.amountCummulate=((statistics.interest||{}).amountCummulate||0)+result.interest.amountCummulate statistics.contract.amount=((statistics.contract||{}).amount||0)+result.contract.amount statistics.contract.amountCummulate=((statistics.contract||{}).amountCummulate||0)+result.contract.amountCummulate diff --git a/functions/utils/verifyMessage.js b/functions/utils/verifyMessage.js index 965e2fe6..9dbb028e 100644 --- a/functions/utils/verifyMessage.js +++ b/functions/utils/verifyMessage.js @@ -280,7 +280,6 @@ module.exports = { interest.amount=Math.max(0,interest.amountBase*(Math.exp(interest.rateYear/365*interest.days)-1)) interest.amountCummulate=(((userPreviousMessageData.interest||{}).amountCummulate)||0)+interest.amount wallet.balance=Math.round((Number(wallet.balance)+Number((interest.amount)||0))*100000)/100000 - wallet.shareBalance=wallet.balance //*******MESSAGE WRITES********************** //message event diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 92093a08..99a94ba2 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,11 +1,11 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { LoginComponent } from './login.component'; -import { ChatComponent } from './chat.component'; -import { ProfileComponent } from './profile.component'; -import { SettingsComponent } from './settings.component'; -import { DirectoryComponent } from './directory.component'; -import { buyPRNComponent } from './buyPRN.component'; +import { LoginComponent } from './login/login.component'; +import { ChatComponent } from './chat/chat.component'; +import { ProfileComponent } from './profile/profile.component'; +import { SettingsComponent } from './settings/settings.component'; +import { DirectoryComponent } from './directory/directory.component'; +import { buyPRNComponent } from './buyPRN/buyPRN.component'; const appRoutes: Routes = [ { path: 'chat/:id', component: ChatComponent }, diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 00000000..680f112a --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1,24 @@ + + 0% + +
+
+
Login
+
+ + {{UI.formatSharesToPRNCurrency(null,UI.currentUserLastMessageObj?.wallet?.balance||0)}} +
+
Buy PRN
+
+
+
+
+ +
\ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 4cdc69c9..79747633 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -5,33 +5,9 @@ import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/comp @Component({ selector: 'app-root', - template: ` - - 0% - -
-
-
Login
-
- - {{UI.formatSharesToPRNCurrency(null,UI.currentUserLastMessageObj?.wallet.shareBalance||0)}} -
-
Buy PRN
-
-
-
-
- -
- `, + templateUrl: './app.component.html', }) + export class AppComponent { constructor( diff --git a/src/app/app.module.ts b/src/app/app.module.ts index d9d768ca..cc6beaea 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -5,12 +5,12 @@ import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; -import { ChatComponent } from './chat.component'; -import { LoginComponent } from './login.component'; -import { ProfileComponent } from './profile.component'; -import { SettingsComponent } from './settings.component'; -import { DirectoryComponent } from './directory.component'; -import { buyPRNComponent } from './buyPRN.component'; +import { ChatComponent } from './chat/chat.component'; +import { LoginComponent } from './login/login.component'; +import { ProfileComponent } from './profile/profile.component'; +import { SettingsComponent } from './settings/settings.component'; +import { DirectoryComponent } from './directory/directory.component'; +import { buyPRNComponent } from './buyPRN/buyPRN.component'; import { LinkyModule } from 'angular-linky'; import { PipeModule } from './pipes.module'; diff --git a/src/app/buyPRN.component.ts b/src/app/buyPRN.component.ts deleted file mode 100644 index e8e39c23..00000000 --- a/src/app/buyPRN.component.ts +++ /dev/null @@ -1,363 +0,0 @@ -import { - AfterViewInit, - ChangeDetectorRef, - ElementRef, - Inject, - OnDestroy, - ViewChild, -} from "@angular/core"; -import { Component, NgZone } from "@angular/core"; -import { HttpClient } from "@angular/common/http"; -import { Observable } from "rxjs"; -import { map } from "rxjs/operators"; -import { Router } from "@angular/router"; -import { UserInterfaceService } from "./userInterface.service"; -import { - AngularFirestore, - AngularFirestoreCollection, -} from "@angular/fire/compat/firestore"; -import { AngularFireAuth } from "@angular/fire/compat/auth"; -import firebase from "firebase/compat/app"; -import { environment } from "environments/environment.prod"; -import { AgChartOptions } from 'ag-charts-community'; - -@Component({ - selector: "buyPRN", - template: ` -
-
-
-
-
- -
-
-
- PRN tokens represent ownership of the PERRINN network. -
- {{UI.PERRINNAdminLastMessageObj?.statistics?.emailsContributorsAuth?.length}} members own {{UI.formatSharesToPRNCurrency(currencySelected,UI.PERRINNAdminLastMessageObj?.statistics?.wallet?.shareBalance)}}. -
- You can follow the impact of your investment live on PERRINN.com -
PRN holders directory
-
-
- Your PRN amount grows at a rate of {{UI.appSettingsCosts?.interestRateYear | percent : "0.0"}} a year -
-
-
- encrypted -
- Your tokens are stored in your wallet on PERRINN.com -
- Soon you will be able to sell or exchange your tokens with other members here. -
-
-
-
-
-
-
- The capital raised from token sales goes towards -
-
- -
Show past funds
-
-
-
-
-
-
- Which currency are you using? -
-
-
    -
  • - {{ currency[1].designation }} -
  • -
-
-
-
-
-
-
-
- How much PRN would you like to buy? -
-
-
    -
  • - {{UI.formatSharesToCurrency(currencySelected,credit*UI.appSettingsPayment.currencyList[currencySelected].toCOIN)}} -
  • -
- You will pay {{UI.formatSharesToCurrency(currencySelected,creditList[creditSelected]*UI.appSettingsPayment.currencyList[currencySelected].toCOIN)}} and recieve {{UI.formatSharesToPRNCurrency(currencySelected,creditList[creditSelected]*UI.appSettingsPayment.currencyList[currencySelected].toCOIN)}}. -
-
-
-
-
-
- Credit or debit card -
-
-
-
-
-
- -
- -  {{ stripeMessage }} - -
-
- -
-
-
-
-
-
-
- `, -}) -export class buyPRNComponent { - cardNumber:string - expiryMonth:string - expiryYear:string - cvc:string - amountSharesPurchased:number - amountCharge:number - currencySelected:string - creditList:any - creditSelected:number - math:any - card:any - cardHandler = this.onChange.bind(this) - stripeMessage:string - @ViewChild("cardElement") cardElement:ElementRef - processing:boolean - currentFunds:Observable - public chartOptions:AgChartOptions - showPastFunds:boolean - - constructor( - public afAuth: AngularFireAuth, - public afs: AngularFirestore, - public router: Router, - private _zone: NgZone, - public UI: UserInterfaceService, - private cd: ChangeDetectorRef, - private http: HttpClient - ) { - if (UI.currentUserLastMessageObj != undefined) - this.currencySelected = - UI.currentUserLastMessageObj.userCurrency || "usd"; - else this.currencySelected = "usd"; - this.processing=false - this.showPastFunds=false - this.math = Math; - if(this.UI.currentUser=='QYm5NATKa6MGD87UpNZCTl6IolX2')this.creditList=[1,100,200,500,1000] - else this.creditList=[50,100,200,500,1000] - this.currentFunds = this.afs - .collection("PERRINNMessages", (ref) => - ref - .where("lastMessage", "==", true) - .where("verified", "==", true) - .orderBy("fund.daysLeft", "desc") - ) - .snapshotChanges() - .pipe( - map((changes) => { - return changes.map((c) => ({ payload: c.payload })); - }) - ); - this.chartOptions = { - title: { text: 'PRN growth' }, - data: [ - { year: 1296578670000, price: 1 }, - { year: this.UI.nowSeconds*1000-6*365*24*3600000, price: Math.exp((this.UI.nowSeconds*1000-6*365*24*3600000-1296578670000)/1000/3600/24/365*0.1) }, - { year: this.UI.nowSeconds*1000, price: Math.exp((this.UI.nowSeconds*1000-1296578670000)/1000/3600/24/365*0.1) }, - { year: this.UI.nowSeconds*1000+6*365*24*3600000, price: Math.exp((this.UI.nowSeconds*1000+6*365*24*3600000-1296578670000)/1000/3600/24/365*0.1) }, - ], - series: [{ type: 'line', xKey: 'year', yKey: 'price' }], - theme: 'ag-default-dark', - axes: [{ type: 'time', position: 'bottom' },{type: 'number',position: 'left',keys: ['price']}], - } - } - - ngAfterViewInit() { - this.card = elements.create("card"); - this.card.mount(this.cardElement.nativeElement); - this.card.addEventListener("change", this.cardHandler); - } - - ngOnInit() { - } - - ngOnDestroy() { - if (this.card) { - this.card.destroy(); - } - } - - onChange({ error }) { - if (error) this.stripeMessage = error.message; - else this.stripeMessage = null; - this.cd.detectChanges(); - } - async createStripeToken() { - this.processing = true; - this.createPaymentIntent(this.amountCharge, this.currencySelected); - // const { token, error } = await stripe.createToken(this.card); - // if (token) this.onSuccess(token); - // else this.onError(error); - } - onSuccess(paymentIntent) { - this.card.destroy(); - this.stripeMessage = "processing payment"; - this.afs - .collection("PERRINNTeams/" + this.UI.currentUser + "/payments") - .add({ - source: paymentIntent, - amountSharesPurchased: this.amountSharesPurchased, - amountCharge: this.amountCharge, - currency: this.currencySelected, - user: this.UI.currentUser, - serverTimestamp: firebase.firestore.FieldValue.serverTimestamp(), - }) - .then((chargeID) => { - this.afs - .doc( - "PERRINNTeams/" + this.UI.currentUser + "/payments/" + chargeID.id - ) - .valueChanges() - .subscribe((payment) => { - if (payment.status) - this.stripeMessage = `Payment ${payment.status}`; - }); - }); - } - onError(error) { - this.processing = false; - if (error.message) this.stripeMessage = error.message; - } - - refreshAmountCharge() { - if ( - this.creditSelected != undefined && - this.currencySelected != undefined - ) { - this.amountCharge = Number( - ((this.creditList[this.creditSelected] || 0) * 100).toFixed(0) - ); - this.amountSharesPurchased = Number( - (this.amountCharge / 100) * - this.UI.appSettingsPayment.currencyList[this.currencySelected].toCOIN - ); - } - } - - objectToArray(obj) { - if (obj == null) { - return []; - } - return Object.keys(obj).map(function (key) { - return [key, obj[key]]; - }); - } - - createPaymentIntent(amount: number, currency: string) { - const url = "https://api.stripe.com/v1/payment_intents"; - var urlencoded = new URLSearchParams(); - urlencoded.append("amount", amount.toString()); - urlencoded.append("currency", currency); - urlencoded.append("receipt_email", this.UI.currentUserEmail); - urlencoded.append( - "description", - `${this.amountSharesPurchased} Shares to ${this.UI.currentUserEmail}` - ); - const params = { - headers: { - "Content-Type": "application/x-www-form-urlencoded", - Authorization: `Bearer ${environment.STRIPE_SECRET}`, - }, - }; - const res = this.http.post(url, urlencoded, params).subscribe( - (success) => { - this.submitPayment(success); - }, - ({ error: { error } }) => { - console.log(error); - this.stripeMessage = error.errorMessage; - } - ); - return res; - } - - submitPayment = async (intent) => { - console.log("success"); - const data = { - payment_method: { card: this.card }, - }; - const { paymentIntent, error } = await stripe.confirmCardPayment( - intent.client_secret, - data - ); - if (error) { - this.onError(error); - } - if (paymentIntent) this.onSuccess(paymentIntent); - }; -} diff --git a/src/app/buyPRN/buyPRN.component.html b/src/app/buyPRN/buyPRN.component.html new file mode 100644 index 00000000..d4763a60 --- /dev/null +++ b/src/app/buyPRN/buyPRN.component.html @@ -0,0 +1,146 @@ +
+
+
+
+
+ +
+
+
+ PRN tokens represent ownership of the PERRINN team. +
+ {{UI.PERRINNAdminLastMessageObj?.statistics?.emailsContributorsAuth?.length}} members own {{UI.formatSharesToPRNCurrency(currencySelected,UI.PERRINNAdminLastMessageObj?.statistics?.wallet?.balance)}}. +
+ You can follow the impact of your investment live on PERRINN.com +
PRN holders directory
+
+
+ Your PRN amount grows at a rate of {{UI.appSettingsCosts?.interestRateYear | percent : "0.0"}} a year +
+
+
+ encrypted +
+ Your tokens are stored in your wallet on PERRINN.com +
+ Soon you will be able to sell or exchange your tokens with other members here. +
+
+
+
+
+
+
+ The capital raised from token sales goes towards +
+
+
    +
  • +
    + {{message.payload.doc.data()?.chatSubject}} +
    +
    +
    +
    + {{message.payload.doc.data()?.fund?.amountGBPRaised/message.payload.doc.data()?.fund?.amountGBPTarget|percent:"1.0-0"}} +
    +
    {{message.payload.doc.data()?.fund?.daysLeft|number:"1.0-0"}} days left
    +
    {{-message.payload.doc.data()?.fund?.daysLeft|number:"1.0-0"}} days ago
    +
    {{ message.payload.doc.data()?.fund?.description }},
    +
    target: {{UI.formatSharesToCurrency(null,message.payload.doc.data()?.fund?.amountGBPTarget*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}} /
    +
    raised: {{UI.formatSharesToCurrency(null,message.payload.doc.data()?.fund?.amountGBPRaised*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}}
    +
    +
    +
  • +
+
Show past funds
+
+
+
+
+
+
+ Which currency are you using? +
+
+
    +
  • + {{ currency[1].designation }} +
  • +
+
+
+
+
+
+
+
+ How much PRN would you like to buy? +
+
+
    +
  • + {{UI.formatSharesToCurrency(currencySelected,credit*UI.appSettingsPayment.currencyList[currencySelected].toCOIN)}} +
  • +
+ You will pay {{UI.formatSharesToCurrency(currencySelected,creditList[creditSelected]*UI.appSettingsPayment.currencyList[currencySelected].toCOIN)}} and recieve {{UI.formatSharesToPRNCurrency(currencySelected,creditList[creditSelected]*UI.appSettingsPayment.currencyList[currencySelected].toCOIN)}}. +
+
+
+
+
+
+ Credit or debit card +
+
+
+
+
+
+ +
+ +  {{ stripeMessage }} + +
+
+ +
+
+
+
+
+
+
\ No newline at end of file diff --git a/src/app/buyPRN/buyPRN.component.ts b/src/app/buyPRN/buyPRN.component.ts new file mode 100644 index 00000000..11f47318 --- /dev/null +++ b/src/app/buyPRN/buyPRN.component.ts @@ -0,0 +1,217 @@ +import { + AfterViewInit, + ChangeDetectorRef, + ElementRef, + Inject, + OnDestroy, + ViewChild, +} from "@angular/core"; +import { Component, NgZone } from "@angular/core"; +import { HttpClient } from "@angular/common/http"; +import { Observable } from "rxjs"; +import { map } from "rxjs/operators"; +import { Router } from "@angular/router"; +import { UserInterfaceService } from "./../userInterface.service"; +import { + AngularFirestore, + AngularFirestoreCollection, +} from "@angular/fire/compat/firestore"; +import { AngularFireAuth } from "@angular/fire/compat/auth"; +import firebase from "firebase/compat/app"; +import { environment } from "environments/environment.prod"; +import { AgChartOptions } from 'ag-charts-community'; + +@Component({ + selector: "buyPRN", + templateUrl: './buyPRN.component.html', +}) + +export class buyPRNComponent { + cardNumber:string + expiryMonth:string + expiryYear:string + cvc:string + amountSharesPurchased:number + amountCharge:number + currencySelected:string + creditList:any + creditSelected:number + math:any + card:any + cardHandler = this.onChange.bind(this) + stripeMessage:string + @ViewChild("cardElement") cardElement:ElementRef + processing:boolean + currentFunds:Observable + public chartOptions:AgChartOptions + showPastFunds:boolean + + constructor( + public afAuth: AngularFireAuth, + public afs: AngularFirestore, + public router: Router, + private _zone: NgZone, + public UI: UserInterfaceService, + private cd: ChangeDetectorRef, + private http: HttpClient + ) { + if (UI.currentUserLastMessageObj != undefined) + this.currencySelected = + UI.currentUserLastMessageObj.userCurrency || "usd"; + else this.currencySelected = "usd"; + this.processing=false + this.showPastFunds=false + this.math = Math; + if(this.UI.currentUser=='QYm5NATKa6MGD87UpNZCTl6IolX2')this.creditList=[1,100,200,500,1000] + else this.creditList=[50,100,200,500,1000] + this.currentFunds = this.afs + .collection("PERRINNMessages", (ref) => + ref + .where("lastMessage", "==", true) + .where("verified", "==", true) + .orderBy("fund.daysLeft", "desc") + ) + .snapshotChanges() + .pipe( + map((changes) => { + return changes.map((c) => ({ payload: c.payload })); + }) + ); + this.chartOptions = { + title: { text: 'PRN growth' }, + data: [ + { year: 1296578670000, price: 1 }, + { year: this.UI.nowSeconds*1000-6*365*24*3600000, price: Math.exp((this.UI.nowSeconds*1000-6*365*24*3600000-1296578670000)/1000/3600/24/365*0.1) }, + { year: this.UI.nowSeconds*1000, price: Math.exp((this.UI.nowSeconds*1000-1296578670000)/1000/3600/24/365*0.1) }, + { year: this.UI.nowSeconds*1000+6*365*24*3600000, price: Math.exp((this.UI.nowSeconds*1000+6*365*24*3600000-1296578670000)/1000/3600/24/365*0.1) }, + ], + series: [{ type: 'line', xKey: 'year', yKey: 'price' }], + theme: 'ag-default-dark', + axes: [{ type: 'time', position: 'bottom' },{type: 'number',position: 'left',keys: ['price']}], + } + } + + ngAfterViewInit() { + this.card = elements.create("card"); + this.card.mount(this.cardElement.nativeElement); + this.card.addEventListener("change", this.cardHandler); + } + + ngOnInit() { + } + + ngOnDestroy() { + if (this.card) { + this.card.destroy(); + } + } + + onChange({ error }) { + if (error) this.stripeMessage = error.message; + else this.stripeMessage = null; + this.cd.detectChanges(); + } + async createStripeToken() { + this.processing = true; + this.createPaymentIntent(this.amountCharge, this.currencySelected); + // const { token, error } = await stripe.createToken(this.card); + // if (token) this.onSuccess(token); + // else this.onError(error); + } + onSuccess(paymentIntent) { + this.card.destroy(); + this.stripeMessage = "processing payment"; + this.afs + .collection("PERRINNTeams/" + this.UI.currentUser + "/payments") + .add({ + source: paymentIntent, + amountSharesPurchased: this.amountSharesPurchased, + amountCharge: this.amountCharge, + currency: this.currencySelected, + user: this.UI.currentUser, + serverTimestamp: firebase.firestore.FieldValue.serverTimestamp(), + }) + .then((chargeID) => { + this.afs + .doc( + "PERRINNTeams/" + this.UI.currentUser + "/payments/" + chargeID.id + ) + .valueChanges() + .subscribe((payment) => { + if (payment.status) + this.stripeMessage = `Payment ${payment.status}`; + }); + }); + } + onError(error) { + this.processing = false; + if (error.message) this.stripeMessage = error.message; + } + + refreshAmountCharge() { + if ( + this.creditSelected != undefined && + this.currencySelected != undefined + ) { + this.amountCharge = Number( + ((this.creditList[this.creditSelected] || 0) * 100).toFixed(0) + ); + this.amountSharesPurchased = Number( + (this.amountCharge / 100) * + this.UI.appSettingsPayment.currencyList[this.currencySelected].toCOIN + ); + } + } + + objectToArray(obj) { + if (obj == null) { + return []; + } + return Object.keys(obj).map(function (key) { + return [key, obj[key]]; + }); + } + + createPaymentIntent(amount: number, currency: string) { + const url = "https://api.stripe.com/v1/payment_intents"; + var urlencoded = new URLSearchParams(); + urlencoded.append("amount", amount.toString()); + urlencoded.append("currency", currency); + urlencoded.append("receipt_email", this.UI.currentUserEmail); + urlencoded.append( + "description", + `${this.amountSharesPurchased} Shares to ${this.UI.currentUserEmail}` + ); + const params = { + headers: { + "Content-Type": "application/x-www-form-urlencoded", + Authorization: `Bearer ${environment.STRIPE_SECRET}`, + }, + }; + const res = this.http.post(url, urlencoded, params).subscribe( + (success) => { + this.submitPayment(success); + }, + ({ error: { error } }) => { + console.log(error); + this.stripeMessage = error.errorMessage; + } + ); + return res; + } + + submitPayment = async (intent) => { + console.log("success"); + const data = { + payment_method: { card: this.card }, + }; + const { paymentIntent, error } = await stripe.confirmCardPayment( + intent.client_secret, + data + ); + if (error) { + this.onError(error); + } + if (paymentIntent) this.onSuccess(paymentIntent); + }; +} diff --git a/src/app/chat.component.ts b/src/app/chat/chat.component.html similarity index 63% rename from src/app/chat.component.ts rename to src/app/chat/chat.component.html index a8f99b70..7f117f38 100644 --- a/src/app/chat.component.ts +++ b/src/app/chat/chat.component.html @@ -1,643 +1,273 @@ -import { Component } from '@angular/core' -import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore' -import { Observable } from 'rxjs' -import { map } from 'rxjs/operators' -import { Router, ActivatedRoute } from '@angular/router' -import { UserInterfaceService } from './userInterface.service' -import { AngularFireStorage } from '@angular/fire/compat/storage' -import firebase from 'firebase/compat/app' - -@Component({ - selector:'chat', - template:` - -
-
-
-
-
- settings -
{{chatLastMessageObj?.chatSubject}}
-
-
- {{recipient==UI.currentUser?'You':chatLastMessageObj?.recipients[recipient]?.name}}{{last?"":", "}} -
-
- event -
in {{UI.formatSecondsToDhm2(eventDateStart/1000-UI.nowSeconds)}}
-
Now
- {{eventDescription}} - {{eventDateStart|date:'EEEE d MMM h:mm a'}} ({{eventDuration}}h) -
-
- crowdsource -
-
-
{{(fund?.amountGBPRaised/fund?.amountGBPTarget)|percent:'1.0-0'}}
-
{{fund.daysLeft|number:'1.0-0'}} days left
-
{{fund.description}},
-
target: {{UI.formatSharesToCurrency(null,fund?.amountGBPTarget*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}} /
-
raised: {{UI.formatSharesToCurrency(null,fund?.amountGBPRaised*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}}
-
-
- poll -
{{UI.formatSecondsToDhm2(survey.expiryTimestamp/1000-UI.nowSeconds)}} left
-
{{survey.question}}
- {{answer.answer}} ({{(answer.votes.length/survey.totalVotes)|percent:'1.0-0'}}) - {{survey.totalVotes}} vote{{survey.totalVotes>1?'s':''}} -
vote now
-
-
- {{showImageGallery?'question_answer':'collections'}} -
- Join -
-
-
-
< messages
-
-
-
-
- - -
- -
Save
-
-
    -
  • -
    - -
    {{chatLastMessageObj?.recipients[recipient]?.name}}
    -
    -
    X
    -
  • -
- -
    -
  • -
    -
    - - {{team.values?.name}} {{UI.formatSharesToPRNCurrency(null,team.values?.wallet?.shareBalance||0)}} -
    -
    Add
    -
    -
  • -
-
- Sending PRN {{UI.appSettingsPayment.currencyList[UI.currentUserLastMessageObj.userCurrency].designation}}: - - -
-
    -
  • -
    - -
    {{chatLastMessageObj?.recipients[recipient]?.name}}
    -
    -
  • -
-
-
- Send {{UI.formatSharesToPRNCurrency(null,transactionAmount*UI.appSettingsPayment.currencyList[this.UI.currentUserLastMessageObj.userCurrency].toCOIN)}} to {{transactionUserName}} -
-
-
- -
{{eventDateStart==0?'':eventDateStart|date:'EEEE d MMM h:mm a'}}
-
Save event
-
    -
  • -
    {{date|date:'EEEE'}}
    -
    {{date|date:'d MMM'}}
    -
  • -
-
    -
  • -
    {{date|date:'h:mm a'}}
    -
  • -
-
- Event duration (hours) - -
- Event location - -
Cancel event
-
-
- Fund description - -
- Amount target - -
- Days left - -
Save fund
-
-
-
-
created on {{survey.createdTimestamp|date:'EEEE d MMM h:mm a'}} expiring on {{survey.expiryTimestamp|date:'EEEE d MMM h:mm a'}}
- Duration of the survey (days) - - -
Save survey
-
    -
  • -
    -
    -
    Vote
    -
    - -
    - {{user==UI.currentUser?'You':chatLastMessageObj?.recipients[user]?.name}}{{last?"":", "}} -
  • -
-
Add answer
-
-
-
- -
-
-
-
-
-
-
-
    -
  • -
    -
    Load more
    -
    {{(message.payload?.serverTimestamp?.seconds*1000)|date:'fullDate'}}
    -
    -
    -
    - -
    -
    -
    -
    -
    {{message.payload?.name}}
    -
    {{(message.payload?.serverTimestamp?.seconds*1000)|date:'h:mm a'}}
    -
    {{UI.formatSecondsToDhm1(math.max(0,(UI.nowSeconds-message.payload?.serverTimestamp?.seconds)))}}
    -
    -
    - -
    -
    -
    {{message.payload?.statistics?.userCount}} Members,
    -
    {{message.payload?.statistics?.emailsContributorsAuth?.length}} PRN holders.
    -
    {{UI.formatSharesToPRNCurrency(null,message.payload?.statistics?.wallet?.shareBalance)}} invested.
    -
    {{UI.formatSharesToCurrency(null,message.payload?.statistics?.stripeBalance?.available[0]?.amount/100*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}} available in the PERRINN fund
    -
    ({{UI.formatSharesToCurrency(null,message.payload?.statistics?.stripeBalance?.pending[0]?.amount/100*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}} pending).
    -
    -
    -
    Email addresses {{message.payload?.emails|json}}
    -
    -
    userChain {{message.payload?.userChain|json}}
    -
    -
    transactionOut {{message.payload?.transactionOut|json}}
    -
    -
    transactionIn {{message.payload?.transactionIn|json}}
    -
    -
    Share purchase {{message.payload?.purchaseCOIN|json}}
    -
    -
    interest {{message.payload?.interest|json}}
    -
    -
    contract {{message.payload?.contract|json}}
    -
    -
    wallet {{message.payload?.wallet|json}}
    -
    -
    -
    fund {{message.payload?.fund|json}}
    -
    -
    survey {{message.payload?.survey|json}}
    -
    -
    {{message.payload|json}}
    -
    -
    -
    - done - aspect_ratio - +{{UI.formatSharesToPRNCurrency(null,message.payload?.contract?.amount)}} earned ({{UI.formatSecondsToDhm1(message.payload?.contract?.hoursValidated*3600)}}declared in {{UI.formatSecondsToDhm1(message.payload?.contract?.hoursAvailable*3600)}} window) - +{{UI.formatSharesToPRNCurrency(null,message.payload?.purchaseCOIN?.amount)}} purchased - +{{UI.formatSharesToPRNCurrency(null,message.payload?.transactionIn?.amount)}} received - {{UI.formatSharesToPRNCurrency(null,-message.payload?.transactionOut?.amount)}} sent - {{UI.formatSharesToPRNCurrency(null,message.payload?.wallet?.shareBalance)}} -
    -
    -
    Details
    -
    -
    -
    Last read
    - {{storeMessageValues(message.payload)}} - {{(last||i==(messageNumberDisplay-1))?scrollToBottom(message.payload?.serverTimestamp?.seconds):''}} -
  • -
-
-
-
- -
-
-
-
-
-
-
-
    -
  • - -
    - {{message.payload?.name}}: {{message.payload?.text}} -
    -
  • -
-
-
-
- -
-
- This message will be the subject of this chat -
-
- -
- -
-
-
- send -
-
- - -
-
-
- ` -}) -export class ChatComponent { - draftMessage:string - imageTimestamp:string - imageDownloadUrl:string - messageNumberDisplay:number - lastChatVisitTimestamp:number - scrollMessageTimestamp:number - previousMessageServerTimestamp:any - previousMessageUser:string - messageShowDetails:[] - messages:Observable - teams:Observable - searchFilter:string - reads:any[] - chatSubject:string - chatLastMessageObj:any - chatChain:string - showChatDetails:boolean - math:any - eventDateList:any - eventDateStart:any - eventDateEnd:any - eventDescription:string - eventDuration:number - eventLocation:string - fund:any - surveyDefault:any - survey:any - messageShowActions:[] - lastRead:string - showImageGallery:boolean - - constructor( - public afs:AngularFirestore, - public router:Router, - public UI:UserInterfaceService, - private route:ActivatedRoute, - private storage:AngularFireStorage, - ) { - this.math=Math - this.UI.loading=true - this.reads=[] - this.route.params.subscribe(params=>{ - this.lastRead=null - this.chatChain=params.id - this.messageShowActions=[] - this.messageShowDetails=[] - this.chatLastMessageObj={} - this.previousMessageServerTimestamp={seconds:this.UI.nowSeconds*1000} - this.previousMessageUser='' - this.messageNumberDisplay=15 - this.chatSubject='' - this.eventDescription='' - this.eventDuration=1 - this.eventLocation="" - this.fund={ - description:'add a description', - amountGBPTarget:0, - daysLeft:30 - } - this.surveyDefault={ - question:'Survey question', - durationDays:7, - answers:[ - {answer:'Answer A',votes:[]}, - {answer:'Answer B',votes:[]}, - {answer:'Answer C',votes:[]} - ] - } - this.survey=this.surveyDefault - this.refreshMessages(params.id) - this.refresheventDateList() - this.resetChat() - }) - } - - ngOnInit(){ - this.refreshSearchLists() - } - - showImageGalleryClick(){ - event.stopPropagation() - this.showImageGallery=!this.showImageGallery - this.refreshMessages(this.chatLastMessageObj.chain||this.chatChain) - } - - loadMore(){ - this.UI.loading=true - this.messageNumberDisplay+=15 - this.refreshMessages(this.chatLastMessageObj.chain||this.chatChain) - } - - refresheventDateList(){ - var i - this.eventDateList=[] - for(i=0;i<1010;i++){ - this.eventDateList[i]=(Math.ceil(this.UI.nowSeconds/3600)+i/2)*3600000 - } - } - - refreshMessages(chain) { - if(!this.showImageGallery)this.messages=this.afs.collection('PERRINNMessages',ref=>ref - .where('chain','==',chain) - .orderBy('serverTimestamp','desc') - .limit(this.messageNumberDisplay) - ).snapshotChanges().pipe(map(changes=>{ - this.UI.loading=false - var batch=this.afs.firestore.batch() - var nextMessageRead=true - changes.forEach(c=>{ - if(this.UI.currentUser&&!this.lastRead&&!nextMessageRead&&(c.payload.doc.data()['reads']||[])[this.UI.currentUser])this.lastRead=c.payload.doc.id - nextMessageRead=(c.payload.doc.data()['reads']||[])[this.UI.currentUser] - if(c.payload.doc.data()['lastMessage']){ - if(this.UI.currentUser&&!this.reads.includes(c.payload.doc.id))batch.set(this.afs.firestore.collection('PERRINNTeams').doc(this.UI.currentUser).collection('reads').doc(c.payload.doc.id),{serverTimestamp:firebase.firestore.FieldValue.serverTimestamp()},{merge:true}) - this.reads.push(c.payload.doc.id) - this.chatLastMessageObj=c.payload.doc.data() - this.chatSubject=c.payload.doc.data()['chatSubject'] - this.eventDescription=c.payload.doc.data()['eventDescription'] - this.eventDateStart=c.payload.doc.data()['eventDateStart'] - this.eventDateEnd=c.payload.doc.data()['eventDateEnd'] - this.eventDuration=c.payload.doc.data()['eventDuration'] - this.eventLocation=c.payload.doc.data()['eventLocation'] - this.fund=c.payload.doc.data()['fund']||this.fund - this.survey=((c.payload.doc.data()['survey']||{})['createdTimestamp'])?c.payload.doc.data()['survey']:this.survey - } - }) - batch.commit() - return changes.reverse().map(c=>({ - key:c.payload.doc.id, - payload:c.payload.doc.data() - })) - })) - else this.messages=this.afs.collection('PERRINNMessages',ref=>ref - .where('chain','==',chain) - .orderBy('chatImageTimestamp','desc') - .limit(this.messageNumberDisplay) - ).snapshotChanges().pipe(map(changes=>{ - this.UI.loading=false - var batch=this.afs.firestore.batch() - var nextMessageRead=true - changes.forEach(c=>{ - if(this.UI.currentUser&&!this.lastRead&&!nextMessageRead&&(c.payload.doc.data()['reads']||[])[this.UI.currentUser])this.lastRead=c.payload.doc.id - nextMessageRead=(c.payload.doc.data()['reads']||[])[this.UI.currentUser] - if(c.payload.doc.data()['lastMessage']){ - if(this.UI.currentUser&&!this.reads.includes(c.payload.doc.id))batch.set(this.afs.firestore.collection('PERRINNTeams').doc(this.UI.currentUser).collection('reads').doc(c.payload.doc.id),{serverTimestamp:firebase.firestore.FieldValue.serverTimestamp()},{merge:true}) - this.reads.push(c.payload.doc.id) - this.chatLastMessageObj=c.payload.doc.data() - this.chatSubject=c.payload.doc.data()['chatSubject'] - this.eventDescription=c.payload.doc.data()['eventDescription'] - this.eventDateStart=c.payload.doc.data()['eventDateStart'] - this.eventDuration=c.payload.doc.data()['eventDuration'] - this.eventLocation=c.payload.doc.data()['eventLocation'] - this.fund=c.payload.doc.data()['fund']||this.fund - this.survey=((c.payload.doc.data()['survey']||{})['createdTimestamp'])?c.payload.doc.data()['survey']:this.survey - } - }) - batch.commit() - return changes.map(c=>({ - key:c.payload.doc.id, - payload:c.payload.doc.data() - })) - })) - } - - isMessageNewTimeGroup(messageServerTimestamp:any) { - let isMessageNewTimeGroup:boolean - isMessageNewTimeGroup=Math.abs(messageServerTimestamp.seconds - this.previousMessageServerTimestamp.seconds) > 60 * 60 * 4 - return isMessageNewTimeGroup - } - - isMessageNewUserGroup(user:any,messageServerTimestamp:any) { - let isMessageNewUserGroup:boolean - isMessageNewUserGroup=Math.abs(messageServerTimestamp.seconds - this.previousMessageServerTimestamp.seconds) > 60 * 5 || (user != this.previousMessageUser) - return isMessageNewUserGroup - } - - storeMessageValues(message) { - this.previousMessageUser=message.user - this.previousMessageServerTimestamp=message.serverTimestamp||{seconds:this.UI.nowSeconds*1000} - } - - scrollToBottom(scrollMessageTimestamp:number) { - if (scrollMessageTimestamp != this.scrollMessageTimestamp) { - const element=document.getElementById('chat_window') - element.scrollTop=element.scrollHeight - this.scrollMessageTimestamp=scrollMessageTimestamp - } - } - - saveNewSubject() { - this.UI.createMessage({ - text:'Changing subject to '+this.chatSubject, - chain:this.chatLastMessageObj.chain||this.chatChain, - chatSubject:this.chatSubject, - }) - this.resetChat() - } - - sendCredit(transactionAmount,transactionCode,transactionUser,transactionUserName){ - this.UI.createMessage({ - text:'sending '+this.UI.appSettingsPayment.currencyList[this.UI.currentUserLastMessageObj.userCurrency].symbol+transactionAmount+' to '+transactionUserName+((transactionCode||null)?' using code ':'')+((transactionCode||null)?transactionCode:''), - chain:this.chatLastMessageObj.chain||this.chatChain, - transactionOut:{ - user:transactionUser, - amount:transactionAmount*this.UI.appSettingsPayment.currencyList[this.UI.currentUserLastMessageObj.userCurrency].toCOIN, - code:transactionCode||null - } - }) - this.resetChat() - } - - saveEvent() { - this.UI.createMessage({ - text:'new event', - chain:this.chatLastMessageObj.chain||this.chatChain, - eventDateStart:this.eventDateStart, - eventDateEnd:this.eventDateStart+this.eventDuration*3600000, - eventDescription:this.eventDescription, - eventDuration:this.eventDuration, - eventLocation:this.eventLocation - }) - this.resetChat() - } - - cancelEvent() { - this.UI.createMessage({ - text:'cancelling event', - chain:this.chatLastMessageObj.chain||this.chatChain, - eventDateStart:this.UI.nowSeconds*1000-3600000, - eventDateEnd:this.UI.nowSeconds*1000-3600000 - }) - this.resetChat() - } - - saveFund() { - this.UI.createMessage({ - text:'edited fund', - chain:this.chatLastMessageObj.chain||this.chatChain, - fund:this.fund - }) - this.resetChat() - } - - saveSurvey() { - this.UI.createMessage({ - text:'Survey saved', - chain:this.chatLastMessageObj.chain||this.chatChain, - survey:this.survey - }) - this.resetChat() - } - - voteSurvey(i) { - this.UI.createMessage({ - text:'Survey vote '+this.survey.answers[i].answer, - chain:this.chatLastMessageObj.chain||this.chatChain, - survey:{voteIndexPlusOne:i+1} - }) - this.resetChat() - } - - addMessage() { - this.UI.createMessage({ - text:this.draftMessage, - chain:this.chatLastMessageObj.chain||this.chatChain, - chatImageTimestamp:this.imageTimestamp, - chatImageUrlThumb:this.imageDownloadUrl, - chatImageUrlMedium:this.imageDownloadUrl, - chatImageUrlOriginal:this.imageDownloadUrl - }) - this.resetChat() - } - - addRecipient(user,name) { - this.UI.createMessage({ - text:'adding '+name+' to this chat.', - chain:this.chatLastMessageObj.chain||this.chatChain, - recipientList:[user] - }) - this.resetChat() - } - - removeRecipient(user,name){ - this.UI.createMessage({ - text:'removing '+name+' from this chat.', - chain:this.chatLastMessageObj.chain||this.chatChain, - recipientListToBeRemoved:[user] - }) - this.resetChat() - } - - onImageChange(event:any) { - const image=event.target.files[0] - const uploader=document.getElementById('uploader') as HTMLInputElement - const storageRef=this.storage.ref('images/' + Date.now() + image.name) - const task=storageRef.put(image) - - task.snapshotChanges().subscribe((snapshot)=>{ - document.getElementById('buttonFile').style.visibility='hidden' - document.getElementById('uploader').style.visibility='visible' - - const percentage=(snapshot.bytesTransferred / snapshot.totalBytes) * 100 - uploader.value=percentage.toString() - }, - (err:any)=>{ - document.getElementById('buttonFile').style.visibility='visible' - document.getElementById('uploader').style.visibility='hidden' - uploader.value='0' - }, - ()=>{ - uploader.value='0' - document.getElementById('buttonFile').style.visibility='visible' - document.getElementById('uploader').style.visibility='hidden' - this.imageTimestamp=task.task.snapshot.ref.name.substring(0, 13) - storageRef.getDownloadURL().subscribe(url=>{ - this.imageDownloadUrl=url - event.target.value='' - }) - }) - } - - refreshSearchLists() { - if (this.searchFilter) { - if (this.searchFilter.length > 1) { - this.teams=this.afs.collection('PERRINNMessages', ref=>ref - .where('userChain.nextMessage','==','none') - .where('verified','==',true) - .where('nameLowerCase','>=',this.searchFilter.toLowerCase()) - .where('nameLowerCase','<=',this.searchFilter.toLowerCase()+'\uf8ff') - .orderBy('nameLowerCase') - .limit(20)) - .snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({ - key:c.payload.doc.id, - values:c.payload.doc.data() - })) - })) - } - } else { - this.teams=null - } - } - - resetChat(){ - this.searchFilter=null - this.teams=null - this.draftMessage='' - this.imageTimestamp=null - this.imageDownloadUrl=null - this.showChatDetails=false - this.messageShowDetails=[] - this.messageShowActions=[] - } - -} +
+
+
+
+
+ settings +
{{chatLastMessageObj?.chatSubject}}
+
+
+ {{recipient==UI.currentUser?'You':chatLastMessageObj?.recipients[recipient]?.name}}{{last?"":", "}} +
+
+ event +
in {{UI.formatSecondsToDhm2(eventDateStart/1000-UI.nowSeconds)}}
+
Now
+ {{eventDescription}} + {{eventDateStart|date:'EEEE d MMM h:mm a'}} ({{eventDuration}}h) +
+
+ crowdsource +
+
+
{{(fund?.amountGBPRaised/fund?.amountGBPTarget)|percent:'1.0-0'}}
+
{{fund.daysLeft|number:'1.0-0'}} days left
+
{{fund.description}},
+
target: {{UI.formatSharesToCurrency(null,fund?.amountGBPTarget*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}} /
+
raised: {{UI.formatSharesToCurrency(null,fund?.amountGBPRaised*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}}
+
+
+ poll +
{{UI.formatSecondsToDhm2(survey.expiryTimestamp/1000-UI.nowSeconds)}} left
+
{{survey.question}}
+ {{answer.answer}} ({{(answer.votes.length/survey.totalVotes)|percent:'1.0-0'}}) + {{survey.totalVotes}} vote{{survey.totalVotes>1?'s':''}} +
vote now
+
+
+ {{showImageGallery?'question_answer':'collections'}} +
+ Join +
+
+
+
< messages
+
+
+
+
+ + +
+ +
Save
+
+
    +
  • +
    + +
    {{chatLastMessageObj?.recipients[recipient]?.name}}
    +
    +
    X
    +
  • +
+ +
    +
  • +
    +
    + + {{team.values?.name}} {{UI.formatSharesToPRNCurrency(null,team.values?.wallet?.balance||0)}} +
    +
    Add
    +
    +
  • +
+
+ Sending PRN {{UI.appSettingsPayment.currencyList[UI.currentUserLastMessageObj.userCurrency].designation}}: + + +
+
    +
  • +
    + +
    {{chatLastMessageObj?.recipients[recipient]?.name}}
    +
    +
  • +
+
+
+ Send {{UI.formatSharesToPRNCurrency(null,transactionAmount*UI.appSettingsPayment.currencyList[this.UI.currentUserLastMessageObj.userCurrency].toCOIN)}} to {{transactionUserName}} +
+
+
+ +
{{eventDateStart==0?'':eventDateStart|date:'EEEE d MMM h:mm a'}}
+
Save event
+
    +
  • +
    {{date|date:'EEEE'}}
    +
    {{date|date:'d MMM'}}
    +
  • +
+
    +
  • +
    {{date|date:'h:mm a'}}
    +
  • +
+
+ Event duration (hours) + +
+ Event location + +
Cancel event
+
+
+ Fund description + +
+ Amount target + +
+ Days left + +
Save fund
+
+
+
+
created on {{survey.createdTimestamp|date:'EEEE d MMM h:mm a'}} expiring on {{survey.expiryTimestamp|date:'EEEE d MMM h:mm a'}}
+ Duration of the survey (days) + + +
Save survey
+
    +
  • +
    +
    +
    Vote
    +
    + +
    + {{user==UI.currentUser?'You':chatLastMessageObj?.recipients[user]?.name}}{{last?"":", "}} +
  • +
+
Add answer
+
+
+
+ +
+
+
+
+
+
+
+
    +
  • +
    +
    Load more
    +
    {{(message.payload?.serverTimestamp?.seconds*1000)|date:'fullDate'}}
    +
    +
    +
    + +
    +
    +
    +
    +
    {{message.payload?.name}}
    +
    {{(message.payload?.serverTimestamp?.seconds*1000)|date:'h:mm a'}}
    +
    {{UI.formatSecondsToDhm1(math.max(0,(UI.nowSeconds-message.payload?.serverTimestamp?.seconds)))}}
    +
    +
    + +
    +
    +
    {{message.payload?.statistics?.userCount}} Members,
    +
    {{message.payload?.statistics?.emailsContributorsAuth?.length}} PRN holders.
    +
    {{UI.formatSharesToPRNCurrency(null,message.payload?.statistics?.wallet?.balance)}} invested.
    +
    {{UI.formatSharesToCurrency(null,message.payload?.statistics?.stripeBalance?.available[0]?.amount/100*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}} available in the PERRINN fund
    +
    ({{UI.formatSharesToCurrency(null,message.payload?.statistics?.stripeBalance?.pending[0]?.amount/100*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}} pending).
    +
    +
    +
    Email addresses {{message.payload?.emails|json}}
    +
    +
    userChain {{message.payload?.userChain|json}}
    +
    +
    transactionOut {{message.payload?.transactionOut|json}}
    +
    +
    transactionIn {{message.payload?.transactionIn|json}}
    +
    +
    Share purchase {{message.payload?.purchaseCOIN|json}}
    +
    +
    interest {{message.payload?.interest|json}}
    +
    +
    contract {{message.payload?.contract|json}}
    +
    +
    wallet {{message.payload?.wallet|json}}
    +
    +
    +
    fund {{message.payload?.fund|json}}
    +
    +
    survey {{message.payload?.survey|json}}
    +
    +
    {{message.payload|json}}
    +
    +
    +
    + done + aspect_ratio + +{{UI.formatSharesToPRNCurrency(null,message.payload?.contract?.amount)}} earned ({{UI.formatSecondsToDhm1(message.payload?.contract?.hoursValidated*3600)}}declared in {{UI.formatSecondsToDhm1(message.payload?.contract?.hoursAvailable*3600)}} window) + +{{UI.formatSharesToPRNCurrency(null,message.payload?.purchaseCOIN?.amount)}} purchased + +{{UI.formatSharesToPRNCurrency(null,message.payload?.transactionIn?.amount)}} received + {{UI.formatSharesToPRNCurrency(null,-message.payload?.transactionOut?.amount)}} sent + {{UI.formatSharesToPRNCurrency(null,message.payload?.wallet?.balance)}} +
    +
    +
    Details
    +
    +
    +
    Last read
    + {{storeMessageValues(message.payload)}} + {{(last||i==(messageNumberDisplay-1))?scrollToBottom(message.payload?.serverTimestamp?.seconds):''}} +
  • +
+
+
+
+ +
+
+
+
+
+
+
+
    +
  • + +
    + {{message.payload?.name}}: {{message.payload?.text}} +
    +
  • +
+
+
+
+ +
+
+ This message will be the subject of this chat +
+
+ +
+ +
+
+
+ send +
+
+ + +
+
+
\ No newline at end of file diff --git a/src/app/chat/chat.component.ts b/src/app/chat/chat.component.ts new file mode 100644 index 00000000..9f7692cf --- /dev/null +++ b/src/app/chat/chat.component.ts @@ -0,0 +1,369 @@ +import { Component } from '@angular/core' +import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore' +import { Observable } from 'rxjs' +import { map } from 'rxjs/operators' +import { Router, ActivatedRoute } from '@angular/router' +import { UserInterfaceService } from './../userInterface.service' +import { AngularFireStorage } from '@angular/fire/compat/storage' +import firebase from 'firebase/compat/app' + +@Component({ + selector:'chat', + templateUrl:'./chat.component.html', +}) + +export class ChatComponent { + draftMessage:string + imageTimestamp:string + imageDownloadUrl:string + messageNumberDisplay:number + lastChatVisitTimestamp:number + scrollMessageTimestamp:number + previousMessageServerTimestamp:any + previousMessageUser:string + messageShowDetails:[] + messages:Observable + teams:Observable + searchFilter:string + reads:any[] + chatSubject:string + chatLastMessageObj:any + chatChain:string + showChatDetails:boolean + math:any + eventDateList:any + eventDateStart:any + eventDateEnd:any + eventDescription:string + eventDuration:number + eventLocation:string + fund:any + surveyDefault:any + survey:any + messageShowActions:[] + lastRead:string + showImageGallery:boolean + + constructor( + public afs:AngularFirestore, + public router:Router, + public UI:UserInterfaceService, + private route:ActivatedRoute, + private storage:AngularFireStorage, + ) { + this.math=Math + this.UI.loading=true + this.reads=[] + this.route.params.subscribe(params=>{ + this.lastRead=null + this.chatChain=params.id + this.messageShowActions=[] + this.messageShowDetails=[] + this.chatLastMessageObj={} + this.previousMessageServerTimestamp={seconds:this.UI.nowSeconds*1000} + this.previousMessageUser='' + this.messageNumberDisplay=15 + this.chatSubject='' + this.eventDescription='' + this.eventDuration=1 + this.eventLocation="" + this.fund={ + description:'add a description', + amountGBPTarget:0, + daysLeft:30 + } + this.surveyDefault={ + question:'Survey question', + durationDays:7, + answers:[ + {answer:'Answer A',votes:[]}, + {answer:'Answer B',votes:[]}, + {answer:'Answer C',votes:[]} + ] + } + this.survey=this.surveyDefault + this.refreshMessages(params.id) + this.refresheventDateList() + this.resetChat() + }) + } + + ngOnInit(){ + this.refreshSearchLists() + } + + showImageGalleryClick(){ + event.stopPropagation() + this.showImageGallery=!this.showImageGallery + this.refreshMessages(this.chatLastMessageObj.chain||this.chatChain) + } + + loadMore(){ + this.UI.loading=true + this.messageNumberDisplay+=15 + this.refreshMessages(this.chatLastMessageObj.chain||this.chatChain) + } + + refresheventDateList(){ + var i + this.eventDateList=[] + for(i=0;i<1010;i++){ + this.eventDateList[i]=(Math.ceil(this.UI.nowSeconds/3600)+i/2)*3600000 + } + } + + refreshMessages(chain) { + if(!this.showImageGallery)this.messages=this.afs.collection('PERRINNMessages',ref=>ref + .where('chain','==',chain) + .orderBy('serverTimestamp','desc') + .limit(this.messageNumberDisplay) + ).snapshotChanges().pipe(map(changes=>{ + this.UI.loading=false + var batch=this.afs.firestore.batch() + var nextMessageRead=true + changes.forEach(c=>{ + if(this.UI.currentUser&&!this.lastRead&&!nextMessageRead&&(c.payload.doc.data()['reads']||[])[this.UI.currentUser])this.lastRead=c.payload.doc.id + nextMessageRead=(c.payload.doc.data()['reads']||[])[this.UI.currentUser] + if(c.payload.doc.data()['lastMessage']){ + if(this.UI.currentUser&&!this.reads.includes(c.payload.doc.id))batch.set(this.afs.firestore.collection('PERRINNTeams').doc(this.UI.currentUser).collection('reads').doc(c.payload.doc.id),{serverTimestamp:firebase.firestore.FieldValue.serverTimestamp()},{merge:true}) + this.reads.push(c.payload.doc.id) + this.chatLastMessageObj=c.payload.doc.data() + this.chatSubject=c.payload.doc.data()['chatSubject'] + this.eventDescription=c.payload.doc.data()['eventDescription'] + this.eventDateStart=c.payload.doc.data()['eventDateStart'] + this.eventDateEnd=c.payload.doc.data()['eventDateEnd'] + this.eventDuration=c.payload.doc.data()['eventDuration'] + this.eventLocation=c.payload.doc.data()['eventLocation'] + this.fund=c.payload.doc.data()['fund']||this.fund + this.survey=((c.payload.doc.data()['survey']||{})['createdTimestamp'])?c.payload.doc.data()['survey']:this.survey + } + }) + batch.commit() + return changes.reverse().map(c=>({ + key:c.payload.doc.id, + payload:c.payload.doc.data() + })) + })) + else this.messages=this.afs.collection('PERRINNMessages',ref=>ref + .where('chain','==',chain) + .orderBy('chatImageTimestamp','desc') + .limit(this.messageNumberDisplay) + ).snapshotChanges().pipe(map(changes=>{ + this.UI.loading=false + var batch=this.afs.firestore.batch() + var nextMessageRead=true + changes.forEach(c=>{ + if(this.UI.currentUser&&!this.lastRead&&!nextMessageRead&&(c.payload.doc.data()['reads']||[])[this.UI.currentUser])this.lastRead=c.payload.doc.id + nextMessageRead=(c.payload.doc.data()['reads']||[])[this.UI.currentUser] + if(c.payload.doc.data()['lastMessage']){ + if(this.UI.currentUser&&!this.reads.includes(c.payload.doc.id))batch.set(this.afs.firestore.collection('PERRINNTeams').doc(this.UI.currentUser).collection('reads').doc(c.payload.doc.id),{serverTimestamp:firebase.firestore.FieldValue.serverTimestamp()},{merge:true}) + this.reads.push(c.payload.doc.id) + this.chatLastMessageObj=c.payload.doc.data() + this.chatSubject=c.payload.doc.data()['chatSubject'] + this.eventDescription=c.payload.doc.data()['eventDescription'] + this.eventDateStart=c.payload.doc.data()['eventDateStart'] + this.eventDuration=c.payload.doc.data()['eventDuration'] + this.eventLocation=c.payload.doc.data()['eventLocation'] + this.fund=c.payload.doc.data()['fund']||this.fund + this.survey=((c.payload.doc.data()['survey']||{})['createdTimestamp'])?c.payload.doc.data()['survey']:this.survey + } + }) + batch.commit() + return changes.map(c=>({ + key:c.payload.doc.id, + payload:c.payload.doc.data() + })) + })) + } + + isMessageNewTimeGroup(messageServerTimestamp:any) { + let isMessageNewTimeGroup:boolean + isMessageNewTimeGroup=Math.abs(messageServerTimestamp.seconds - this.previousMessageServerTimestamp.seconds) > 60 * 60 * 4 + return isMessageNewTimeGroup + } + + isMessageNewUserGroup(user:any,messageServerTimestamp:any) { + let isMessageNewUserGroup:boolean + isMessageNewUserGroup=Math.abs(messageServerTimestamp.seconds - this.previousMessageServerTimestamp.seconds) > 60 * 5 || (user != this.previousMessageUser) + return isMessageNewUserGroup + } + + storeMessageValues(message) { + this.previousMessageUser=message.user + this.previousMessageServerTimestamp=message.serverTimestamp||{seconds:this.UI.nowSeconds*1000} + } + + scrollToBottom(scrollMessageTimestamp:number) { + if (scrollMessageTimestamp != this.scrollMessageTimestamp) { + const element=document.getElementById('chat_window') + element.scrollTop=element.scrollHeight + this.scrollMessageTimestamp=scrollMessageTimestamp + } + } + + saveNewSubject() { + this.UI.createMessage({ + text:'Changing subject to '+this.chatSubject, + chain:this.chatLastMessageObj.chain||this.chatChain, + chatSubject:this.chatSubject, + }) + this.resetChat() + } + + sendCredit(transactionAmount,transactionCode,transactionUser,transactionUserName){ + this.UI.createMessage({ + text:'sending '+this.UI.appSettingsPayment.currencyList[this.UI.currentUserLastMessageObj.userCurrency].symbol+transactionAmount+' to '+transactionUserName+((transactionCode||null)?' using code ':'')+((transactionCode||null)?transactionCode:''), + chain:this.chatLastMessageObj.chain||this.chatChain, + transactionOut:{ + user:transactionUser, + amount:transactionAmount*this.UI.appSettingsPayment.currencyList[this.UI.currentUserLastMessageObj.userCurrency].toCOIN, + code:transactionCode||null + } + }) + this.resetChat() + } + + saveEvent() { + this.UI.createMessage({ + text:'new event', + chain:this.chatLastMessageObj.chain||this.chatChain, + eventDateStart:this.eventDateStart, + eventDateEnd:this.eventDateStart+this.eventDuration*3600000, + eventDescription:this.eventDescription, + eventDuration:this.eventDuration, + eventLocation:this.eventLocation + }) + this.resetChat() + } + + cancelEvent() { + this.UI.createMessage({ + text:'cancelling event', + chain:this.chatLastMessageObj.chain||this.chatChain, + eventDateStart:this.UI.nowSeconds*1000-3600000, + eventDateEnd:this.UI.nowSeconds*1000-3600000 + }) + this.resetChat() + } + + saveFund() { + this.UI.createMessage({ + text:'edited fund', + chain:this.chatLastMessageObj.chain||this.chatChain, + fund:this.fund + }) + this.resetChat() + } + + saveSurvey() { + this.UI.createMessage({ + text:'Survey saved', + chain:this.chatLastMessageObj.chain||this.chatChain, + survey:this.survey + }) + this.resetChat() + } + + voteSurvey(i) { + this.UI.createMessage({ + text:'Survey vote '+this.survey.answers[i].answer, + chain:this.chatLastMessageObj.chain||this.chatChain, + survey:{voteIndexPlusOne:i+1} + }) + this.resetChat() + } + + addMessage() { + this.UI.createMessage({ + text:this.draftMessage, + chain:this.chatLastMessageObj.chain||this.chatChain, + chatImageTimestamp:this.imageTimestamp, + chatImageUrlThumb:this.imageDownloadUrl, + chatImageUrlMedium:this.imageDownloadUrl, + chatImageUrlOriginal:this.imageDownloadUrl + }) + this.resetChat() + } + + addRecipient(user,name) { + this.UI.createMessage({ + text:'adding '+name+' to this chat.', + chain:this.chatLastMessageObj.chain||this.chatChain, + recipientList:[user] + }) + this.resetChat() + } + + removeRecipient(user,name){ + this.UI.createMessage({ + text:'removing '+name+' from this chat.', + chain:this.chatLastMessageObj.chain||this.chatChain, + recipientListToBeRemoved:[user] + }) + this.resetChat() + } + + onImageChange(event:any) { + const image=event.target.files[0] + const uploader=document.getElementById('uploader') as HTMLInputElement + const storageRef=this.storage.ref('images/' + Date.now() + image.name) + const task=storageRef.put(image) + + task.snapshotChanges().subscribe((snapshot)=>{ + document.getElementById('buttonFile').style.visibility='hidden' + document.getElementById('uploader').style.visibility='visible' + + const percentage=(snapshot.bytesTransferred / snapshot.totalBytes) * 100 + uploader.value=percentage.toString() + }, + (err:any)=>{ + document.getElementById('buttonFile').style.visibility='visible' + document.getElementById('uploader').style.visibility='hidden' + uploader.value='0' + }, + ()=>{ + uploader.value='0' + document.getElementById('buttonFile').style.visibility='visible' + document.getElementById('uploader').style.visibility='hidden' + this.imageTimestamp=task.task.snapshot.ref.name.substring(0, 13) + storageRef.getDownloadURL().subscribe(url=>{ + this.imageDownloadUrl=url + event.target.value='' + }) + }) + } + + refreshSearchLists() { + if (this.searchFilter) { + if (this.searchFilter.length > 1) { + this.teams=this.afs.collection('PERRINNMessages', ref=>ref + .where('userChain.nextMessage','==','none') + .where('verified','==',true) + .where('nameLowerCase','>=',this.searchFilter.toLowerCase()) + .where('nameLowerCase','<=',this.searchFilter.toLowerCase()+'\uf8ff') + .orderBy('nameLowerCase') + .limit(20)) + .snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({ + key:c.payload.doc.id, + values:c.payload.doc.data() + })) + })) + } + } else { + this.teams=null + } + } + + resetChat(){ + this.searchFilter=null + this.teams=null + this.draftMessage='' + this.imageTimestamp=null + this.imageDownloadUrl=null + this.showChatDetails=false + this.messageShowDetails=[] + this.messageShowActions=[] + } + +} diff --git a/src/app/directory.component.ts b/src/app/directory/directory.component.html similarity index 53% rename from src/app/directory.component.ts rename to src/app/directory/directory.component.html index f6ec9d02..a8548d06 100644 --- a/src/app/directory.component.ts +++ b/src/app/directory/directory.component.html @@ -1,89 +1,41 @@ -import { Component } from '@angular/core'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; -import { Router } from '@angular/router'; -import { UserInterfaceService } from './userInterface.service'; -import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore'; -import { AngularFireAuth } from '@angular/fire/compat/auth' -import firebase from 'firebase/compat/app'; - -@Component({ - selector:'directory', - template:` -
-
- {{UI.PERRINNAdminLastMessageObj?.statistics?.emailsContributorsAuth?.length}} members own {{UI.formatSharesToPRNCurrency(null,UI.PERRINNAdminLastMessageObj?.statistics?.wallet?.shareBalance)}}. -
-
-
-
-
    -
  • -
    - -
    -
    {{message.values?.name}}
    - link -
    -
    - {{message.values?.userPresentation}} - Level {{message.values?.contract?.levelTimeAdjusted|number:'1.1-1'}}. -
    -
    -
    {{UI.formatSharesToPRNCurrency(null,message.values?.wallet?.shareBalance||0)}}
    -
    {{((message.values?.wallet?.shareBalance||0)/(UI.PERRINNAdminLastMessageObj?.statistics?.wallet?.shareBalance))|percent:'1.1-1'}}
    -
    -
    -
    -
  • -
-
-
    - -
  • - -
  • -
-
-
    -
  • - {{message.values?.name}} - {{UI.formatSharesToPRNCurrency(null,message.values?.wallet?.shareBalance||0)}}   -
  • -
-
-
- `, -}) - -export class DirectoryComponent { - - messages:Observable; - - constructor( - public afAuth:AngularFireAuth, - public afs:AngularFirestore, - public router:Router, - public UI:UserInterfaceService - ){} - - ngOnInit() { - this.refreshMembersList() - } - - refreshMembersList() { - this.messages = this.afs.collection('PERRINNMessages', ref => ref - .where('userChain.nextMessage','==','none') - .where('verified','==',true) - .where('wallet.shareBalance','>',0) - .orderBy('wallet.shareBalance',"desc") - .limit(100)) - .snapshotChanges().pipe(map(changes => { - return changes.map(c => ({ - key:c.payload.doc.id, - values:c.payload.doc.data(), - })); - })); - } - -} +
+
+ {{UI.PERRINNAdminLastMessageObj?.statistics?.emailsContributorsAuth?.length}} members own {{UI.formatSharesToPRNCurrency(null,UI.PERRINNAdminLastMessageObj?.statistics?.wallet?.balance)}}. +
+
+
+
+
    +
  • +
    + +
    +
    {{message.values?.name}}
    + link + {{message.values?.userPresentation}} + Level {{message.values?.contract?.levelTimeAdjusted|number:'1.1-1'}}. +
    +
    +
    {{UI.formatSharesToPRNCurrency(null,message.values?.wallet?.balance||0)}}
    +
    {{((message.values?.wallet?.balance||0)/(UI.PERRINNAdminLastMessageObj?.statistics?.wallet?.balance))|percent:'1.1-1'}}
    +
    +
    +
    +
  • +
+
+
    + +
  • + +
  • +
+
+
    +
  • + {{message.values?.name}} + {{UI.formatSharesToPRNCurrency(null,message.values?.wallet?.balance||0)}}   +
  • +
+
+
\ No newline at end of file diff --git a/src/app/directory/directory.component.ts b/src/app/directory/directory.component.ts new file mode 100644 index 00000000..f4f4688c --- /dev/null +++ b/src/app/directory/directory.component.ts @@ -0,0 +1,45 @@ +import { Component } from '@angular/core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { Router } from '@angular/router'; +import { UserInterfaceService } from './../userInterface.service'; +import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore'; +import { AngularFireAuth } from '@angular/fire/compat/auth' +import firebase from 'firebase/compat/app'; + +@Component({ + selector:'directory', + templateUrl:'./directory.component.html', +}) + +export class DirectoryComponent { + + messages:Observable; + + constructor( + public afAuth:AngularFireAuth, + public afs:AngularFirestore, + public router:Router, + public UI:UserInterfaceService + ){} + + ngOnInit() { + this.refreshMembersList() + } + + refreshMembersList() { + this.messages = this.afs.collection('PERRINNMessages', ref => ref + .where('userChain.nextMessage','==','none') + .where('verified','==',true) + .where('wallet.balance','>',0) + .orderBy('wallet.balance',"desc") + .limit(200)) + .snapshotChanges().pipe(map(changes => { + return changes.map(c => ({ + key:c.payload.doc.id, + values:c.payload.doc.data(), + })); + })); + } + +} diff --git a/src/app/login/login.component.html b/src/app/login/login.component.html new file mode 100644 index 00000000..c82ef2cd --- /dev/null +++ b/src/app/login/login.component.html @@ -0,0 +1,24 @@ +
+
+
+
+
New member
+
Existing member
+
+ + +
+
+
Login
+
Forgot password?
+
+
+ + +
Register
+
+
{{messageUser}}
+
+
+
+
\ No newline at end of file diff --git a/src/app/login.component.ts b/src/app/login/login.component.ts similarity index 67% rename from src/app/login.component.ts rename to src/app/login/login.component.ts index aaae95b4..209ad01f 100644 --- a/src/app/login.component.ts +++ b/src/app/login/login.component.ts @@ -2,37 +2,12 @@ import { Component } from '@angular/core'; import { Router } from '@angular/router'; import firebase from 'firebase/compat/app'; import { AngularFireAuth } from '@angular/fire/compat/auth'; -import { UserInterfaceService } from './userInterface.service'; +import { UserInterfaceService } from './../userInterface.service'; import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore'; @Component({ selector:'login', - template:` -
-
-
-
-
New member
-
Existing member
-
- - -
-
-
Login
-
Forgot password?
-
-
- - -
Register
-
-
{{messageUser}}
-
-
-
-
- `, + templateUrl:'./login.component.html', }) export class LoginComponent { diff --git a/src/app/profile.component.ts b/src/app/profile/profile.component.html similarity index 65% rename from src/app/profile.component.ts rename to src/app/profile/profile.component.html index b54fa61f..2bf7d030 100644 --- a/src/app/profile.component.ts +++ b/src/app/profile/profile.component.html @@ -1,521 +1,225 @@ -import { Component } from '@angular/core' -import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore' -import { Observable } from 'rxjs' -import { map } from 'rxjs/operators' -import { Router, ActivatedRoute } from '@angular/router' -import { UserInterfaceService } from './userInterface.service' -import { AngularFireAuth } from '@angular/fire/compat/auth' -import firebase from 'firebase/compat/app' - -@Component({ - selector:'profile', - template:` -
-
- -
-
-
-
- -
-
-
-
- {{focusUserLastMessageObj?.name}} - {{UI.formatSharesToPRNCurrency(null,focusUserLastMessageObj?.wallet?.shareBalance||0)}} - link -
- {{focusUserLastMessageObj?.userPresentation}} - Level {{focusUserLastMessageObj?.contract?.levelTimeAdjusted|number:'1.1-1'}} - Waiting for contract signature (Level {{focusUserLastMessageObj?.contract?.level|number:'1.1-1'}}) -
Sign contract
-
-
settings
-
-
Created {{focusUserLastMessageObj?.createdTimestamp|date:'MMMM yyyy'}}, {{focusUserLastMessageObj?.userChain?.index}} Messages, Verified {{((UI.nowSeconds-focusUserLastMessageObj?.verifiedTimestamp?.seconds)/3600/24)|number:'1.2-2'}} days ago
-
-
inbox
-
30 days
-
24 months
-
chain
-
20 year forecast
-
-
New message to {{focusUserLastMessageObj?.name}}
-
-
-
-
- link -
filter_list
-
Clear {{UI.tagFilters.length}} filter{{UI.tagFilters.length>1?'s':''}}
-
    -
  • - {{message.payload.doc.data()?.tag}} -
  • -
-
-
-
-
    -
  • -
    -
    - Join -
    - event -
    -
    -
    - settings - {{message.payload.doc.data()?.chatSubject}} -
    -
    -
    in {{UI.formatSecondsToDhm2(message.payload.doc.data()?.eventDateStart/1000-UI.nowSeconds)}}
    -
    Now
    - {{message.payload.doc.data()?.eventDescription}} - {{message.payload.doc.data()?.eventDateStart|date:'EEEE d MMM h:mm a'}} ({{message.payload.doc.data()?.eventDuration}}h) -
    -
    -
    -
    -
    -
  • -
-
    -
  • -
    -
    -
    - crowdsource -
    -
    -
    - settings - {{message.payload.doc.data()?.chatSubject}} -
    -
    -
    -
    -
    {{(message.payload.doc.data()?.fund?.amountGBPRaised/message.payload.doc.data()?.fund?.amountGBPTarget)|percent:'1.0-0'}}
    -
    {{message.payload.doc.data()?.fund?.daysLeft|number:'1.0-0'}} days left
    -
    {{message.payload.doc.data()?.fund?.description}},
    -
    target: {{UI.formatSharesToCurrency(null,message.payload.doc.data()?.fund?.amountGBPTarget*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}} /
    -
    raised: {{UI.formatSharesToCurrency(null,message.payload.doc.data()?.fund?.amountGBPRaised*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}}
    -
    -
    -
    -
    -
    -
  • -
-
    -
  • -
    -
    -
    - poll -
    -
    -
    - settings - {{message.payload.doc.data()?.chatSubject}} -
    -
    -
    {{UI.formatSecondsToDhm2(message.payload.doc.data()?.survey.expiryTimestamp/1000-UI.nowSeconds)}} left
    -
    {{message.payload.doc.data()?.survey.question}}
    - {{answer.answer}} ({{(answer.votes.length/message.payload.doc.data()?.survey.totalVotes)|percent:'1.0-0'}}) - {{message.payload.doc.data()?.survey.totalVotes}} vote{{message.payload.doc.data()?.survey.totalVotes>1?'s':''}} -
    Vote now
    -
    -
    -
    -
    -
    -
  • -
-
    -
  • -
    - -
    -
  • -
    -
-
    -
  • -
    -
    - - -
    -
    -
    - settings - {{message.payload.doc.data()?.chatSubject}}{{message.payload.doc.data()?.recipientList.length>1?' ('+message.payload.doc.data()?.recipientList.length+')':''}} -
    -
    - {{message.payload.doc.data()?.recipients[UI.currentUser]?.unreadMessages}} -
    -
    - {{message.payload.doc.data()?.recipients[UI.currentUser]?.unreadMessages}} -
    -
    {{UI.formatSecondsToDhm1(math.max(0,(UI.nowSeconds-message.payload.doc.data()?.serverTimestamp?.seconds)))}}
    -
    - {{message.payload.doc.data()?.name}}:  - aspect_ratio - {{message.payload.doc.data()?.text}} -
    -
    -
    -
    -
    -
    -
    Date
    -
    Days
    -
    Messages
    -
    Balance
    -
    Change
    -
    Purchase
    -
    Transaction
    -
    Interest
    -
    Contract
    -
    -
    -
    {{(message.payload.doc.data()?.verifiedTimestamp?.seconds*1000)|date:'d MMM'}}
    -
    {{first?'':(message.payload.doc.data()?.verifiedTimestamp?.seconds-previousTimestamp.seconds)/3600/24|number:'1.2-2'}}
    -
    {{first?'':(message.payload.doc.data()?.userChain?.index-previousIndex)}}
    -
    {{UI.formatSharesToCurrency(null,message.payload.doc.data()?.wallet?.shareBalance)}}
    -
    {{first?'':UI.formatSharesToCurrency(null,message.payload.doc.data()?.wallet?.shareBalance-previousBalance)}}
    -
    {{first?'':UI.formatSharesToCurrency(null,(message.payload.doc.data()?.purchaseCOIN?.amountCummulate||0)-previousPurchaseCOINAmountCummulate)|blankIfZero}}
    -
    {{first?'':UI.formatSharesToCurrency(null,(message.payload.doc.data()?.transactionIn?.amountCummulate||0)-(message.payload.doc.data()?.transactionOut?.amountCummulate||0)-previousAmountTransactionCummulate)|blankIfZero}}
    -
    {{first?'':UI.formatSharesToCurrency(null,(message.payload.doc.data()?.interest?.amountCummulate||0)-previousAmountInterestCummulate)|blankIfZero}}
    -
    {{first?'':UI.formatSharesToCurrency(null,(message.payload.doc.data()?.contract?.amountCummulate||0)-previousContractAmountCummulate)|blankIfZero}}
    -
    - {{storeMessageValues(message.payload.doc.data())}} -
    -
  • -
-
-
Year
-
Growth
-
Balance
-
Multiple
-
-
    -
  • -
    {{number}}
    -
    {{UI.appSettingsCosts?.interestRateYear | percent : "0.0"}}
    -
    - {{UI.formatSharesToPRNCurrency(null,focusUserLastMessageObj?.wallet?.shareBalance*math.exp(UI.appSettingsCosts?.interestRateYear*number))}} -
    -
    {{math.exp(UI.appSettingsCosts?.interestRateYear*number)|number:'1.1-1'}}X
    -
  • -
-
-
-
-
-
-
-
-
Load more
-
-
-
- `, -}) -export class ProfileComponent { - messages:Observable - comingEvents:Observable - currentFunds:Observable - currentSurveys:Observable - latestImages:Observable - tags:Observable - scrollTeam:string - focusUserLastMessageObj:any - scope:string - mode:string - previousBalance:string - previousTimestamp:string - previousIndex:string - previousPurchaseCOINAmountCummulate:number - previousContractAmountCummulate:number - previousAmountInterestCummulate:number - previousAmountTransactionCummulate:number - math:any - messageNumberDisplay:number - showTags:boolean - - constructor( - public afAuth:AngularFireAuth, - public afs:AngularFirestore, - public router:Router, - public UI:UserInterfaceService, - private route:ActivatedRoute - ) { - this.showTags=false - this.math=Math - this.messageNumberDisplay=30 - this.scope='' - this.mode='inbox' - this.scrollTeam='' - this.route.params.subscribe(params => { - this.scope=params.id - afs.collection('PERRINNMessages',ref=>ref - .where('user','==',this.scope) - .where('verified','==',true) - .orderBy('serverTimestamp','desc').limit(1) - ).valueChanges().subscribe(snapshot=>{ - this.focusUserLastMessageObj=snapshot[0] - }) - this.tags=this.afs.collection('PERRINNMessages',ref=>ref - .where('lastMessage','==',true) - .where('tagLastMessage','==',true) - .where('verified','==',true) - .orderBy('tag','asc') - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.refreshMessages() - }) - } - - ngOnInit() { - } - - refreshMessages(){ - this.UI.loading=true - if(this.scope=='all'){ - if(this.UI.tagFilters.length==0){ - this.comingEvents=this.afs.collection('PERRINNMessages',ref=>ref - .where('lastMessage','==',true) - .where('verified','==',true) - .orderBy('eventDateEnd') - .where('eventDateEnd','>',this.UI.nowSeconds*1000) - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.currentFunds=this.afs.collection('PERRINNMessages',ref=>ref - .where('lastMessage','==',true) - .where('verified','==',true) - .where('fund.active','==',true) - .orderBy('fund.daysLeft','asc') - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.currentSurveys=this.afs.collection('PERRINNMessages',ref=>ref - .where('lastMessage','==',true) - .where('verified','==',true) - .orderBy('survey.expiryTimestamp') - .where('survey.expiryTimestamp','>=',this.UI.nowSeconds*1000) - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.latestImages=this.afs.collection('PERRINNMessages',ref=>ref - .where('verified','==',true) - .orderBy('chatImageTimestamp','desc') - .limit(5) - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.messages=this.afs.collection('PERRINNMessages',ref=>ref - .where('lastMessage','==',true) - .where('verified','==',true) - .orderBy('serverTimestamp','desc') - .limit(this.messageNumberDisplay) - ).snapshotChanges().pipe(map(changes=>{ - this.UI.loading=false - return changes.map(c=>({payload:c.payload})) - })) - } - else{ - this.comingEvents=this.afs.collection('PERRINNMessages',ref=>ref - .where('lastMessage','==',true) - .where('tag','in',this.UI.tagFilters) - .where('verified','==',true) - .orderBy('eventDateEnd') - .where('eventDateEnd','>',this.UI.nowSeconds*1000) - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.currentFunds=this.afs.collection('PERRINNMessages',ref=>ref - .where('lastMessage','==',true) - .where('tag','in',this.UI.tagFilters) - .where('verified','==',true) - .where('fund.active','==',true) - .orderBy('fund.daysLeft','asc') - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.currentSurveys=this.afs.collection('PERRINNMessages',ref=>ref - .where('lastMessage','==',true) - .where('tag','in',this.UI.tagFilters) - .where('verified','==',true) - .orderBy('survey.expiryTimestamp') - .where('survey.expiryTimestamp','>=',this.UI.nowSeconds*1000) - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.latestImages=this.afs.collection('PERRINNMessages',ref=>ref - .where('verified','==',true) - .where('tag','in',this.UI.tagFilters) - .orderBy('chatImageTimestamp','desc') - .limit(5) - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.messages=this.afs.collection('PERRINNMessages',ref=>ref - .where('lastMessage','==',true) - .where('tag','in',this.UI.tagFilters) - .where('verified','==',true) - .orderBy('serverTimestamp','desc') - .limit(this.messageNumberDisplay) - ).snapshotChanges().pipe(map(changes=>{ - this.UI.loading=false - return changes.map(c=>({payload:c.payload})) - })) - } - } - else if(this.mode=='30days'){ - this.messages=this.afs.collection('PERRINNMessages',ref=>ref - .where('user','==',this.scope) - .where('verified','==',true) - .where('userChain.newDay','==',true) - .orderBy('serverTimestamp','desc') - .limit(this.messageNumberDisplay) - ).snapshotChanges().pipe(map(changes=>{ - this.UI.loading=false - return changes.reverse().map(c=>({payload:c.payload})) - })) - } - else if(this.mode=='24months'){ - this.messages=this.afs.collection('PERRINNMessages',ref=>ref - .where('user','==',this.scope) - .where('verified','==',true) - .where('userChain.newMonth','==',true) - .orderBy('serverTimestamp','desc') - .limit(24) - ).snapshotChanges().pipe(map(changes=>{ - this.UI.loading=false - return changes.reverse().map(c=>({payload:c.payload})) - })) - } - else if(this.mode=='chain'){ - this.messages=this.afs.collection('PERRINNMessages',ref=>ref - .where('user','==',this.scope) - .where('verified','==',true) - .orderBy('serverTimestamp','desc') - .limit(this.messageNumberDisplay) - ).snapshotChanges().pipe(map(changes=>{ - this.UI.loading=false - return changes.reverse().map(c=>({payload:c.payload})) - })) - } - else{ - this.comingEvents=this.afs.collection('PERRINNMessages',ref=>ref - .where('recipientList','array-contains-any',[this.scope,'xCxYTM0AD7aj5SKZ27iFaqJaXps1']) - .where('lastMessage','==',true) - .where('verified','==',true) - .orderBy('eventDateEnd') - .where('eventDateEnd','>',this.UI.nowSeconds*1000) - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.currentFunds=this.afs.collection('PERRINNMessages',ref=>ref - .where('recipientList','array-contains-any',[this.scope,'xCxYTM0AD7aj5SKZ27iFaqJaXps1']) - .where('lastMessage','==',true) - .where('verified','==',true) - .where('fund.active','==',true) - .orderBy('fund.daysLeft','asc') - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.currentSurveys=this.afs.collection('PERRINNMessages',ref=>ref - .where('recipientList','array-contains-any',[this.scope,'xCxYTM0AD7aj5SKZ27iFaqJaXps1']) - .where('lastMessage','==',true) - .where('verified','==',true) - .orderBy('survey.expiryTimestamp') - .where('survey.expiryTimestamp','>=',this.UI.nowSeconds*1000) - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.latestImages=this.afs.collection('PERRINNMessages',ref=>ref - .where('recipientList','array-contains-any',[this.scope,'xCxYTM0AD7aj5SKZ27iFaqJaXps1']) - .where('verified','==',true) - .orderBy('chatImageTimestamp','desc') - .limit(5) - ).snapshotChanges().pipe(map(changes=>{ - return changes.map(c=>({payload:c.payload})) - })) - this.messages=this.afs.collection('PERRINNMessages',ref=>ref - .where('recipientList','array-contains-any',[this.scope,'xCxYTM0AD7aj5SKZ27iFaqJaXps1']) - .where('verified','==',true) - .where('lastMessage','==',true) - .orderBy('serverTimestamp','desc') - .limit(this.messageNumberDisplay) - ).snapshotChanges().pipe(map(changes=>{ - this.UI.loading=false - return changes.map(c=>({payload:c.payload})) - })) - } - } - - readFlagClick(messageId,readFlag){ - event.stopPropagation() - if(readFlag)return this.afs.firestore.collection('PERRINNTeams').doc(this.UI.currentUser).collection('reads').doc(messageId).delete() - return this.afs.firestore.collection('PERRINNTeams').doc(this.UI.currentUser).collection('reads').doc(messageId).set({ - serverTimestamp:firebase.firestore.FieldValue.serverTimestamp() - }) - } - - newMessageToUser() { - let ID=this.UI.newId() - this.UI.createMessage({ - text:'Starting a new chat.', - chain:ID, - recipientList:[this.focusUserLastMessageObj.user] - }) - this.router.navigate(['chat',ID]) - } - - storeMessageValues(message) { - this.previousBalance=((message.wallet||{}).shareBalance)||0 - this.previousTimestamp=message.verifiedTimestamp - this.previousIndex=message.userChain.index - this.previousPurchaseCOINAmountCummulate=(message.purchaseCOIN||{}).amountCummulate||0 - this.previousContractAmountCummulate=(message.contract||{}).amountCummulate||0 - this.previousAmountInterestCummulate=(message.interest||{}).amountCummulate||0 - this.previousAmountTransactionCummulate=((message.transactionIn||{}).amountCummulate||0)-((message.transactionOut||{}).amountCummulate||0) - } - - signContract(){ - this.UI.createMessage({ - chain:this.focusUserLastMessageObj.user, - text:'Contract signature for level '+((this.focusUserLastMessageObj.contract||{}).level||0), - contractSignature:{ - user:this.focusUserLastMessageObj.user, - contract:this.focusUserLastMessageObj.contract||{} - } - }) - this.router.navigate(['chat',this.focusUserLastMessageObj.user]) - } - - loadMore() { - this.messageNumberDisplay+=15 - this.refreshMessages() - } - -} +
+
+ +
+
+
+
+ +
+
+
+
+ {{focusUserLastMessageObj?.name}} + {{UI.formatSharesToPRNCurrency(null,focusUserLastMessageObj?.wallet?.balance||0)}} + link +
+ {{focusUserLastMessageObj?.userPresentation}} + Level {{focusUserLastMessageObj?.contract?.levelTimeAdjusted|number:'1.1-1'}} + Waiting for contract signature (Level {{focusUserLastMessageObj?.contract?.level|number:'1.1-1'}}) +
Sign contract
+
+
settings
+
+
Created {{focusUserLastMessageObj?.createdTimestamp|date:'MMMM yyyy'}}, {{focusUserLastMessageObj?.userChain?.index}} Messages, Verified {{((UI.nowSeconds-focusUserLastMessageObj?.verifiedTimestamp?.seconds)/3600/24)|number:'1.2-2'}} days ago
+
+
inbox
+
30 days
+
24 months
+
chain
+
20 year forecast
+
+
New message to {{focusUserLastMessageObj?.name}}
+
+
+
+
+ link +
filter_list
+
Clear {{UI.tagFilters.length}} filter{{UI.tagFilters.length>1?'s':''}}
+
    +
  • + {{message.payload.doc.data()?.tag}} +
  • +
+
+
+
+
    +
  • +
    +
    + Join +
    + event +
    +
    +
    + settings + {{message.payload.doc.data()?.chatSubject}} +
    +
    +
    in {{UI.formatSecondsToDhm2(message.payload.doc.data()?.eventDateStart/1000-UI.nowSeconds)}}
    +
    Now
    + {{message.payload.doc.data()?.eventDescription}} + {{message.payload.doc.data()?.eventDateStart|date:'EEEE d MMM h:mm a'}} ({{message.payload.doc.data()?.eventDuration}}h) +
    +
    +
    +
    +
    +
  • +
+
    +
  • +
    +
    +
    + crowdsource +
    +
    +
    + settings + {{message.payload.doc.data()?.chatSubject}} +
    +
    +
    +
    +
    {{(message.payload.doc.data()?.fund?.amountGBPRaised/message.payload.doc.data()?.fund?.amountGBPTarget)|percent:'1.0-0'}}
    +
    {{message.payload.doc.data()?.fund?.daysLeft|number:'1.0-0'}} days left
    +
    {{message.payload.doc.data()?.fund?.description}},
    +
    target: {{UI.formatSharesToCurrency(null,message.payload.doc.data()?.fund?.amountGBPTarget*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}} /
    +
    raised: {{UI.formatSharesToCurrency(null,message.payload.doc.data()?.fund?.amountGBPRaised*UI.appSettingsPayment.currencyList["gbp"].toCOIN)}}
    +
    +
    +
    +
    +
    +
  • +
+
    +
  • +
    +
    +
    + poll +
    +
    +
    + settings + {{message.payload.doc.data()?.chatSubject}} +
    +
    +
    {{UI.formatSecondsToDhm2(message.payload.doc.data()?.survey.expiryTimestamp/1000-UI.nowSeconds)}} left
    +
    {{message.payload.doc.data()?.survey.question}}
    + {{answer.answer}} ({{(answer.votes.length/message.payload.doc.data()?.survey.totalVotes)|percent:'1.0-0'}}) + {{message.payload.doc.data()?.survey.totalVotes}} vote{{message.payload.doc.data()?.survey.totalVotes>1?'s':''}} +
    Vote now
    +
    +
    +
    +
    +
    +
  • +
+
    +
  • +
    + +
    +
  • +
    +
+
    +
  • +
    +
    + + +
    +
    +
    + settings + {{message.payload.doc.data()?.chatSubject}}{{message.payload.doc.data()?.recipientList.length>1?' ('+message.payload.doc.data()?.recipientList.length+')':''}} +
    +
    + {{message.payload.doc.data()?.recipients[UI.currentUser]?.unreadMessages}} +
    +
    + {{message.payload.doc.data()?.recipients[UI.currentUser]?.unreadMessages}} +
    +
    {{UI.formatSecondsToDhm1(math.max(0,(UI.nowSeconds-message.payload.doc.data()?.serverTimestamp?.seconds)))}}
    +
    + {{message.payload.doc.data()?.name}}:  + aspect_ratio + {{message.payload.doc.data()?.text}} +
    +
    +
    +
    +
    +
    +
    Date
    +
    Days
    +
    Messages
    +
    Balance
    +
    Change
    +
    Purchase
    +
    Transaction
    +
    Interest
    +
    Contract
    +
    +
    +
    {{(message.payload.doc.data()?.verifiedTimestamp?.seconds*1000)|date:'d MMM'}}
    +
    {{first?'':(message.payload.doc.data()?.verifiedTimestamp?.seconds-previousTimestamp.seconds)/3600/24|number:'1.2-2'}}
    +
    {{first?'':(message.payload.doc.data()?.userChain?.index-previousIndex)}}
    +
    {{UI.formatSharesToCurrency(null,message.payload.doc.data()?.wallet?.balance)}}
    +
    {{first?'':UI.formatSharesToCurrency(null,message.payload.doc.data()?.wallet?.balance-previousBalance)}}
    +
    {{first?'':UI.formatSharesToCurrency(null,(message.payload.doc.data()?.purchaseCOIN?.amountCummulate||0)-previousPurchaseCOINAmountCummulate)|blankIfZero}}
    +
    {{first?'':UI.formatSharesToCurrency(null,(message.payload.doc.data()?.transactionIn?.amountCummulate||0)-(message.payload.doc.data()?.transactionOut?.amountCummulate||0)-previousAmountTransactionCummulate)|blankIfZero}}
    +
    {{first?'':UI.formatSharesToCurrency(null,(message.payload.doc.data()?.interest?.amountCummulate||0)-previousAmountInterestCummulate)|blankIfZero}}
    +
    {{first?'':UI.formatSharesToCurrency(null,(message.payload.doc.data()?.contract?.amountCummulate||0)-previousContractAmountCummulate)|blankIfZero}}
    +
    + {{storeMessageValues(message.payload.doc.data())}} +
    +
  • +
+
+
Year
+
Growth
+
Balance
+
Multiple
+
+
    +
  • +
    {{number}}
    +
    {{UI.appSettingsCosts?.interestRateYear | percent : "0.0"}}
    +
    + {{UI.formatSharesToPRNCurrency(null,focusUserLastMessageObj?.wallet?.balance*math.exp(UI.appSettingsCosts?.interestRateYear*number))}} +
    +
    {{math.exp(UI.appSettingsCosts?.interestRateYear*number)|number:'1.1-1'}}X
    +
  • +
+
+
+
+
+
+
+
+
Load more
+
+
+
\ No newline at end of file diff --git a/src/app/profile/profile.component.ts b/src/app/profile/profile.component.ts new file mode 100644 index 00000000..2881af88 --- /dev/null +++ b/src/app/profile/profile.component.ts @@ -0,0 +1,296 @@ +import { Component } from '@angular/core' +import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore' +import { Observable } from 'rxjs' +import { map } from 'rxjs/operators' +import { Router, ActivatedRoute } from '@angular/router' +import { UserInterfaceService } from './../userInterface.service' +import { AngularFireAuth } from '@angular/fire/compat/auth' +import firebase from 'firebase/compat/app' + +@Component({ + selector:'profile', + templateUrl:'./profile.component.html', +}) + +export class ProfileComponent { + messages:Observable + comingEvents:Observable + currentFunds:Observable + currentSurveys:Observable + latestImages:Observable + tags:Observable + scrollTeam:string + focusUserLastMessageObj:any + scope:string + mode:string + previousBalance:string + previousTimestamp:string + previousIndex:string + previousPurchaseCOINAmountCummulate:number + previousContractAmountCummulate:number + previousAmountInterestCummulate:number + previousAmountTransactionCummulate:number + math:any + messageNumberDisplay:number + showTags:boolean + + constructor( + public afAuth:AngularFireAuth, + public afs:AngularFirestore, + public router:Router, + public UI:UserInterfaceService, + private route:ActivatedRoute + ) { + this.showTags=false + this.math=Math + this.messageNumberDisplay=30 + this.scope='' + this.mode='inbox' + this.scrollTeam='' + this.route.params.subscribe(params => { + this.scope=params.id + afs.collection('PERRINNMessages',ref=>ref + .where('user','==',this.scope) + .where('verified','==',true) + .orderBy('serverTimestamp','desc').limit(1) + ).valueChanges().subscribe(snapshot=>{ + this.focusUserLastMessageObj=snapshot[0] + }) + this.tags=this.afs.collection('PERRINNMessages',ref=>ref + .where('lastMessage','==',true) + .where('tagLastMessage','==',true) + .where('verified','==',true) + .orderBy('tag','asc') + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.refreshMessages() + }) + } + + ngOnInit() { + } + + refreshMessages(){ + this.UI.loading=true + if(this.scope=='all'){ + if(this.UI.tagFilters.length==0){ + this.comingEvents=this.afs.collection('PERRINNMessages',ref=>ref + .where('lastMessage','==',true) + .where('verified','==',true) + .orderBy('eventDateEnd') + .where('eventDateEnd','>',this.UI.nowSeconds*1000) + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.currentFunds=this.afs.collection('PERRINNMessages',ref=>ref + .where('lastMessage','==',true) + .where('verified','==',true) + .where('fund.active','==',true) + .orderBy('fund.daysLeft','asc') + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.currentSurveys=this.afs.collection('PERRINNMessages',ref=>ref + .where('lastMessage','==',true) + .where('verified','==',true) + .orderBy('survey.expiryTimestamp') + .where('survey.expiryTimestamp','>=',this.UI.nowSeconds*1000) + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.latestImages=this.afs.collection('PERRINNMessages',ref=>ref + .where('verified','==',true) + .orderBy('chatImageTimestamp','desc') + .limit(5) + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.messages=this.afs.collection('PERRINNMessages',ref=>ref + .where('lastMessage','==',true) + .where('verified','==',true) + .orderBy('serverTimestamp','desc') + .limit(this.messageNumberDisplay) + ).snapshotChanges().pipe(map(changes=>{ + this.UI.loading=false + return changes.map(c=>({payload:c.payload})) + })) + } + else{ + this.comingEvents=this.afs.collection('PERRINNMessages',ref=>ref + .where('lastMessage','==',true) + .where('tag','in',this.UI.tagFilters) + .where('verified','==',true) + .orderBy('eventDateEnd') + .where('eventDateEnd','>',this.UI.nowSeconds*1000) + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.currentFunds=this.afs.collection('PERRINNMessages',ref=>ref + .where('lastMessage','==',true) + .where('tag','in',this.UI.tagFilters) + .where('verified','==',true) + .where('fund.active','==',true) + .orderBy('fund.daysLeft','asc') + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.currentSurveys=this.afs.collection('PERRINNMessages',ref=>ref + .where('lastMessage','==',true) + .where('tag','in',this.UI.tagFilters) + .where('verified','==',true) + .orderBy('survey.expiryTimestamp') + .where('survey.expiryTimestamp','>=',this.UI.nowSeconds*1000) + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.latestImages=this.afs.collection('PERRINNMessages',ref=>ref + .where('verified','==',true) + .where('tag','in',this.UI.tagFilters) + .orderBy('chatImageTimestamp','desc') + .limit(5) + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.messages=this.afs.collection('PERRINNMessages',ref=>ref + .where('lastMessage','==',true) + .where('tag','in',this.UI.tagFilters) + .where('verified','==',true) + .orderBy('serverTimestamp','desc') + .limit(this.messageNumberDisplay) + ).snapshotChanges().pipe(map(changes=>{ + this.UI.loading=false + return changes.map(c=>({payload:c.payload})) + })) + } + } + else if(this.mode=='30days'){ + this.messages=this.afs.collection('PERRINNMessages',ref=>ref + .where('user','==',this.scope) + .where('verified','==',true) + .where('userChain.newDay','==',true) + .orderBy('serverTimestamp','desc') + .limit(this.messageNumberDisplay) + ).snapshotChanges().pipe(map(changes=>{ + this.UI.loading=false + return changes.reverse().map(c=>({payload:c.payload})) + })) + } + else if(this.mode=='24months'){ + this.messages=this.afs.collection('PERRINNMessages',ref=>ref + .where('user','==',this.scope) + .where('verified','==',true) + .where('userChain.newMonth','==',true) + .orderBy('serverTimestamp','desc') + .limit(24) + ).snapshotChanges().pipe(map(changes=>{ + this.UI.loading=false + return changes.reverse().map(c=>({payload:c.payload})) + })) + } + else if(this.mode=='chain'){ + this.messages=this.afs.collection('PERRINNMessages',ref=>ref + .where('user','==',this.scope) + .where('verified','==',true) + .orderBy('serverTimestamp','desc') + .limit(this.messageNumberDisplay) + ).snapshotChanges().pipe(map(changes=>{ + this.UI.loading=false + return changes.reverse().map(c=>({payload:c.payload})) + })) + } + else{ + this.comingEvents=this.afs.collection('PERRINNMessages',ref=>ref + .where('recipientList','array-contains-any',[this.scope]) + .where('lastMessage','==',true) + .where('verified','==',true) + .orderBy('eventDateEnd') + .where('eventDateEnd','>',this.UI.nowSeconds*1000) + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.currentFunds=this.afs.collection('PERRINNMessages',ref=>ref + .where('recipientList','array-contains-any',[this.scope]) + .where('lastMessage','==',true) + .where('verified','==',true) + .where('fund.active','==',true) + .orderBy('fund.daysLeft','asc') + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.currentSurveys=this.afs.collection('PERRINNMessages',ref=>ref + .where('recipientList','array-contains-any',[this.scope]) + .where('lastMessage','==',true) + .where('verified','==',true) + .orderBy('survey.expiryTimestamp') + .where('survey.expiryTimestamp','>=',this.UI.nowSeconds*1000) + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.latestImages=this.afs.collection('PERRINNMessages',ref=>ref + .where('recipientList','array-contains-any',[this.scope]) + .where('verified','==',true) + .orderBy('chatImageTimestamp','desc') + .limit(5) + ).snapshotChanges().pipe(map(changes=>{ + return changes.map(c=>({payload:c.payload})) + })) + this.messages=this.afs.collection('PERRINNMessages',ref=>ref + .where('recipientList','array-contains-any',[this.scope]) + .where('verified','==',true) + .where('lastMessage','==',true) + .orderBy('serverTimestamp','desc') + .limit(this.messageNumberDisplay) + ).snapshotChanges().pipe(map(changes=>{ + this.UI.loading=false + return changes.map(c=>({payload:c.payload})) + })) + } + } + + readFlagClick(messageId,readFlag){ + event.stopPropagation() + if(readFlag)return this.afs.firestore.collection('PERRINNTeams').doc(this.UI.currentUser).collection('reads').doc(messageId).delete() + return this.afs.firestore.collection('PERRINNTeams').doc(this.UI.currentUser).collection('reads').doc(messageId).set({ + serverTimestamp:firebase.firestore.FieldValue.serverTimestamp() + }) + } + + newMessageToUser() { + let ID=this.UI.newId() + this.UI.createMessage({ + text:'Starting a new chat.', + chain:ID, + recipientList:[this.focusUserLastMessageObj.user] + }) + this.router.navigate(['chat',ID]) + } + + storeMessageValues(message) { + this.previousBalance=((message.wallet||{}).balance)||0 + this.previousTimestamp=message.verifiedTimestamp + this.previousIndex=message.userChain.index + this.previousPurchaseCOINAmountCummulate=(message.purchaseCOIN||{}).amountCummulate||0 + this.previousContractAmountCummulate=(message.contract||{}).amountCummulate||0 + this.previousAmountInterestCummulate=(message.interest||{}).amountCummulate||0 + this.previousAmountTransactionCummulate=((message.transactionIn||{}).amountCummulate||0)-((message.transactionOut||{}).amountCummulate||0) + } + + signContract(){ + this.UI.createMessage({ + chain:this.focusUserLastMessageObj.user, + text:'Contract signature for level '+((this.focusUserLastMessageObj.contract||{}).level||0), + contractSignature:{ + user:this.focusUserLastMessageObj.user, + contract:this.focusUserLastMessageObj.contract||{} + } + }) + this.router.navigate(['chat',this.focusUserLastMessageObj.user]) + } + + loadMore() { + this.messageNumberDisplay+=15 + this.refreshMessages() + } + +} diff --git a/src/app/settings.component.ts b/src/app/settings.component.ts deleted file mode 100644 index 4f91f70b..00000000 --- a/src/app/settings.component.ts +++ /dev/null @@ -1,222 +0,0 @@ -import { Component } from '@angular/core'; -import { AngularFireAuth } from '@angular/fire/compat/auth'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; -import { Router, ActivatedRoute } from '@angular/router'; -import { UserInterfaceService } from './userInterface.service'; -import { AngularFireStorage } from '@angular/fire/compat/storage'; -import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore'; -import firebase from 'firebase/compat/app'; - -@Component({ - selector:'settings', - template:` -
- -
-
- - -
-
- {{UI.currentUserLastMessageObj?.name}} - {{UI.formatSharesToPRNCurrency(null,UI.currentUserLastMessageObj?.wallet?.shareBalance||0)}} -
- {{UI.currentUserLastMessageObj?.userPresentation}} Level {{UI.currentUserLastMessageObj?.contract?.levelTimeAdjusted|number:'1.1-1'}} - Waiting for contract signature (Level {{UI.currentUserLastMessageObj?.contract?.level}}) -
-
-
-
Your name (preferably your first name)
- -
Update my name
-
-
Your preferred currency
-
-
    -
  • - {{currency[1].designation}} -
  • -
-
-
-
Your short presentation
-
Your short presentation helps other members get to know you.
-
I am someone who is:
- -
Update my presentation
-
-
Your public link
-
Add view only public link so other members can view your documents, website, code and more.
- -
Update my link
-
-
Your email address
-
Authentication address.
- -
Update my email address
-
-
Your PERRINN contract
-
This contract is between you and PERRINN team. When these settings are updated, they will need to be approved before taking effect. You or PERRINN can cancel this contract at any time.
-
Level [1-10] defines the level of experience / capacity to resolve problems independently. Level 1 is university student with no experience, 10 is expert (10+ years experience in the field). After signature your level will increase automatically with time at a rate of +1 per year.
- -
No contract registered.
-
Contract number {{UI.currentUserLastMessageObj?.contract?.createdTimestamp}}
-
Signature valid for level {{UI.currentUserLastMessageObj?.contract?.levelTimeAdjusted|number:'1.1-1'}}, you will receive {{UI.formatSharesToPRNCurrency(null,UI.appSettingsContract.hourlyRateLevel1*UI.currentUserLastMessageObj?.contract?.levelTimeAdjusted)}} per hour when you declare working hours.
-
Waiting for contract signature
-
Update my contract
-
-
logout
-
- `, -}) -export class SettingsComponent { - name:string - userPresentation:string - emailsAuth:string - contract:any - searchFilter:string - publicLink:any - - constructor( - public afAuth:AngularFireAuth, - public afs:AngularFirestore, - public router:Router, - private storage:AngularFireStorage, - public UI:UserInterfaceService - ) { - this.contract={} - this.name=this.UI.currentUserLastMessageObj.name||null - this.userPresentation=this.UI.currentUserLastMessageObj.userPresentation||null - this.publicLink=this.UI.currentUserLastMessageObj.publicLink||null - this.emailsAuth=this.UI.currentUserLastMessageObj.emails.auth||null - this.contract.level=(this.UI.currentUserLastMessageObj.contract||{}).level||null - } - - ngOnInit() { - } - - updateName(){ - if(!this.name)return - this.UI.createMessage({ - chain:this.UI.currentUser, - text:'Updating my name to '+this.name, - name:this.name - }) - this.router.navigate(['chat',this.UI.currentUser]) - } - - updateUserCurrency(currency){ - if(!currency)return - this.UI.createMessage({ - chain:this.UI.currentUser, - text:'Updating my preferred currency to '+this.UI.appSettingsPayment.currencyList[currency].designation, - userCurrency:currency - }) - this.router.navigate(['chat',this.UI.currentUser]) - } - - updateUserPresentation(){ - if(!this.userPresentation)return - this.UI.createMessage({ - chain:this.UI.currentUser, - text:'Updating my presentation to '+this.userPresentation, - userPresentation:this.userPresentation - }) - this.router.navigate(['chat',this.UI.currentUser]) - } - - updatePublicLink(){ - if(this.publicLink==(this.UI.currentUserLastMessageObj.publicLink||null))return - this.UI.createMessage({ - chain:this.UI.currentUser, - text:'Updating my public link.', - publicLink:this.publicLink - }) - this.router.navigate(['chat',this.UI.currentUser]) - } - - updateEmails(){ - if(this.emailsAuth!=this.UI.currentUserLastMessageObj.emails.auth){ - this.UI.createMessage({ - chain:this.UI.currentUser, - text:'Updating my email addresses.', - emails:{ - auth:this.emailsAuth - } - }) - this.router.navigate(['chat',this.UI.currentUser]) - return - } - else return - } - - updateContract(){ - if(!this.contract.level)return - this.UI.createMessage({ - chain:this.UI.currentUser, - text:'Updating my contract details to level '+this.contract.level, - contract:{ - level:this.contract.level - } - }) - this.router.navigate(['chat',this.UI.currentUser]) - } - - addChild(team){ - } - - onImageChange(event:any) { - const image = event.target.files[0]; - const uploader = document.getElementById('uploader') as HTMLInputElement; - const storageRef = this.storage.ref('images/'+Date.now()+image.name); - const task = storageRef.put(image); - - task.snapshotChanges().subscribe((snapshot) => { - document.getElementById('buttonFile').style.visibility = 'hidden'; - document.getElementById('uploader').style.visibility = 'visible'; - - const percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; - uploader.value = percentage.toString(); - }, - (err:any) => { - document.getElementById('buttonFile').style.visibility = 'visible'; - document.getElementById('uploader').style.visibility = 'hidden'; - uploader.value = '0'; - }, - () => { - uploader.value = '0'; - document.getElementById('buttonFile').style.visibility = 'visible'; - document.getElementById('uploader').style.visibility = 'hidden'; - let imageTimestamp = task.task.snapshot.ref.name.substring(0, 13); - storageRef.getDownloadURL().subscribe(url => { - this.UI.createMessage({ - chain:this.UI.currentUser, - text:'updating my profile picture', - userImageTimestamp:imageTimestamp, - chatImageTimestamp:imageTimestamp, - chatImageUrlThumb:url, - chatImageUrlMedium:url, - chatImageUrlOriginal:url, - imageUrlOriginal:url - }) - this.router.navigate(['chat',this.UI.currentUser]) - }); - }); - } - - objectToArray(obj) { - if (obj == null) { return []; } - return Object.keys(obj).map(function(key) { - return [key, obj[key]]; - }); - } - -} diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html new file mode 100644 index 00000000..a05a3795 --- /dev/null +++ b/src/app/settings/settings.component.html @@ -0,0 +1,64 @@ +
+ +
+
+ + +
+
+ {{UI.currentUserLastMessageObj?.name}} + {{UI.formatSharesToPRNCurrency(null,UI.currentUserLastMessageObj?.wallet?.balance||0)}} +
+ {{UI.currentUserLastMessageObj?.userPresentation}} Level {{UI.currentUserLastMessageObj?.contract?.levelTimeAdjusted|number:'1.1-1'}} + Waiting for contract signature (Level {{UI.currentUserLastMessageObj?.contract?.level}}) +
+
+
+
Your name (preferably your first name)
+ +
Update my name
+
+
Your preferred currency
+
+
    +
  • + {{currency[1].designation}} +
  • +
+
+
+
Your short presentation
+
Your short presentation helps other members get to know you.
+
I am someone who is:
+ +
Update my presentation
+
+
Your public link
+
Add view only public link so other members can view your documents, website, code and more.
+ +
Update my link
+
+
Your email address
+
Authentication address.
+ +
Update my email address
+
+
Your PERRINN contract
+
This contract is between you and PERRINN team. When these settings are updated, they will need to be approved before taking effect. You or PERRINN can cancel this contract at any time.
+
Level [1-10] defines the level of experience / capacity to resolve problems independently. Level 1 is university student with no experience, 10 is expert (10+ years experience in the field). After signature your level will increase automatically with time at a rate of +1 per year.
+ +
No contract registered.
+
Contract number {{UI.currentUserLastMessageObj?.contract?.createdTimestamp}}
+
Signature valid for level {{UI.currentUserLastMessageObj?.contract?.levelTimeAdjusted|number:'1.1-1'}}, you will receive {{UI.formatSharesToPRNCurrency(null,UI.appSettingsContract.hourlyRateLevel1*UI.currentUserLastMessageObj?.contract?.levelTimeAdjusted)}} per hour when you declare working hours.
+
Waiting for contract signature
+
Update my contract
+
+
logout
+
\ No newline at end of file diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts new file mode 100644 index 00000000..0eb6b0b2 --- /dev/null +++ b/src/app/settings/settings.component.ts @@ -0,0 +1,157 @@ +import { Component } from '@angular/core'; +import { AngularFireAuth } from '@angular/fire/compat/auth'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { Router, ActivatedRoute } from '@angular/router'; +import { UserInterfaceService } from './../userInterface.service'; +import { AngularFireStorage } from '@angular/fire/compat/storage'; +import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore'; +import firebase from 'firebase/compat/app'; + +@Component({ + selector:'settings', + templateUrl:'./settings.component.html', +}) +export class SettingsComponent { + name:string + userPresentation:string + emailsAuth:string + contract:any + searchFilter:string + publicLink:any + + constructor( + public afAuth:AngularFireAuth, + public afs:AngularFirestore, + public router:Router, + private storage:AngularFireStorage, + public UI:UserInterfaceService + ) { + this.contract={} + this.name=this.UI.currentUserLastMessageObj.name||null + this.userPresentation=this.UI.currentUserLastMessageObj.userPresentation||null + this.publicLink=this.UI.currentUserLastMessageObj.publicLink||null + this.emailsAuth=this.UI.currentUserLastMessageObj.emails.auth||null + this.contract.level=(this.UI.currentUserLastMessageObj.contract||{}).level||null + } + + ngOnInit() { + } + + updateName(){ + if(!this.name)return + this.UI.createMessage({ + chain:this.UI.currentUser, + text:'Updating my name to '+this.name, + name:this.name + }) + this.router.navigate(['chat',this.UI.currentUser]) + } + + updateUserCurrency(currency){ + if(!currency)return + this.UI.createMessage({ + chain:this.UI.currentUser, + text:'Updating my preferred currency to '+this.UI.appSettingsPayment.currencyList[currency].designation, + userCurrency:currency + }) + this.router.navigate(['chat',this.UI.currentUser]) + } + + updateUserPresentation(){ + if(!this.userPresentation)return + this.UI.createMessage({ + chain:this.UI.currentUser, + text:'Updating my presentation to '+this.userPresentation, + userPresentation:this.userPresentation + }) + this.router.navigate(['chat',this.UI.currentUser]) + } + + updatePublicLink(){ + if(this.publicLink==(this.UI.currentUserLastMessageObj.publicLink||null))return + this.UI.createMessage({ + chain:this.UI.currentUser, + text:'Updating my public link.', + publicLink:this.publicLink + }) + this.router.navigate(['chat',this.UI.currentUser]) + } + + updateEmails(){ + if(this.emailsAuth!=this.UI.currentUserLastMessageObj.emails.auth){ + this.UI.createMessage({ + chain:this.UI.currentUser, + text:'Updating my email addresses.', + emails:{ + auth:this.emailsAuth + } + }) + this.router.navigate(['chat',this.UI.currentUser]) + return + } + else return + } + + updateContract(){ + if(!this.contract.level)return + this.UI.createMessage({ + chain:this.UI.currentUser, + text:'Updating my contract details to level '+this.contract.level, + contract:{ + level:this.contract.level + } + }) + this.router.navigate(['chat',this.UI.currentUser]) + } + + addChild(team){ + } + + onImageChange(event:any) { + const image = event.target.files[0]; + const uploader = document.getElementById('uploader') as HTMLInputElement; + const storageRef = this.storage.ref('images/'+Date.now()+image.name); + const task = storageRef.put(image); + + task.snapshotChanges().subscribe((snapshot) => { + document.getElementById('buttonFile').style.visibility = 'hidden'; + document.getElementById('uploader').style.visibility = 'visible'; + + const percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; + uploader.value = percentage.toString(); + }, + (err:any) => { + document.getElementById('buttonFile').style.visibility = 'visible'; + document.getElementById('uploader').style.visibility = 'hidden'; + uploader.value = '0'; + }, + () => { + uploader.value = '0'; + document.getElementById('buttonFile').style.visibility = 'visible'; + document.getElementById('uploader').style.visibility = 'hidden'; + let imageTimestamp = task.task.snapshot.ref.name.substring(0, 13); + storageRef.getDownloadURL().subscribe(url => { + this.UI.createMessage({ + chain:this.UI.currentUser, + text:'updating my profile picture', + userImageTimestamp:imageTimestamp, + chatImageTimestamp:imageTimestamp, + chatImageUrlThumb:url, + chatImageUrlMedium:url, + chatImageUrlOriginal:url, + imageUrlOriginal:url + }) + this.router.navigate(['chat',this.UI.currentUser]) + }); + }); + } + + objectToArray(obj) { + if (obj == null) { return []; } + return Object.keys(obj).map(function(key) { + return [key, obj[key]]; + }); + } + +} diff --git a/src/styles.css b/src/styles.css index d1809006..3ac552b2 100644 --- a/src/styles.css +++ b/src/styles.css @@ -27,8 +27,6 @@ *::-webkit-scrollbar-track { background-color: #131B20; } -html { -} body { border: 0; background-color:#222C32; @@ -61,6 +59,9 @@ a:visited { width: 100%; user-select: none; } +.menu span:hover, .menu img:hover{ + opacity: 0.6; +} .menu .iconSmall { cursor: pointer; text-align: center; @@ -108,15 +109,18 @@ a:visited { .buttonBlack { cursor: pointer; background-color: black; - color: #B0BAC0; + color: whitesmoke; margin: 0 auto; text-align:center; border-style:solid; padding:3px; - border-color:#B0BAC0; + border-color:whitesmoke; + border-radius: 4px; } .buttonBlack:hover{ - opacity: 0.95; + background-color:rgba(67,67,67,0.67); + color: #B0BAC0; + border-color: #B0BAC0; } .buttonWhite { cursor: pointer; @@ -126,9 +130,13 @@ a:visited { text-align:center; border-style:solid; padding:3px; + border-color:black; + border-radius: 4px; } .buttonWhite:hover{ - opacity: 0.95; + background-color:rgba(56,118,29,0.5); + color: whitesmoke; + border-color:whitesmoke; } .buttonRed { cursor: pointer; @@ -377,4 +385,4 @@ img:hover { -webkit-transform: scale(1.0); transform: scale(1.0); } -} +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 0b5860c8..307285c3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,5 +19,7 @@ ], "module": "es2015" }, - + // "angularCompilerOptions": { + // "strictTemplates": true + // } }