diff --git a/src/app/campaigns/campaign-details/components/campaign-details-container/campaign-details-container.component.html b/src/app/campaigns/campaign-details/components/campaign-details-container/campaign-details-container.component.html index 78434e310..721e7e32e 100755 --- a/src/app/campaigns/campaign-details/components/campaign-details-container/campaign-details-container.component.html +++ b/src/app/campaigns/campaign-details/components/campaign-details-container/campaign-details-container.component.html @@ -1,3 +1,4 @@ + +
diff --git a/src/app/campaigns/campaign-details/components/campaign-details-container/campaign-details-container.component.ts b/src/app/campaigns/campaign-details/components/campaign-details-container/campaign-details-container.component.ts index 5edb450ce..10397d011 100755 --- a/src/app/campaigns/campaign-details/components/campaign-details-container/campaign-details-container.component.ts +++ b/src/app/campaigns/campaign-details/components/campaign-details-container/campaign-details-container.component.ts @@ -317,7 +317,26 @@ export class CampaignDetailsContainerComponent implements OnInit { return description ? description.slice(0, maxLength) : ''; } + + updateMetaTags(campaign: Campaign) { + if (campaign) { + this.ogImageUrl = campaign.coverSrcMobile.includes('ipfs') + ? ipfsURL + campaign.coverSrcMobile.substring(27, campaign.coverSrcMobile.length) + : campaign.coverSrcMobile; + + this.meta.updateTag({ property: 'og:title', content: campaign.title }); + this.meta.updateTag({ property: 'og:description', content: campaign.description }); + this.meta.updateTag({ property: 'og:image', content: this.ogImageUrl }); + + this.meta.updateTag({ property: 'og:image:width', content: '1200' }); + this.meta.updateTag({ property: 'og:image:height', content: '630' }); + + this.meta.updateTag({ name: 'twitter:card', content: 'summary_large_image' }); + this.meta.updateTag({ name: 'twitter:image', content: this.ogImageUrl }); + } + } + ngOnDestroy(): void { // Remove or update any additional meta tags when the component is destroyed this.meta.updateTag({ name: 'og:title', content: '' }); diff --git a/src/app/campaigns/campaigns.module.ts b/src/app/campaigns/campaigns.module.ts index 9f8515bd5..8d5673b5e 100755 --- a/src/app/campaigns/campaigns.module.ts +++ b/src/app/campaigns/campaigns.module.ts @@ -35,6 +35,11 @@ import { DraftPictureComponent } from './components/draft-picture/draft-picture. import { CommonModule } from '@angular/common'; import { SocialsComponent } from './socials/socials.component'; import { SharedModule } from '@app/shared/shared.module'; + +import { cryptoReducerList } from '@app/core/store/crypto-prices/reducer/crypto.reducer'; +import { CryptoEffectsList } from '@app/core/store/crypto-prices/effects/crypto.effects'; + + import { CampaignDetailsModule } from './campaign-details/campaign-details.module'; @NgModule({ @@ -72,7 +77,9 @@ import { CampaignDetailsModule } from './campaign-details/campaign-details.modul fromListLinks.linksListFeatureKey, fromListLinks.reducer ), - SharedModule + SharedModule, + StoreModule.forFeature('cryptoPriceList', cryptoReducerList), + EffectsModule.forFeature([CryptoEffectsList]), ], exports: [CampaignsRoutingModule], providers: [ConvertFromWei] diff --git a/src/app/campaigns/services/format-data.service.ts b/src/app/campaigns/services/format-data.service.ts index 1b74b63fe..24006e5d8 100755 --- a/src/app/campaigns/services/format-data.service.ts +++ b/src/app/campaigns/services/format-data.service.ts @@ -5,7 +5,11 @@ import { CryptofetchServiceService } from '@core/services/wallet/cryptofetch-ser import { Big } from 'big.js'; import { WalletFacadeService } from '@core/facades/wallet-facade.service'; import { Subject } from 'rxjs'; -import { map, takeUntil } from 'rxjs/operators'; +import { map, take, takeUntil } from 'rxjs/operators'; +import * as CryptoActionsList from '../../core/store/crypto-prices/actions/crypto.actions'; +import { Store } from '@ngrx/store'; +import { selectCryptoPriceList } from '@app/core/store/crypto-prices/selectors/crypto.selectors'; +import { SharedDataService } from '@app/shared/service/SharedDataService'; @Injectable({ providedIn: 'root' @@ -13,20 +17,33 @@ import { map, takeUntil } from 'rxjs/operators'; export class FormatDataService { private coinsPrices: any = []; private isDestroyed = new Subject(); + cryptoPriceList: any[] | null | undefined; constructor( private convertToWeiPipe: ConvertToWeiPipe, private fetchCoinsPrices: CryptofetchServiceService, - private walletFacade: WalletFacadeService + private walletFacade: WalletFacadeService, + private store: Store, + private sharedDataService: SharedDataService ) { - this.walletFacade - .getCryptoPriceList() + this.store.dispatch(CryptoActionsList.fetchCryptoPriceList()); + this.store + .select(selectCryptoPriceList) .pipe( - map((response: any) => response.data), - takeUntil(this.isDestroyed) + takeUntil(this.isDestroyed), + map((response: any) => { + if (response && response.data) { + return response.data; + } else { + return null; + } + }) ) .subscribe((data: any) => { - this.coinsPrices = data; + if (data) { + this.coinsPrices = data; + this.sharedDataService.setCryptoDetails(this.coinsPrices); + } }); } @@ -51,14 +68,14 @@ export class FormatDataService { if (campaign.hasOwnProperty('targetedCountries')) { object.countries = campaign.targetedCountries; //this.countriesCode(campaign.targetedCountries); } - if (campaign.hasOwnProperty('currency')) { + if (campaign.hasOwnProperty('currency')) { object.token = { name: campaign.currency.name || '', type: campaign.currency.type.toUpperCase() || '', - addr: campaign.currency.addr || null + addr: campaign.currency.addr || null }; } - + if (campaign.hasOwnProperty('tags')) { object.tags = campaign.tags?.map((tag: any) => tag.value || tag); } @@ -72,7 +89,7 @@ export class FormatDataService { object.startDate = new Date(campaign.startDate).getTime() / 1000; } - campaign.limitParticipation && (object.limit = campaign.limitParticipation) + campaign.limitParticipation && (object.limit = campaign.limitParticipation); if (campaign.hasOwnProperty('remuneration')) { // TODO: fix remuneration not sent to backend @@ -125,7 +142,7 @@ export class FormatDataService { } if (campaign.hasOwnProperty('initialBudgetInUSD')) { - object.cost_usd = campaign.initialBudgetInUSD.toString(); + object.cost_usd = campaign.initialBudgetInUSD.toString(); } if (campaign.hasOwnProperty('cover')) { diff --git a/src/app/core/services/crypto-info.service.ts b/src/app/core/services/crypto-info.service.ts index 86e05aada..d53ce24d6 100755 --- a/src/app/core/services/crypto-info.service.ts +++ b/src/app/core/services/crypto-info.service.ts @@ -1,6 +1,9 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import * as http from 'http'; +import { Observable } from 'rxjs'; +import { IResponseWallet } from '../iresponse-wallet'; +import { sattUrl } from '@app/config/atn.config'; @Injectable({ providedIn: 'root' @@ -13,9 +16,11 @@ export class CryptoInfoService { ); } - listIdToken() { - return this.http.get('https://api.coingecko.com/api/v3/coins/list'); + listIdToken(): Observable { + const url = ` https://api.coingecko.com/api/v3/coins/list`; + return this.http.get(url); } + historiqueToken( cryptoId: string, currency: string, @@ -32,13 +37,14 @@ export class CryptoInfoService { ); } - marketChartToken( - cryptoId: string, - currency: string, - days: string - ) { - - + getCharts(id:any, range:any) { + return this.http.post(sattUrl + '/wallet/getCharts', { + id: id, + range: range + }); + } + + marketChartToken(cryptoId: string, currency: string, days: string) { return this.http.get( `https://api.coingecko.com/api/v3/coins/${cryptoId}/market_chart?vs_currency=${currency}&days=${days}` ); diff --git a/src/app/core/store/crypto-prices/actions/crypto.actions.ts b/src/app/core/store/crypto-prices/actions/crypto.actions.ts new file mode 100644 index 000000000..a0b3199d7 --- /dev/null +++ b/src/app/core/store/crypto-prices/actions/crypto.actions.ts @@ -0,0 +1,12 @@ +import { createAction, props } from '@ngrx/store'; + +export const fetchCryptoPriceList = createAction('[Crypto] Fetch Price List'); +export const fetchCryptoPriceListSuccess = createAction( + '[Crypto] Fetch Price List Success', + props<{ cryptoPriceList: any }>() +); + +export const fetchCryptoPriceListFailure = createAction( + '[Crypto] Fetch Price List Failure', + props<{ error: any }>() +); diff --git a/src/app/core/store/crypto-prices/effects/crypto.effects.ts b/src/app/core/store/crypto-prices/effects/crypto.effects.ts new file mode 100644 index 000000000..9df612ced --- /dev/null +++ b/src/app/core/store/crypto-prices/effects/crypto.effects.ts @@ -0,0 +1,31 @@ +import { map, catchError, mergeMap, tap } from 'rxjs/operators'; +import * as CryptoActions from '../actions/crypto.actions'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { WalletFacadeService } from '@app/core/facades/wallet-facade.service'; +import { Injectable } from '@angular/core'; +import { of } from 'rxjs'; + +@Injectable() +export class CryptoEffectsList { + constructor( + private actions$: Actions, + private walletFacadeService: WalletFacadeService + ) {} + + fetchCryptoPriceList$ = createEffect(() => + this.actions$.pipe( + ofType(CryptoActions.fetchCryptoPriceList), + // tap(() => console.log('fetchCryptoPriceList action dispatched')), + mergeMap(() => + this.walletFacadeService.getCryptoPriceList().pipe( + map((cryptoPriceList) => + CryptoActions.fetchCryptoPriceListSuccess({ cryptoPriceList }) + ), + catchError((error) => { + return of(CryptoActions.fetchCryptoPriceListFailure({ error })); + }) + ) + ) + ) + ); +} diff --git a/src/app/core/store/crypto-prices/reducer/crypto.reducer.ts b/src/app/core/store/crypto-prices/reducer/crypto.reducer.ts new file mode 100644 index 000000000..b7b2830ff --- /dev/null +++ b/src/app/core/store/crypto-prices/reducer/crypto.reducer.ts @@ -0,0 +1,31 @@ + import { createReducer, on } from '@ngrx/store'; + import * as CryptoActions from '../actions/crypto.actions'; + + export interface CryptoState { + cryptoPriceList: any[] | null; + error: any | null; + } + + export const initialState: CryptoState = { + cryptoPriceList: null, + error: null + }; + + export const cryptoReducerList = createReducer( + initialState, + on( + CryptoActions.fetchCryptoPriceListSuccess, + (state, { cryptoPriceList }) => { + return { + ...state, + cryptoPriceList, + error: null, + }; + } + ), + on(CryptoActions.fetchCryptoPriceListFailure, (state, { error }) => ({ + ...state, + cryptoPriceList: null, + error + })) + ); diff --git a/src/app/core/store/crypto-prices/selectors/crypto.selectors.ts b/src/app/core/store/crypto-prices/selectors/crypto.selectors.ts new file mode 100644 index 000000000..b6201982e --- /dev/null +++ b/src/app/core/store/crypto-prices/selectors/crypto.selectors.ts @@ -0,0 +1,9 @@ +import { createSelector, createFeatureSelector } from '@ngrx/store'; +import { CryptoState } from '../reducer/crypto.reducer'; + +const selectCryptoState = createFeatureSelector('cryptoPriceList'); + +export const selectCryptoPriceList = createSelector( + selectCryptoState, + (state) => state.cryptoPriceList +); diff --git a/src/app/shared/service/SharedDataService.ts b/src/app/shared/service/SharedDataService.ts new file mode 100644 index 000000000..a4896dae0 --- /dev/null +++ b/src/app/shared/service/SharedDataService.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class SharedDataService { + private cryptoDetails: any = []; + + setCryptoDetails(data: any): void { + this.cryptoDetails = data; + } + + getCryptoDetails(): any { + return this.cryptoDetails; + } +} diff --git a/src/app/wallet/components/crypto-info/crypto-info.component.html b/src/app/wallet/components/crypto-info/crypto-info.component.html index 75c078b57..d5049179d 100755 --- a/src/app/wallet/components/crypto-info/crypto-info.component.html +++ b/src/app/wallet/components/crypto-info/crypto-info.component.html @@ -30,7 +30,6 @@ src="{{ cryptoImgUrl }}" />
{{ cryptoName }}
@@ -54,7 +53,7 @@