diff --git a/angular.json b/angular.json index 1998c6a328325620f7097d465ee8d482f4ab474b..df701f0a8ccdeb988e2ff2651c55260d6f0582eb 100644 --- a/angular.json +++ b/angular.json @@ -95,8 +95,8 @@ "budgets": [ { "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" + "maximumWarning": "3mb", + "maximumError": "6mb" } ] }, @@ -143,8 +143,8 @@ "budgets": [ { "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" + "maximumWarning": "3mb", + "maximumError": "6mb" } ] }, diff --git a/src/app/account/accounts.service.ts b/src/app/account/accounts.service.ts index 9e1ef7e8bf15db57d089e2d8cbe6c0efb72a5b40..f5feca466854d93728dff500d11695090e9c60fb 100644 --- a/src/app/account/accounts.service.ts +++ b/src/app/account/accounts.service.ts @@ -38,6 +38,7 @@ import { FetchPolicy } from '@apollo/client'; import { TranslateService } from '@ngx-translate/core'; import { WotService } from '@app/wot/wot.service'; import { CertificationSearchFilter } from '@app/certification/history/cert-history.model'; +import { ISubmittableResult } from '@polkadot/types/types'; // kind of certify action enum CertType { @@ -598,63 +599,36 @@ export class AccountsService extends RxStartableService<AccountsState> { } try { - let txHash; - // Sign and send a transfer from Alice to Bob + let result: ISubmittableResult; + // Transfer with comment if (isNotNilOrBlank(comment)) { const txTransfer = this.api.tx.balances.transferKeepAlive(to.address, amount); const txComment = this.api.tx.system.remarkWithEvent(comment ?? ''); - txHash = this.api.tx.utility.batch([txTransfer, txComment]).signAndSend(issuerPair, async ({ status, events }) => { - if (status.isInBlock) { - console.info(`${this._logPrefix}Extrinsic status`, status.toHuman()); - console.info(`${this._logPrefix}Completed at block hash #${status.hash.toHuman()}`); - - if (this._debug) console.debug(`${this._logPrefix}Block events:`, JSON.stringify(events)); - - // List of outdated accounts - const outdatedAccounts = [issuerAccount]; - - // Add receiver to outdated account - if (await this.isAvailable(to.address)) { - const toAccount = await this.getByAddress(to.address); - outdatedAccounts.push(toAccount); - } - - await sleep(200); // Wait 200ms - - await this.refreshData(outdatedAccounts, { reload: true }); - } else { - console.info(`${this._logPrefix}Current status: `, status.toHuman()); - } - }); + result = await ExtrinsicUtils.submit(this.api.tx.utility.batch([txTransfer, txComment]), issuerPair); } else { - txHash = this.api.tx.balances.transferKeepAlive(to.address, amount).signAndSend(issuerPair, async ({ status, events }) => { - if (status.isInBlock) { - console.info(`${this._logPrefix}Extrinsic status`, status.toHuman()); - console.info(`${this._logPrefix}Completed at block hash #${status.hash.toHuman()}`); + // Transfer without comment + result = await ExtrinsicUtils.submit(this.api.tx.balances.transferKeepAlive(to.address, amount), issuerPair); + } + const { status, events } = result; + console.info(`${this._logPrefix}Extrinsic status`, status.toHuman()); + console.info(`${this._logPrefix}Completed at block hash #${status.hash.toHuman()}`); - if (this._debug) console.debug(`${this._logPrefix}Block events:`, JSON.stringify(events)); + if (this._debug) console.debug(`${this._logPrefix}Block events:`, JSON.stringify(events)); - // List of outdated accounts - const outdatedAccounts = [issuerAccount]; + // List of outdated accounts + const outdatedAccounts = [issuerAccount]; - // Add receiver to outdated account - if (await this.isAvailable(to.address)) { - const toAccount = await this.getByAddress(to.address); - outdatedAccounts.push(toAccount); - } + // Add receiver to outdated account + if (await this.isAvailable(to.address)) { + const toAccount = await this.getByAddress(to.address); + outdatedAccounts.push(toAccount); + } - await sleep(200); // Wait 200ms + await sleep(200); // Wait 200ms - await this.refreshData(outdatedAccounts, { reload: true }); - } else { - console.info(`${this._logPrefix}Current status: `, status.toHuman()); - } - }); - } - // Show the hash - console.info(`${this._logPrefix}Finalized hash ${txHash}`); + await this.refreshData(outdatedAccounts, { reload: true }); - return txHash.toString(); + return status.hash.toString(); } catch (err) { console.error(err); throw new Error('ERROR.SEND_TX_FAILED'); diff --git a/src/app/account/wallet/wallet.page.html b/src/app/account/wallet/wallet.page.html index cdb23b72a6cdc45f5f8202f8109f327d7f8cea7f..d6f04b965e6ec46bbc5dad62a7931b88fdf0f11b 100644 --- a/src/app/account/wallet/wallet.page.html +++ b/src/app/account/wallet/wallet.page.html @@ -186,9 +186,11 @@ HELP.GLOSSARY.DISTANCE_RULE <ion-icon [color]="'tertiary'" name="help-circle-outline" (click)="showModalDistanceRuleDefinition()" tappable></ion-icon> </ion-label> - <ion-badge title="{{ titleDistanceRule() }}" color="{{ distanceRuleValid() ? 'success' : 'danger' }}"> - {{ refereePercent$ | async | percent: '1.1' }} - </ion-badge> + @if (!disableDistanceRule()) { + <ion-badge title="{{ titleDistanceRule() }}" color="{{ distanceRuleValid() ? 'success' : 'danger' }}"> + {{ refereePercent$ | async | percent: '1.1' }} + </ion-badge> + } </ion-item> } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 73967b6bf8c5369d7fd3cfeaf8392c7b5685ce6b..348a9591eecb9ce13bd8c8892beb093ef3bbdc79 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -31,6 +31,7 @@ import { IdentityConfirmValidators } from '@app/account/confirm/identity-confirm import { CodeInputModule } from 'angular-code-input'; import { HelpModule } from '@app/home/help/help.module'; import { AboutModule } from '@app/home/about/about.module'; +import { VerificationModule } from '@app/certification/verification/verification.module'; export function createTranslateLoader(http: HttpClient) { if (environment.production) { @@ -62,6 +63,7 @@ export function createTranslateLoader(http: HttpClient) { }, }), HelpModule, + VerificationModule, AboutModule, CodeInputModule.forRoot({ codeLength: 6, diff --git a/src/app/certification/verification/verification.modal.css b/src/app/certification/verification/verification.modal.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/app/certification/verification/verification.modal.html b/src/app/certification/verification/verification.modal.html new file mode 100644 index 0000000000000000000000000000000000000000..241bb17b34324c921ee7d151ffe722c88d7ca309 --- /dev/null +++ b/src/app/certification/verification/verification.modal.html @@ -0,0 +1,55 @@ +<ion-header [translucent]="true"> + <ion-toolbar color="primary"> + <ion-buttons slot="start"> + <ion-menu-button *ngIf="!canGoBack"></ion-menu-button> + <ion-back-button></ion-back-button> + </ion-buttons> + <ion-title translate>ACCOUNT.CERTIFICATION_MODAL.CHECKLIST_TITLE</ion-title> + </ion-toolbar> +</ion-header> + +<ion-content [fullscreen]="true"> + <ion-header collapse="condense"> + <ion-toolbar> + <ion-title size="large" translate>ACCOUNT.CERTIFICATION_MODAL.CHECKLIST_TITLE</ion-title> + </ion-toolbar> + </ion-header> + + <ion-list lines="none"> + @for (step of certificationModalConfig.steps; track step) { + <ion-item> + <ion-label [innerHTML]="step.labelKey | translate"></ion-label> + <ion-button [fill]="answers.get(step.labelKey) === true ? 'solid' : 'clear'" (click)="onAnswerSelect(step.labelKey, true)"> + <ion-icon slot="icon-only" name="checkmark-circle-outline"></ion-icon> + <ion-label translate>COMMON.BTN_YES</ion-label> + </ion-button> + + <ion-button [fill]="answers.get(step.labelKey) === false ? 'solid' : 'clear'" (click)="onAnswerSelect(step.labelKey, false)"> + <ion-icon slot="icon-only" name="close-circle-outline"></ion-icon> + <ion-label translate>COMMON.BTN_NO</ion-label> + </ion-button> + </ion-item> + } + </ion-list> +</ion-content> +@if (!mobile) { + <ion-footer> + <ion-toolbar> + <ion-row class="ion-no-padding"> + <ion-col size="4"></ion-col> + <!-- buttons --> + <ion-col size="8"> + <ion-button color="light" (click)="cancel()"> + <ion-label translate>COMMON.BTN_CLOSE</ion-label> + </ion-button> + + <ion-button [disabled]="!isCompleted()" (click)="doSubmit()"> + <ion-icon slot="start" name="checkmark-outline"></ion-icon> + <ion-label translate>COMMON.BTN_YES_CONTINUE</ion-label> + </ion-button> + </ion-col> + <ion-col size="4"></ion-col> + </ion-row> + </ion-toolbar> + </ion-footer> +} diff --git a/src/app/certification/verification/verification.modal.ts b/src/app/certification/verification/verification.modal.ts new file mode 100644 index 0000000000000000000000000000000000000000..9396514a3f1fe0ee8503b0edec0a0b151daa6e6c --- /dev/null +++ b/src/app/certification/verification/verification.modal.ts @@ -0,0 +1,109 @@ +import { Component } from '@angular/core'; +import { AppPage, AppPageState } from '@app/shared/pages/base-page.class'; +import { RxState } from '@rx-angular/state'; +import { Promise } from '@rx-angular/cdk/zone-less/browser'; +import { TranslateService } from '@ngx-translate/core'; +import { ModalController } from '@ionic/angular'; + +interface CertificationVerificationStep { + labelKey: string; + expectedResponse: boolean; +} +interface ModalSequenceConfig { + title: string; + steps: CertificationVerificationStep[]; +} + +export interface VerificationModalState extends AppPageState {} + +@Component({ + selector: 'app-verification-modal', + templateUrl: './verification.modal.html', + styleUrls: ['./verification.modal.css'], + providers: [RxState], +}) +export class VerificationModal extends AppPage<VerificationModalState> { + private readonly certificationSteps: CertificationVerificationStep[] = [ + { + labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.WELL_KNOWN', + expectedResponse: true, + }, + { + labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.REVOCATION', + expectedResponse: true, + }, + { + labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.CONTACT', + expectedResponse: true, + }, + { + labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.DOUBLE_IDENTITY', + expectedResponse: false, + }, + { + labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.MASTER_ACCOUNT', + expectedResponse: true, + }, + { + labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.LICENSE', + expectedResponse: true, + }, + { + labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.CREDENTIALS', + expectedResponse: true, + }, + { + labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.PUBLIC_KEY_DIFFERENT', + expectedResponse: false, + }, + ]; + + answers: Map<string, boolean> = new Map<string, boolean>(); + certificationModalConfig: ModalSequenceConfig; + + constructor( + protected translate: TranslateService, + protected viewCtrl: ModalController + ) { + super({ name: 'verification-modal' }); + this.certificationModalConfig = this.getCertificationModalConfig(); + } + + protected ngOnLoad(): Promise<Partial<VerificationModalState>> { + return Promise.resolve(undefined); + } + + private getCertificationModalConfig(): ModalSequenceConfig { + return { + title: 'ACCOUNT.CERTIFICATION_MODAL.CHECKLIST_TITLE', + steps: this.shuffleSteps(this.certificationSteps), + }; + } + + private shuffleSteps<T>(array: T[]): T[] { + const shuffled = [...array]; + for (let i = shuffled.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; + } + return shuffled.slice(0, 4); + } + + onAnswerSelect(step: string, value: boolean) { + this.answers.set(step, value); + } + + cancel() { + return this.viewCtrl.dismiss(undefined); + } + + isCompleted(): boolean { + return this.certificationModalConfig.steps.length === this.answers.size; + } + + doSubmit() { + return this.viewCtrl.dismiss( + this.isCompleted() && this.certificationSteps.every((step) => this.answers.get(step.labelKey) === step.expectedResponse) + ); + } +} diff --git a/src/app/certification/verification/verification.module.ts b/src/app/certification/verification/verification.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae36e9d4c3bfb091c045b6050019e4d80de0ff89 --- /dev/null +++ b/src/app/certification/verification/verification.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { AppSharedModule } from '@app/shared/shared.module'; +import { TranslateModule } from '@ngx-translate/core'; +import { HomePageRoutingModule } from '@app/home/home-routing.module'; +import { AppAuthModule } from '@app/account/auth/auth.module'; +import { AppRegisterModule } from '@app/account/register/register.module'; +import { AppTransferModule } from '@app/transfer/send/transfer.module'; +import { VerificationModal } from '@app/certification/verification/verification.modal'; + +@NgModule({ + imports: [AppSharedModule, TranslateModule.forChild(), HomePageRoutingModule, AppAuthModule, AppRegisterModule, AppTransferModule], + declarations: [VerificationModal], +}) +export class VerificationModule {} diff --git a/src/app/currency/currency.page.html b/src/app/currency/currency.page.html index 94b83521c9c300eda4fda49e1b4099bdfafeb387..7810274a1beb3136320bb7679039a9cf0a892222 100644 --- a/src/app/currency/currency.page.html +++ b/src/app/currency/currency.page.html @@ -21,7 +21,9 @@ <ion-col size="8" size-sm="12" size-md="12" size-lg="8" size-xs="12"> <ion-card> <ion-card-content> - <ion-label + <div + translatedHelp + (helpRequest)="showHelpModal($event)" [innerHTML]=" 'CURRENCY.VIEW.CURRENCY_SHORT_DESCRIPTION' | translate @@ -31,8 +33,9 @@ N: params.members, dt: params.udCreationPeriodMs | duration: 'ms' } + | safe " - ></ion-label> + ></div> </ion-card-content> </ion-card> </ion-col> diff --git a/src/app/currency/currency.page.ts b/src/app/currency/currency.page.ts index 42392ab8650722a66621590e011bb082c00afcf5..d5a3c204bda032d91f461b3ca42b185d6d58474d 100644 --- a/src/app/currency/currency.page.ts +++ b/src/app/currency/currency.page.ts @@ -18,6 +18,7 @@ import { Color } from '@app/shared/colors/graph-colors'; import { ModalController } from '@ionic/angular'; import { Promise } from '@rx-angular/cdk/zone-less/browser'; import { map } from 'rxjs/operators'; +import { HelpPage } from '@app/home/help/help.page'; export interface CurrencyParameters { currencyName: string; @@ -387,4 +388,17 @@ export class CurrencyPage extends AppPage<CurrencyPageState> { private getFirstBlockValue(histories: CurrencyHistory[]): Moment { return moment(histories[0].timestamp); } + + async showHelpModal(label: string) { + const modal = await this.modalCtrl.create({ + id: 'help-modal', + component: HelpPage, + componentProps: { + highlightedDefinition: label, + }, + presentingElement: this._presentingElement, + canDismiss: true, + }); + await modal.present(); + } } diff --git a/src/app/home/feed/feed.component.ts b/src/app/home/feed/feed.component.ts index c3303c16c82a7907e32cf8e99119d0589bd84ae0..83776f320afbd68b0693d46a44a43018777bef9e 100644 --- a/src/app/home/feed/feed.component.ts +++ b/src/app/home/feed/feed.component.ts @@ -37,6 +37,7 @@ export class FeedComponent extends AppPage<FeedState> { protected async ngOnLoad(): Promise<FeedState> { await Promise.all([this.settings.ready(), this.networkService.ready()]); + console.log(await this.settings); const feedUrl = environment.feed.jsonFeed.get(this.settings.locale); this.topics = await this.networkService.loadJsonFeed(feedUrl); this.topics = this.topics.filter(isNotNil).map((value) => value); diff --git a/src/app/home/help/help.page.html b/src/app/home/help/help.page.html index 1c7dd5e8778486153efeaa3e35d40e7c18d78527..743f8d7db6724885af9379fc79c399489c5f423d 100644 --- a/src/app/home/help/help.page.html +++ b/src/app/home/help/help.page.html @@ -133,10 +133,10 @@ </ion-row> </ion-grid> </ion-item> - <ion-item lines="none"> - <ion-grid> + <ion-item id="UD" lines="none"> + <ion-grid [ngClass]="{ highlight: isUDHelp() }"> <ion-row> - <ion-col size="4" size-lg="4" size-sm="12"> + <ion-col size="4" size-lg="4" size-sm="12" [ngClass]="{ 'text-bold': isUDHelp() }"> <ion-label translate>COMMON.UNIVERSAL_DIVIDEND</ion-label> </ion-col> <ion-col size="8" size-lg="8" size-sm="12"> diff --git a/src/app/home/help/help.page.ts b/src/app/home/help/help.page.ts index 15d477f54870e5e55b8115ad83465942d76f09ca..aefbcc768988de93b30bbed21c2ed0fe7173e6d8 100644 --- a/src/app/home/help/help.page.ts +++ b/src/app/home/help/help.page.ts @@ -12,7 +12,7 @@ import { isNotNilOrBlank } from '@app/shared/functions'; export interface HelpPageState extends AppPageState, Settings {} -export declare type HighlightedDefinition = 'GLOSSARY_DISTANCE_RULE' | 'DEMO_MODE_HELP' | 'READONLY_MODE_HELP' | ''; +export declare type HighlightedDefinition = 'GLOSSARY_DISTANCE_RULE' | 'DEMO_MODE_HELP' | 'READONLY_MODE_HELP' | 'UD' | ''; @Component({ selector: 'app-help', @@ -60,6 +60,10 @@ export class HelpPage extends AppPage<HelpPageState> implements OnInit { return this.highlightedDefinition === 'READONLY_MODE_HELP'; } + isUDHelp() { + return this.highlightedDefinition === 'UD'; + } + async scrollToDefinition(definitionId: string) { const targetElement = document.getElementById(definitionId); if (targetElement) { diff --git a/src/app/network/indexer/indexer-account.gql b/src/app/network/indexer/indexer-account.gql index fced4b5d137376f8e621b7b14ecdefb8ece17571..4289e3a4dc3a064fe2e59055e5757ec10b46489b 100644 --- a/src/app/network/indexer/indexer-account.gql +++ b/src/app/network/indexer/indexer-account.gql @@ -6,11 +6,6 @@ fragment LightIdentity on Identity { status isMember createdOn - membershipHistory { - __typename - id - eventType - } } fragment LightAccount on Account { diff --git a/src/app/network/indexer/indexer-transfer.gql b/src/app/network/indexer/indexer-transfer.gql index a2dc9ab7f9013fcf906138c42f89fca795f60af0..127ebdf3a21bcbb649c8873ee9fe4c59b4114f98 100644 --- a/src/app/network/indexer/indexer-transfer.gql +++ b/src/app/network/indexer/indexer-transfer.gql @@ -10,6 +10,9 @@ fragment Transfer on Transfer { to { ...LightAccount } + comment { + remark + } } fragment TransferConnection on TransferConnection { diff --git a/src/app/network/indexer/indexer-types.generated.ts b/src/app/network/indexer/indexer-types.generated.ts index 7b48abfda0326c2b35a21bffd7853a437623d6e7..6edf4ab32976f321431434e334cedb976a494f59 100644 --- a/src/app/network/indexer/indexer-types.generated.ts +++ b/src/app/network/indexer/indexer-types.generated.ts @@ -6185,11 +6185,11 @@ export type TxCommentAggregateBoolExpCount = { predicate: IntComparisonExp; }; -export type LightIdentityFragment = { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> }; +export type LightIdentityFragment = { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number }; -export type LightAccountFragment = { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null }; +export type LightAccountFragment = { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null }; -export type LightAccountConnectionFragment = { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }> }; +export type LightAccountConnectionFragment = { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }> }; export type LightBlockFragment = { __typename: 'Block', id: string, height: number, hash: any, timestamp: any, callsCount: number, eventsCount: number, extrinsicsCount: number }; @@ -6219,13 +6219,13 @@ export type LastBlockQuery = { __typename?: 'query_root', blockConnection: { __t export type LightCertFragment = { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number }; -export type CertFragment = { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null }; +export type CertFragment = { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null }; -export type CertConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; +export type CertConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; -export type CertReceivedConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; +export type CertReceivedConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; -export type CertIssuedConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; +export type CertIssuedConnectionFragment = { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } }; export type CertsConnectionByIssuerQueryVariables = Exact<{ address: Scalars['String']['input']; @@ -6235,7 +6235,7 @@ export type CertsConnectionByIssuerQueryVariables = Exact<{ }>; -export type CertsConnectionByIssuerQuery = { __typename?: 'query_root', identityConnection: { __typename?: 'IdentityConnection', edges: Array<{ __typename?: 'IdentityEdge', node: { __typename?: 'Identity', aggregate: { __typename?: 'CertAggregate', aggregate?: { __typename?: 'CertAggregateFields', count: number } | null }, connection: { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } } } }> } }; +export type CertsConnectionByIssuerQuery = { __typename?: 'query_root', identityConnection: { __typename?: 'IdentityConnection', edges: Array<{ __typename?: 'IdentityEdge', node: { __typename?: 'Identity', aggregate: { __typename?: 'CertAggregate', aggregate?: { __typename?: 'CertAggregateFields', count: number } | null }, connection: { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, receiver?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } } } }> } }; export type CertsConnectionByReceiverQueryVariables = Exact<{ address: Scalars['String']['input']; @@ -6245,7 +6245,7 @@ export type CertsConnectionByReceiverQueryVariables = Exact<{ }>; -export type CertsConnectionByReceiverQuery = { __typename?: 'query_root', identityConnection: { __typename?: 'IdentityConnection', edges: Array<{ __typename?: 'IdentityEdge', node: { __typename?: 'Identity', aggregate: { __typename?: 'CertAggregate', aggregate?: { __typename?: 'CertAggregateFields', count: number } | null }, connection: { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } } } }> } }; +export type CertsConnectionByReceiverQuery = { __typename?: 'query_root', identityConnection: { __typename?: 'IdentityConnection', edges: Array<{ __typename?: 'IdentityEdge', node: { __typename?: 'Identity', aggregate: { __typename?: 'CertAggregate', aggregate?: { __typename?: 'CertAggregateFields', count: number } | null }, connection: { __typename?: 'CertConnection', edges: Array<{ __typename?: 'CertEdge', node: { __typename: 'Cert', id: string, expireOn: number, createdOn: number, updatedOn: number, issuer?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }>, pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean } } } }> } }; export type LightUniversalDividendFragment = { __typename?: 'UniversalDividend', membersCount: number, blockNumber: number, timestamp: any, monetaryMass: any }; @@ -6261,9 +6261,9 @@ export type CurrencyHistoryQueryVariables = Exact<{ export type CurrencyHistoryQuery = { __typename?: 'query_root', universalDividendConnection: { __typename?: 'UniversalDividendConnection', edges: Array<{ __typename?: 'UniversalDividendEdge', node: { __typename?: 'UniversalDividend', membersCount: number, blockNumber: number, timestamp: any, monetaryMass: any } }> } }; -export type TransferFragment = { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null }; +export type TransferFragment = { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } | null, comment?: { __typename?: 'TxComment', remark: string } | null }; -export type TransferConnectionFragment = { __typename?: 'TransferConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'TransferEdge', node: { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null } }> }; +export type TransferConnectionFragment = { __typename?: 'TransferConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'TransferEdge', node: { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } | null, comment?: { __typename?: 'TxComment', remark: string } | null } }> }; export type TransferConnectionByAddressQueryVariables = Exact<{ address: Scalars['String']['input']; @@ -6273,7 +6273,7 @@ export type TransferConnectionByAddressQueryVariables = Exact<{ }>; -export type TransferConnectionByAddressQuery = { __typename?: 'query_root', transferConnection: { __typename?: 'TransferConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'TransferEdge', node: { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } | null } }> } }; +export type TransferConnectionByAddressQuery = { __typename?: 'query_root', transferConnection: { __typename?: 'TransferConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'TransferEdge', node: { __typename: 'Transfer', id: string, amount: any, timestamp: any, blockNumber: number, from?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } | null, to?: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } | null, comment?: { __typename?: 'TxComment', remark: string } | null } }> } }; export type WotSearchByTextQueryVariables = Exact<{ searchText: Scalars['String']['input']; @@ -6283,7 +6283,7 @@ export type WotSearchByTextQueryVariables = Exact<{ }>; -export type WotSearchByTextQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }> } }; +export type WotSearchByTextQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }> } }; export type WotSearchByAddressQueryVariables = Exact<{ address: Scalars['String']['input']; @@ -6293,7 +6293,7 @@ export type WotSearchByAddressQueryVariables = Exact<{ }>; -export type WotSearchByAddressQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }> } }; +export type WotSearchByAddressQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }> } }; export type WotSearchLastQueryVariables = Exact<{ first: Scalars['Int']['input']; @@ -6303,7 +6303,7 @@ export type WotSearchLastQueryVariables = Exact<{ }>; -export type WotSearchLastQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }> } }; +export type WotSearchLastQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }> } }; export type WotSearchByUidQueryVariables = Exact<{ name: Scalars['String']['input']; @@ -6313,7 +6313,7 @@ export type WotSearchByUidQueryVariables = Exact<{ }>; -export type WotSearchByUidQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number, membershipHistory: Array<{ __typename: 'MembershipEvent', id: string, eventType?: EventTypeEnum | null }> } | null } }> } }; +export type WotSearchByUidQuery = { __typename?: 'query_root', accountConnection: { __typename?: 'AccountConnection', pageInfo: { __typename?: 'PageInfo', endCursor: string, hasNextPage: boolean }, edges: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'Account', id: string, identity?: { __typename?: 'Identity', id: string, index: number, name: string, accountId?: string | null, status?: IdentityStatusEnum | null, isMember: boolean, createdOn: number } | null } }> } }; export const LightIdentityFragmentDoc = gql` fragment LightIdentity on Identity { @@ -6324,11 +6324,6 @@ export const LightIdentityFragmentDoc = gql` status isMember createdOn - membershipHistory { - __typename - id - eventType - } } `; export const LightAccountFragmentDoc = gql` @@ -6475,6 +6470,9 @@ export const TransferFragmentDoc = gql` to { ...LightAccount } + comment { + remark + } } ${LightAccountFragmentDoc}`; export const TransferConnectionFragmentDoc = gql` diff --git a/src/app/network/indexer/indexer.service.ts b/src/app/network/indexer/indexer.service.ts index 7d4a989a9b541eb4e38b0e2a2abc91a80119a53d..86b3af3fdcbb3b2d57a824c954890d05243077f3 100644 --- a/src/app/network/indexer/indexer.service.ts +++ b/src/app/network/indexer/indexer.service.ts @@ -41,6 +41,7 @@ import { import { AccountConverter } from '@app/account/account.converter'; import { CurrencyHistory, CurrencyHistoryFilter } from '@app/currency/currency-history.model'; import { CurrencyConverter } from '@app/currency/currency.converter'; +import { ApiPromise } from '@polkadot/api'; export interface IndexerState extends GraphqlServiceState { currency: Currency; @@ -50,14 +51,16 @@ export interface IndexerState extends GraphqlServiceState { @Injectable({ providedIn: 'root' }) export class IndexerService extends GraphqlService<IndexerState> { @RxStateSelect() currency$: Observable<Currency>; - @RxStateProperty() currency: Currency; - @RxStateSelect() minBlockHeight$: Observable<number>; + + @RxStateProperty() currency: Currency; @RxStateProperty() minBlockHeight: number; + api: ApiPromise; constructor( storage: StorageService, private settings: SettingsService, + // private networkService: NetworkService, private graphqlService: IndexerGraphqlService, @Optional() @Inject(APP_GRAPHQL_TYPE_POLICIES) typePolicies: TypePolicies, @Optional() @Inject(APP_GRAPHQL_FRAGMENTS) fragments: DocumentNode[] @@ -208,7 +211,14 @@ export class IndexerService extends GraphqlService<IndexerState> { const result: LoadResult<Transfer> = { data }; if (transferConnection.pageInfo.hasNextPage) { const after = transferConnection.pageInfo.endCursor; - result.fetchMore = (first) => firstValueFrom(this.transferSearch(filter, { ...options, after, first: toNumber(first, options.first) })); + result.fetchMore = (first) => + firstValueFrom( + this.transferSearch(filter, { + ...options, + after, + first: toNumber(first, options.first), + }) + ); } return result; }) diff --git a/src/app/network/network.service.ts b/src/app/network/network.service.ts index 9ec61953c6a724758617372bc89d82d615cf5a3c..dbc8f9f635fef3c4ee949542997989359c8f7166 100644 --- a/src/app/network/network.service.ts +++ b/src/app/network/network.service.ts @@ -179,10 +179,12 @@ export class NetworkService extends RxStartableService<NetworkState> { // Configure and start indexer and pod this.indexer.currency = currency; + this.indexer.api = api; this.pod.currency = currency; - await Promise.all([this.indexer.start(), this.pod.start()]).catch((err) => - console.error(`${this._logPrefix}Error starting indexer or pod:`, err) - ); + await Promise.all([ + this.indexer.start(), + //this.pod.start() + ]).catch((err) => console.error(`${this._logPrefix}Error starting indexer or pod:`, err)); return { api, @@ -377,7 +379,7 @@ export class NetworkService extends RxStartableService<NetworkState> { } protected extractTopicIdFromUrl(url: string) { - const idMatch = url.match(/\/(\d+)(?:$|\/)/); + const idMatch = url.match(/\/(\d+)(?:$|\/)/) || url.match(/\/(\d+)\.json$/); return idMatch ? parseInt(idMatch[1], 10) : null; } diff --git a/src/app/settings/settings.model.ts b/src/app/settings/settings.model.ts index 77f0a95827488c1479fbb0858825fc0233b22658..17fcc3b46bc2ceaa3305ef820a6bd1e93cc89750 100644 --- a/src/app/settings/settings.model.ts +++ b/src/app/settings/settings.model.ts @@ -38,4 +38,5 @@ export interface Settings { displayUnit: CurrencyDisplayUnit; selectedRedeemPeriod?: DurationConstructor; lastRedeemDate: Moment; + expertMode: boolean; } diff --git a/src/app/settings/settings.page.html b/src/app/settings/settings.page.html index 72fbe614d20bde4a23941df11a5b352fba290277..9a9f8ffcde9bbca8448530dac86f7d487ce7820e 100644 --- a/src/app/settings/settings.page.html +++ b/src/app/settings/settings.page.html @@ -40,15 +40,25 @@ <ion-item-divider translate>MENU.ACCOUNT</ion-item-divider> <ion-item> - <ion-icon slot="start" name="timer-outline"></ion-icon> - <ion-label translate>SETTINGS.DURATION_BETWEEN_UD_CLAIM</ion-label> - <ion-select [interface]="mobile ? 'action-sheet' : 'popover'" [(ngModel)]="selectedRedeemPeriod"> - @for (period of redeemPeriodOptions; track period.key) { - <ion-select-option [value]="period.key" translate>{{ period.i18nKey }}</ion-select-option> - } - </ion-select> + <ion-icon slot="start" name="build-outline"></ion-icon> + <ion-label translate>SETTINGS.EXPERT_MODE</ion-label> + <ion-toggle [(ngModel)]="expertMode"> + <ion-label color="medium" translate></ion-label> + </ion-toggle> </ion-item> + @if (expertMode) { + <ion-item> + <ion-icon slot="start" name="timer-outline"></ion-icon> + <ion-label translate>SETTINGS.DURATION_BETWEEN_UD_CLAIM</ion-label> + <ion-select [interface]="mobile ? 'action-sheet' : 'popover'" [(ngModel)]="selectedRedeemPeriod"> + @for (period of redeemPeriodOptions; track period.key) { + <ion-select-option [value]="period.key" translate>{{ period.i18nKey }}</ion-select-option> + } + </ion-select> + </ion-item> + } + <ion-item> <ion-toggle [(ngModel)]="useRelativeUnit" justify="end"> <ion-label color="medium" translate>COMMON.BTN_RELATIVE_UNIT</ion-label> diff --git a/src/app/settings/settings.page.ts b/src/app/settings/settings.page.ts index c30c63211637c073f8e422d4ce9dda7ad750ed90..bd0bfe3d75f338de78f0383d73cea341665192f8 100644 --- a/src/app/settings/settings.page.ts +++ b/src/app/settings/settings.page.ts @@ -58,15 +58,15 @@ export class SettingsPage extends AppPage<SettingsPageState> implements OnInit { redeemPeriodOptions: PeriodOption[] = [ { key: 'day', - i18nKey: 'SETTINGS.REDEEM_UD_PERIOD_OPTION.DAILY', + i18nKey: 'SETTINGS.CLAIM_UD_PERIOD_OPTION.DAILY', }, { key: 'week', - i18nKey: 'SETTINGS.REDEEM_UD_PERIOD_OPTION.WEEKLY', + i18nKey: 'SETTINGS.CLAIM_UD_PERIOD_OPTION.WEEKLY', }, { key: 'month', - i18nKey: 'SETTINGS.REDEEM_UD_PERIOD_OPTION.MONTHLY', + i18nKey: 'SETTINGS.CLAIM_UD_PERIOD_OPTION.MONTHLY', }, ]; @@ -91,8 +91,9 @@ export class SettingsPage extends AppPage<SettingsPageState> implements OnInit { @RxStateProperty() ipfsGateway: string; @RxStateProperty() unAuthDelayMs: number; @RxStateProperty() dirty: boolean; + @RxStateProperty() expertMode: boolean; @Input() @RxStateProperty() customPeer: string; - @Input() @RxStateProperty() selectedRedeemPeriod: DurationConstructor = 'week'; + @Input() @RxStateProperty() selectedRedeemPeriod: DurationConstructor = 'day'; @ViewChild('selectPeerModal') selectPeerModal: IonModal; @ViewChild('selectIndexerModal') selectIndexerModal: IonModal; @@ -112,7 +113,7 @@ export class SettingsPage extends AppPage<SettingsPageState> implements OnInit { // Detect changes this._state.hold( this._state - .select(['locale', 'peer', 'indexer', 'pod', 'ipfsGateway', 'unAuthDelayMs', 'displayUnit', 'selectedRedeemPeriod'], (s) => s) + .select(['locale', 'peer', 'indexer', 'pod', 'ipfsGateway', 'unAuthDelayMs', 'displayUnit', 'selectedRedeemPeriod', 'expertMode'], (s) => s) .pipe(skip(1)), () => { if (this.mobile) { diff --git a/src/app/settings/settings.service.ts b/src/app/settings/settings.service.ts index 094eba61eea1ed873eb35e51941b14bb43f995cf..576eacc97f6e5db4fe0578d07803618fa25b2154 100644 --- a/src/app/settings/settings.service.ts +++ b/src/app/settings/settings.service.ts @@ -85,9 +85,6 @@ export class SettingsService extends RxStartableService<SettingsState> { clone(): Settings { const data = this.get(); - // const conf = await this.storage.get(SETTINGS_STORAGE_KEY); - - // console.log('TODO storage', conf); return <Settings>{ locale: environment.defaultLocale, peer: environment.dev?.peer ?? environment.defaultPeers?.[0], diff --git a/src/app/shared/directives/directives.module.ts b/src/app/shared/directives/directives.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..afcb71aaf4b34450c6dc2b3761fd286aefbeeba3 --- /dev/null +++ b/src/app/shared/directives/directives.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { IonicModule } from '@ionic/angular'; +import { TranslatedHelpDirective } from '@app/shared/directives/translate-help.directive'; + +@NgModule({ + declarations: [TranslatedHelpDirective], + imports: [CommonModule, IonicModule, TranslateModule], + exports: [TranslatedHelpDirective], +}) +export class SharedDirectivesModule {} diff --git a/src/app/shared/directives/translate-help.directive.ts b/src/app/shared/directives/translate-help.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..31cefef5cbd4f1379fcba4155ebee2ff271f1802 --- /dev/null +++ b/src/app/shared/directives/translate-help.directive.ts @@ -0,0 +1,30 @@ +import { AfterContentInit, Directive, ElementRef, EventEmitter, Output } from '@angular/core'; + +@Directive({ + selector: '[translatedHelp]', +}) +export class TranslatedHelpDirective implements AfterContentInit { + @Output() helpRequest = new EventEmitter<string>(); + + constructor(private el: ElementRef) {} + + ngAfterContentInit() { + // setTimeout(() => this.setupLinks(), 1000); + setTimeout(() => this.setupLinks(), 100); + } + + private setupLinks() { + const element = this.el.nativeElement; + const helpLinks = element.querySelectorAll('a[data-help-topic]'); + helpLinks.forEach((link: HTMLElement) => { + link.style.cursor = 'pointer'; + link.addEventListener('click', (event: Event) => { + event.preventDefault(); + const topic = link.getAttribute('data-help-topic'); + if (topic) { + this.helpRequest.emit(topic); + } + }); + }); + } +} diff --git a/src/app/shared/pipes/pipes.module.ts b/src/app/shared/pipes/pipes.module.ts index d01a81efa2190535adb302f1e5bdf3f51400a744..6f39d5f2dbed16b36b2ef4181d9fdb69382a1f02 100644 --- a/src/app/shared/pipes/pipes.module.ts +++ b/src/app/shared/pipes/pipes.module.ts @@ -46,6 +46,7 @@ import { } from '@app/shared/pipes/account.pipes'; import { PubkeyFormatPipe } from '@app/shared/pipes/pubkey.pipes'; import { BlockNumberPipe } from '@app/shared/pipes/block-number.pipe'; +import { SafePipe } from '@app/shared/pipes/safe.pipe'; @NgModule({ declarations: [ @@ -102,6 +103,7 @@ import { BlockNumberPipe } from '@app/shared/pipes/block-number.pipe'; AccountAvatarPipe, IsMemberAccountPipe, IsUserAccountPipePipe, + SafePipe, ], imports: [CommonModule, IonicModule, TranslateModule], exports: [ @@ -159,6 +161,7 @@ import { BlockNumberPipe } from '@app/shared/pipes/block-number.pipe'; AccountAvatarPipe, IsMemberAccountPipe, IsUserAccountPipePipe, + SafePipe, ], }) export class SharedPipesModule {} diff --git a/src/app/shared/pipes/safe.pipe.ts b/src/app/shared/pipes/safe.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..9edae541bf251eeba0f088eaba600de3dcf89bda --- /dev/null +++ b/src/app/shared/pipes/safe.pipe.ts @@ -0,0 +1,14 @@ +import { Injectable, Pipe, PipeTransform } from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; + +@Pipe({ + name: 'safe', +}) +@Injectable({ providedIn: 'root' }) +export class SafePipe implements PipeTransform { + constructor(protected sanitizer: DomSanitizer) {} + + transform(value: string) { + return this.sanitizer.bypassSecurityTrustHtml(value); + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 925813ec720ad85bbe2df36b8e3063b00d3ff7c4..47697e36bdcdc34e63bd756cb29ed0630ab2f0f2 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -18,6 +18,7 @@ import { AppGraphQLModule } from '@app/shared/services/network/graphql/graphql.m import { RouterModule } from '@angular/router'; import { AppErrorItem } from '@app/shared/error/error-item.component'; import { AppWarningItem } from '@app/shared/error/warning-item.component'; +import { SharedDirectivesModule } from '@app/shared/directives/directives.module'; @NgModule({ imports: [ @@ -38,6 +39,7 @@ import { AppWarningItem } from '@app/shared/error/warning-item.component'; // Sub modules SharedPipesModule, + SharedDirectivesModule, ListPopoverModule, SwiperDirective, AppGraphQLModule, @@ -65,6 +67,7 @@ import { AppWarningItem } from '@app/shared/error/warning-item.component'; // Sub modules SharedPipesModule, + SharedDirectivesModule, ListPopoverModule, SwiperDirective, AppGraphQLModule, diff --git a/src/app/transfer/history/transfer-history.page.html b/src/app/transfer/history/transfer-history.page.html index 8a866e00eb5262f9410c37e310e5d88015de00f2..22d750202083fa1e09c1a7f0482dbdbf62113007 100644 --- a/src/app/transfer/history/transfer-history.page.html +++ b/src/app/transfer/history/transfer-history.page.html @@ -5,6 +5,14 @@ <ion-back-button></ion-back-button> </ion-buttons> <ion-title translate>WOT.OPERATIONS.TITLE</ion-title> + <!-- button refresh (desktop only) --> + @if (!mobile) { + <ion-buttons slot="end"> + <ion-button (click)="doRefresh()"> + <ion-icon name="refresh" slot="icon-only" /> + </ion-button> + </ion-buttons> + } </ion-toolbar> <ion-progress-bar type="indeterminate" *rxIf="loading$"></ion-progress-bar> </ion-header> @@ -13,17 +21,15 @@ <ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)" *ngIf="mobile"> <ion-refresher-content></ion-refresher-content> </ion-refresher> - <ion-header collapse="condense"> <ion-toolbar> <ion-title size="large" translate>WOT.OPERATIONS.TITLE</ion-title> </ion-toolbar> </ion-header> - <ion-header [translucent]="true"> <ion-item color="secondary" lines="none"> <ion-avatar slot="start" [style.background-color]="'white'"> - <app-account-image [account]="account$|push"></app-account-image> + <app-account-image [account]="account$ | push"></app-account-image> </ion-avatar> @if (account$ | push | isUserAccount) { @@ -53,7 +59,6 @@ </div> </ion-item> </ion-header> - <ion-list> <ion-item *rxIf="error$; let error" lines="none" color="light"> <ion-icon slot="start" name="alert-circle" color="danger"></ion-icon> @@ -71,44 +76,62 @@ <app-account-image [account]="item.account"></app-account-image> </ion-avatar> - <ion-label *rxLet="item.account | isMemberAccount; let isMember"> - <h3> - @if (item.account | isUserAccount) { - <a - [routerLink]="['/wallet', item.account.address]" - routerDirection="root" - class="tx-account" - (click)="$event.preventDefault()" - [class.member]="isMember" - > - <small> - <ion-icon [name]="item.account.meta?.uid ? 'person' : 'key'"></ion-icon> - </small> - {{ item.account | accountName }} - </a> - } @else { - <a - [routerLink]="['/wot', item.account.address]" - routerDirection="forward" - class="tx-account" - (click)="$event.preventDefault()" - [class.member]="isMember" - > - <small> - <ion-icon [name]="item.account.meta?.uid ? 'person' : 'key'"></ion-icon> - </small> - {{ item.account | accountName }} - </a> - } - </h3> - <p> - <a [routerLink]="['/block', item.blockNumber]" routerDirection="forward" (click)="$event.preventDefault()" class="tx-timestamp"> - {{ item.timestamp | dateFromNow }} | {{ item.timestamp | dateFormat }} - </a> - </p> - </ion-label> - - <ion-badge [color]="item.amount > 0 ? 'secondary' : 'light'" slot="end" [innerHtml]="item.amount | amountFormat"></ion-badge> + <ion-grid> + <ion-row> + <ion-col size="12" size-sm="3"> + <ion-label *rxLet="item.account | isMemberAccount; let isMember"> + <h3> + @if (item.account | isUserAccount) { + <a + [routerLink]="['/wallet', item.account.address]" + routerDirection="root" + class="tx-account" + (click)="$event.preventDefault()" + [class.member]="isMember" + > + <small> + <ion-icon [name]="item.account.meta?.uid ? 'person' : 'key'"></ion-icon> + </small> + {{ item.account | accountName }} + </a> + } @else { + <a + [routerLink]="['/wot', item.account.address]" + routerDirection="forward" + class="tx-account" + (click)="$event.preventDefault()" + [class.member]="isMember" + > + <small> + <ion-icon [name]="item.account.meta?.uid ? 'person' : 'key'"></ion-icon> + </small> + {{ item.account | accountName }} + </a> + } + </h3> + <p> + <a [routerLink]="['/block', item.blockNumber]" routerDirection="forward" (click)="$event.preventDefault()" class="tx-timestamp"> + {{ item.timestamp | dateFromNow }} | {{ item.timestamp | dateFormat }} + </a> + </p> + </ion-label> + </ion-col> + <ion-col size="12" size-sm="7"> + @if (item?.comment) { + <ion-label class="tx-comment"> + <p> + {{ item?.comment }} + </p> + </ion-label> + } + </ion-col> + <ion-col size="12" size-sm="2"> + <div> + <ion-badge slot="end" [color]="item.amount > 0 ? 'secondary' : 'light'" [innerHtml]="item.amount | amountFormat"></ion-badge> + </div> + </ion-col> + </ion-row> + </ion-grid> </ion-item> <!-- loading spinner --> @@ -155,8 +178,12 @@ <ion-item> <ion-icon slot="start" name="card"></ion-icon> <ion-label> - <h3><ion-skeleton-text animated style="width: 20%"></ion-skeleton-text></h3> - <p><ion-skeleton-text animated style="width: 50%"></ion-skeleton-text></p> + <h3> + <ion-skeleton-text animated style="width: 20%"></ion-skeleton-text> + </h3> + <p> + <ion-skeleton-text animated style="width: 50%"></ion-skeleton-text> + </p> </ion-label> </ion-item> </ng-template> diff --git a/src/app/transfer/history/transfer-history.page.scss b/src/app/transfer/history/transfer-history.page.scss index 40acdab0815ff8353202517c3f069460deff3437..61c24f48a5b3a99f64277155f5c43f79d9aa6b52 100644 --- a/src/app/transfer/history/transfer-history.page.scss +++ b/src/app/transfer/history/transfer-history.page.scss @@ -2,7 +2,7 @@ ion-toolbar { div[slot='end'], ion-buttons[slot='end'] { padding-inline-end: var(--ion-padding); - color: var(--ion-text-color, #000); + color: var(--ion-color-contrast); } } ion-list.list-md { @@ -28,3 +28,9 @@ ion-item { } } } + +.tx-comment{ + color: var(--ion-color-medium); + font-size: 12px; + font-style: italic; +} diff --git a/src/app/transfer/history/transfer-history.page.ts b/src/app/transfer/history/transfer-history.page.ts index f4e421c66e766de7f1b6d7ebe81a0774a0a182a6..097d147515cd5687a195e7dd93ecdd3a58a7d0ed 100644 --- a/src/app/transfer/history/transfer-history.page.ts +++ b/src/app/transfer/history/transfer-history.page.ts @@ -191,10 +191,11 @@ export class TransferHistoryPage extends AppPage<TransferHistoryPageState> imple try { this.markAsLoading(); - return this.indexerService.transferSearch(searchFilter, options).pipe( + const transfer = this.indexerService.transferSearch(searchFilter, options).pipe( filter(() => TransferSearchFilterUtils.isEquals(this.filter, searchFilter)), tap(() => this.markAsLoaded()) ); + return transfer; } catch (err) { this.setError(err); this.markAsLoaded(); diff --git a/src/app/transfer/send/transfer.page.ts b/src/app/transfer/send/transfer.page.ts index 202e73c2f97eb87efdec683f40b91be3f04ef5c9..00aa9d1db720f6f968a64dfa6fcf9cfc0ad63268 100644 --- a/src/app/transfer/send/transfer.page.ts +++ b/src/app/transfer/send/transfer.page.ts @@ -238,7 +238,7 @@ export class TransferPage extends AppPage<TransferPageState> implements Transfer this.resetError(); try { - const hash = await this.accountService.transfer(this.account, this.recipient, this.amount, this.comment); + const hash = await this.accountService.transfer(this.account, this.recipient, this.amount, this.comment?.trim()); if (this.showToastOnSubmit) { await this.showToast({ message: 'INFO.TRANSFER_SENT' }); @@ -277,7 +277,7 @@ export class TransferPage extends AppPage<TransferPageState> implements Transfer event.preventDefault(); const searchText = this.recipient?.address; - const data = await this.wotCtrl.select({ searchText, showItemActions: false, showFilterButtons: false }); + const data = await this.wotCtrl.select({ searchText, showItemActions: false, showFilterButtons: true }); if (!data) { console.debug('User cancelled'); @@ -307,8 +307,6 @@ export class TransferPage extends AppPage<TransferPageState> implements Transfer const result = await firstValueFrom(this.context.qrcode$.pipe(skip(1))); - console.info('[transfer] TODO: ' + result); - // if the result has content if (isNotNilOrBlank(result)) { // TODO check address format diff --git a/src/app/transfer/transfer.model.ts b/src/app/transfer/transfer.model.ts index b214e87da01c58fbb8f1992fc67055df1c26d463..6b47577ee3d6412f77b61e9287265af3b516bdde 100644 --- a/src/app/transfer/transfer.model.ts +++ b/src/app/transfer/transfer.model.ts @@ -34,6 +34,7 @@ export interface Transfer { timestamp: Moment; amount: number; blockNumber: number; + comment?: string; } export class TransferConverter { @@ -67,6 +68,7 @@ export class TransferConverter { amount, blockNumber: item.blockNumber, timestamp: fromDateISOString(item.timestamp), + comment: item.comment?.remark, }; } } diff --git a/src/app/wot/wot-details.page.html b/src/app/wot/wot-details.page.html index da9c01e57429f97f02bdead7a922d8a8f1cbe2f4..f6751ba0b16d13d285a08ea04726de27a7534e12 100644 --- a/src/app/wot/wot-details.page.html +++ b/src/app/wot/wot-details.page.html @@ -126,9 +126,11 @@ HELP.GLOSSARY.DISTANCE_RULE <ion-icon [color]="'tertiary'" name="help-circle-outline" class="tappable" (click)="showModalDistanceRuleDefinition()"></ion-icon> </ion-label> - <ion-badge title="{{ titleDistanceRule() }}" color="{{ distanceRuleValid() ? 'success' : 'danger' }}"> - {{ refereePercent$ | async | percent: '1.1' }} - </ion-badge> + @if (!disableDistanceRule()) { + <ion-badge title="{{ titleDistanceRule() }}" color="{{ distanceRuleValid() ? 'success' : 'danger' }}"> + {{ refereePercent$ | async | percent: '1.1' }} + </ion-badge> + } </ion-item> <!-- Received cert count --> <ion-item detail [routerLink]="['/wot', 'cert', account.address, account.meta?.uid || '', 'received']" routerDirection="forward"> diff --git a/src/app/wot/wot-details.page.ts b/src/app/wot/wot-details.page.ts index 5f5f2c22ca87889e5e3c7a112829443263de0c5a..6c360f17fb750b7b70a6860e0dd070dc281a610a 100644 --- a/src/app/wot/wot-details.page.ts +++ b/src/app/wot/wot-details.page.ts @@ -17,6 +17,7 @@ import { DistanceInformation, WotService } from '@app/wot/wot.service'; import { NetworkService } from '@app/network/network.service'; import { HelpPage } from '@app/home/help/help.page'; import { AlertController, ModalController } from '@ionic/angular'; +import { VerificationModal } from '@app/certification/verification/verification.modal'; export interface WotDetailsPageState extends AppPageState { address: string; @@ -29,15 +30,6 @@ export interface WotDetailsPageState extends AppPageState { isRenewal: boolean; canCertify: boolean; } -interface CertificationVerificationStep { - labelKey: string; - expectedResponse: 'confirm' | 'cancel'; - order: number; -} -interface ModalSequenceConfig { - title: string; - steps: CertificationVerificationStep[]; -} @Component({ selector: 'app-wot-details', @@ -67,58 +59,6 @@ export class WotDetailsPage extends AppPage<WotDetailsPageState> implements OnIn @RxStateProperty() isRenewal: boolean; @RxStateProperty() canCertify: boolean; - private readonly certificationSteps: CertificationVerificationStep[] = [ - { - labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.WELL_KNOWN', - order: 0, - expectedResponse: 'confirm', - }, - { - labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.REVOCATION', - order: 1, - expectedResponse: 'confirm', - }, - { - labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.CONTACT', - order: 2, - expectedResponse: 'confirm', - }, - { - labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.DOUBLE_IDENTITY', - order: 3, - expectedResponse: 'cancel', - }, - { - labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.MASTER_ACCOUNT', - order: 4, - expectedResponse: 'confirm', - }, - { - labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.LICENSE', - order: 5, - expectedResponse: 'confirm', - }, - { - labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.CREDENTIALS', - order: 6, - expectedResponse: 'confirm', - }, - { - labelKey: 'ACCOUNT.CERTIFICATION_MODAL.QUESTIONS.PUBLIC_KEY_DIFFERENT', - order: 7, - expectedResponse: 'cancel', - }, - { - labelKey: 'ACCOUNT.CERTIFICATION_MODAL.SHORT_LICENSE_REMINDER', - order: 8, - expectedResponse: 'confirm', - }, - ]; - private readonly certificationModalConfig: ModalSequenceConfig = { - title: 'ACCOUNT.CERTIFICATION_MODAL.CHECKLIST_TITLE', - steps: this.certificationSteps, - }; - constructor( private accountsService: AccountsService, private indexerService: IndexerService, @@ -228,7 +168,8 @@ export class WotDetailsPage extends AppPage<WotDetailsPageState> implements OnIn } async certifyTo() { - const issuer = await this.accountsService.selectAccount({ isMember: true }); + const accountsMember = this.accounts.filter((account) => account.meta.isMember === true); + const issuer = accountsMember.length === 1 ? accountsMember[0] : await this.accountsService.selectAccount({ isMember: true }); if (!issuer) { await this.showToast({ id: 'cert', @@ -297,53 +238,36 @@ export class WotDetailsPage extends AppPage<WotDetailsPageState> implements OnIn } private async showModalVerification(): Promise<boolean> { - let confirm = true; - console.log(`${this._logPrefix}prepare verification modal`); + const modal = await this.modalCtrl.create({ + id: 'help-modal', + component: VerificationModal, + presentingElement: this._presentingElement, + canDismiss: true, + }); + await modal.present(); + + const { data } = await modal.onDidDismiss(); - for (const step of this.certificationModalConfig.steps) { - const alert = await this.alertCtrl.create({ - header: this.translate.instant(this.certificationModalConfig.title), - message: this.translate.instant(step.labelKey), + if (data === undefined) { + return false; + } + if (data === false) { + const warning = await this.alertCtrl.create({ + header: this.translate.instant('ACCOUNT.CERTIFICATION_MODAL.REMINDER_TITLE'), + message: this.translate.instant('ACCOUNT.CERTIFICATION_MODAL.CHECKLIST_CONDITIONS_NOT_MET'), buttons: [ { - text: this.translate.instant('COMMON.BTN_NO'), - role: 'cancel', - cssClass: 'secondary', - }, - { - text: this.translate.instant('COMMON.BTN_YES'), + text: this.translate.instant('COMMON.BTN_OK'), role: 'confirm', cssClass: 'primary', }, ], }); - await alert.present(); - const { role } = await alert.onDidDismiss(); - - if (role !== step.expectedResponse) { - confirm = false; - const warning = await this.alertCtrl.create({ - header: this.translate.instant(this.certificationModalConfig.title), - message: this.translate.instant('ACCOUNT.CERTIFICATION_MODAL.CHECKLIST_CONDITIONS_NOT_MET'), - buttons: [ - { - text: this.translate.instant('COMMON.BTN_NO'), - role: 'cancel', - cssClass: 'secondary', - }, - { - text: this.translate.instant('COMMON.BTN_YES'), - role: 'confirm', - cssClass: 'primary', - }, - ], - }); - await warning.present(); - break; - } + await warning.present(); + return false; } - return confirm; + return true; } protected async enableCertify() { diff --git a/src/assets/i18n/ca.json b/src/assets/i18n/ca.json index db0eaeff0a98e86854ea449796c4b79320506020..46b201e10388c83de4b6f875a3a87cf0c7ca3553 100644 --- a/src/assets/i18n/ca.json +++ b/src/assets/i18n/ca.json @@ -175,7 +175,7 @@ "HOUR": "Després de {{value}}h d'inactivitat", "ALWAYS": "Al final de la sessió" }, - "REDEEM_UD_PERIOD_OPTION": { + "CLAIM_UD_PERIOD_OPTION": { "DAILY": "Cada dia", "WEEKLY": "Cada setmana", "MONTHLY": "Cada mes" @@ -262,7 +262,7 @@ "TAB_WOT": "Xarxa de confiança", "TAB_NETWORK": "Xarxa", "TAB_BLOCKS": "Blocs", - "CURRENCY_SHORT_DESCRIPTION": "{{currency}} es una <b>moneda lliure</b>, originada {{firstBlockTime|formatFromNow}}. Té actualmente <b>{{N}} membres</b>, que produeixen i reben un <a ng-click=\"showHelpModal('ud')\">Dividend Universal</a> (DU) cada {{dt|formatPeriod}}.", + "CURRENCY_SHORT_DESCRIPTION": "{{currency}} es una <b>moneda lliure</b>, originada {{firstBlockTime}}. Té actualmente <b>{{N}} membres</b>, que produeixen i reben un <a data-help-topic='UD' tappable>Dividend Universal</a> (DU) cada {{dt}}.", "NETWORK_RULES_DIVIDER": "Regles de la xarxa", "CURRENCY_NAME": "Nom de la moneda", "MEMBERS": "Quantitat de membres", @@ -685,6 +685,7 @@ "CERTIFICATION_MODAL": { "CHECKLIST_TITLE": "Llista de verificacions abans de la certificació", "INFOS": "La seguretat de la moneda Äž1 recau sobre cada membre. Abans de certificar la identitat d'aquesta persona, cal que realitzis algunes verificacions. Si us plau, respon a les següents preguntes:", + "REMINDER_TITLE": "Recordatori", "BTN_ALL_CHECK": "Certificar", "CHECKLIST_CONDITIONS_NOT_MET": "La certificació no s'ha enviat. Les verificacions semblen insuficients. Si us plau, verifica de nou cada punt amb la persona a certificar.", "QUESTIONS": { @@ -697,7 +698,7 @@ "CREDENTIALS": "L'identificador i la contrasenya del seu compte són <b>suficientment llargs i complexos</b>? Ha entès que tant la contrasenya com la frase secreta han de romandre secret? Està segur que en recordarà o que podrà trobar-los?", "PUBLIC_KEY_DIFFERENT": "La <b>clau pública</b> indicada ha de ser <b>idèntica</b> a la que aquesta persona t'ha donat. Les claus són <b>diferents</b>?" }, - "SHORT_LICENSE_REMINDER": "Pots recordar a la persona certificada els parà metres de les certificacions:<br/><br/><ul><li> - Cada membre pot emetre com a mà xim 100 certificacions và lides.</li><li> - Les certificacions es registren amb un interval de 5 dies.</li><li> - Una nova identitat de membre ha de reunir com a mÃnim 5 certificacions en menys de dos mesos.</li><li> - Un membre ha de renovar la seva afiliació cada any.</li><li> - Les certificacions són và lides durant dos anys.</li></ul>" + "SHORT_LICENSE_REMINDER": "Pots recordar a la persona certificada els parà metres de les certificacions:<br/><br/><ul><li>Cada membre pot emetre com a mà xim 100 certificacions và lides.</li><li>Les certificacions es registren amb un interval de 5 dies.</li><li>Una nova identitat de membre ha de reunir com a mÃnim 5 certificacions en menys de dos mesos.</li><li>Un membre ha de renovar la seva afiliació cada any.</li><li>Les certificacions són và lides durant dos anys.</li></ul>" } }, "TRANSFER": { diff --git a/src/assets/i18n/en-GB.json b/src/assets/i18n/en-GB.json index 47b2a8275bde18d76dd99ba41210db0a542aa31c..fa6c23db4d434e71786dcc88b1bee04f1472d8b1 100644 --- a/src/assets/i18n/en-GB.json +++ b/src/assets/i18n/en-GB.json @@ -172,7 +172,7 @@ "HOUR": "After {{value}}h of inactivity", "ALWAYS": "At the end of the session" }, - "REDEEM_UD_PERIOD_OPTION": { + "CLAIM_UD_PERIOD_OPTION": { "DAILY": "Every day", "WEEKLY": "Every week", "MONTHLY": "Every month" @@ -256,7 +256,7 @@ "TAB_WOT": "Web of trust", "TAB_NETWORK": "Network", "TAB_BLOCKS": "Blocks", - "CURRENCY_SHORT_DESCRIPTION": "{{currency|}} is a <b>libre money</b>, started {{firstBlockTime | formatFromNow}}. It currently counts <b>{{N}} members </b>, who produce and collect a <a ng-click=\"showHelpModal('ud')\">Universal Dividend</a> (DU), each {{dt | formatPeriod}}.", + "CURRENCY_SHORT_DESCRIPTION": "{{currency}} is a <b>libre money</b>, started {{firstBlockTime}}. It currently counts <b>{{N}} members </b>, who produce and collect a <a data-help-topic='UD' tappable>Universal Dividend</a> (DU), each {{dt}}.", "NETWORK_RULES_DIVIDER": "Network rules", "CURRENCY_NAME": "Currency name", "MEMBERS": "Members count", @@ -502,7 +502,7 @@ "EVENTS": "Events", "OUT_DISTANCED": "Your current certifications come from a group too isolated from the <a ng-click=\"showHelpModal('wot')\"> Web of Trust</a> (WoT): the <a ng-click=\"showHelpModal('distance_rule')\">maximum distance rule</a> is violated.<br/>You must obtain certifications from another area of the Web of Trust, or wait for it to tighten.", "WAITING_MEMBERSHIP": "Membership application sent. Waiting validation.", - "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member and produce the <a ng-click=\"showHelpModal('ud')\">Universal Dividend</a>. Your account is however already operational, to receive and send payments.", + "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member and produce the <a data-help-topic='UD' tappable>Universal Dividend</a>. Your account is however already operational, to receive and send payments.", "WAITING_CERTIFICATIONS_HELP": "To get your certifications, only request members <b>who know you enough</b>, as required by <a ng-click=\"showLicenseModal()\">the currency license</a> that you have accepted.<br/>If you do not know enough members, let them know on <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">the user forum</a>.", "WILL_MISSING_CERTIFICATIONS": "You will <b>lack certifications</b> soon (at least {{willNeedCertificationCount}} more are needed)", "WILL_NEED_RENEW_MEMBERSHIP": "Your membership <b>will expire {{membershipExpiresIn|formatDurationTo}}</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a> before then.", @@ -675,6 +675,7 @@ "INFOS": "Each member is responsible for the security of Äž1 currency. Before certifying this person's identity, you should have performed few checks. Please answer following questions:", "BTN_ALL_CHECK": "Certify", "CHECKLIST_CONDITIONS_NOT_MET": "The certification has not been sent. All answers are not right. Please recheck each point with the person to be certified.", + "REMINDER_TITLE": "Reminder", "QUESTIONS": { "WELL_KNOWN": "Do you know <b>well</b> the person you are about to certify? Do you know other people who also know this person well?", "REVOCATION": "Has this person downloaded their <b>revocation document</b> and do they know where to find it?", @@ -685,7 +686,7 @@ "CREDENTIALS": "Was the account created with <b>long and complex secret identifier and password</b> (ex. passphrases)? Did the person understand that both secret identifier and password must remain secret ? Are they <b>sure to remember them</b> or to be able to find them?", "PUBLIC_KEY_DIFFERENT": "The <b>public key</b> that is shown must be <b>identical</b> to the one the person gave you. The public keys are they <b>different</b>?" }, - "SHORT_LICENSE_REMINDER": "You may remind the person to certify different certification parameters:<br/><br/><ul><li> - Each member can certify 100 other identities at most.</li><li> - The certifications are saved with a 5 days interval.</li><li> - A new identity must gather at least 5 certifications in less than 2 months.</li><li>- A member must renew its membership at least once a year.</li><li> - Certifications have a lifespan of two years.</li></ul>" + "SHORT_LICENSE_REMINDER": "You may remind the person to certify different certification parameters:<br/><br/><ul><li>Each member can certify 100 other identities at most.</li><li>The certifications are saved with a 5 days interval.</li><li>A new identity must gather at least 5 certifications in less than 2 months.</li><li>- A member must renew its membership at least once a year.</li><li>Certifications have a lifespan of two years.</li></ul>" } }, "TRANSFER": { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 9fb124558c13d617982941c36d3f06664d40307c..da1577f482b82930cb6bb6f2ff70f974977890b0 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -173,7 +173,7 @@ "HOUR": "After {{value}}h of inactivity", "ALWAYS": "At the end of the session" }, - "REDEEM_UD_PERIOD_OPTION": { + "CLAIM_UD_PERIOD_OPTION": { "DAILY": "Every day", "WEEKLY": "Every week", "MONTHLY": "Every month" @@ -257,7 +257,7 @@ "TAB_WOT": "Web of trust", "TAB_NETWORK": "Network", "TAB_BLOCKS": "Blocks", - "CURRENCY_SHORT_DESCRIPTION": "{{currency|capitalize}} is a <b>libre money</b>, started {{firstBlockTime | formatFromNow}}. It currently counts <b>{{N}} members </b>, who produce and collect a <a ng-click=\"showHelpModal('ud')\">Universal Dividend</a> (DU), each {{dt | formatPeriod}}.", + "CURRENCY_SHORT_DESCRIPTION": "{{currency}} is a <b>libre money</b>, started {{firstBlockTime}}. It currently counts <b>{{N}} members </b>, who produce and collect a <a data-help-topic='UD' tappable>Universal Dividend</a> (DU), each {{dt}}.", "NETWORK_RULES_DIVIDER": "Network rules", "CURRENCY_NAME": "Currency name", "MEMBERS": "Members count", @@ -520,7 +520,7 @@ "EVENTS": "Events", "OUT_DISTANCED": "Your current certifications come from a group too isolated from the <a ng-click=\"showHelpModal('wot')\"> Web of Trust</a> (WoT): the <a ng-click=\"showHelpModal('distance_rule')\">maximum distance rule</a> is violated.<br/>You must obtain certifications from another area of the Web of Trust, or wait for it to tighten.", "WAITING_MEMBERSHIP": "Membership application sent. Waiting validation.", - "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member and produce the <a ng-click=\"showHelpModal('ud')\">Universal Dividend</a>. Your account is however already operational, to receive and send payments.", + "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member and produce the <a data-help-topic='UD' tappable>Universal Dividend</a>. Your account is however already operational, to receive and send payments.", "WAITING_CERTIFICATIONS_HELP": "To get your certifications, only request members <b>who know you enough</b>, as required by <a ng-click=\"showLicenseModal()\">the currency license</a> that you have accepted.<br/>If you do not know enough members, let them know on <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">the user forum</a>.", "WILL_MISSING_CERTIFICATIONS": "You will <b>lack certifications</b> soon (at least {{willNeedCertificationCount}} more are needed)", "WILL_NEED_RENEW_MEMBERSHIP": "Your membership <b>will expire {{membershipExpiresIn|formatDurationTo}}</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a> before then.", @@ -695,6 +695,7 @@ "INFOS": "Each member is responsible for the security of Äž1 currency. Before certifying this person's identity, you should have performed few checks. Please answer following questions:", "BTN_ALL_CHECK": "Certify", "CHECKLIST_CONDITIONS_NOT_MET": "The certification has not been sent. All answers are not right. Please recheck each point with the person to be certified.", + "REMINDER_TITLE": "Reminder", "QUESTIONS": { "WELL_KNOWN": "Do you know <b>well</b> the person you are about to certify? Do you know other people who also know this person well?", "REVOCATION": "Has this person downloaded their <b>revocation document</b> and do they know where to find it?", @@ -705,7 +706,7 @@ "CREDENTIALS": "Was the account created with <b>long and complex secret identifier and password</b> (ex. passphrases)? Did the person understand that both secret identifier and password must remain secret ? Are they <b>sure to remember them</b> or to be able to find them?", "PUBLIC_KEY_DIFFERENT": "The <b>public key</b> that is shown must be <b>identical</b> to the one the person gave you. The public keys are they <b>different</b>?" }, - "SHORT_LICENSE_REMINDER": "You may remind the person to certify different certification parameters:<br/><br/><ul><li> - Each member can certify 100 other identities at most.</li><li> - The certifications are saved with a 5 days interval.</li><li> - A new identity must gather at least 5 certifications in less than 2 months.</li><li>- A member must renew its membership at least once a year.</li><li> - Certifications have a lifespan of two years.</li></ul>" + "SHORT_LICENSE_REMINDER": "You may remind the person to certify different certification parameters:<br/><br/><ul><li>Each member can certify 100 other identities at most.</li><li>The certifications are saved with a 5 days interval.</li><li>A new identity must gather at least 5 certifications in less than 2 months.</li><li>- A member must renew its membership at least once a year.</li><li>Certifications have a lifespan of two years.</li></ul>" } }, "TRANSFER": { diff --git a/src/assets/i18n/eo-EO.json b/src/assets/i18n/eo-EO.json index 39c1d4572170a7a64130577026c1dea8d1ea1ebd..6c7118d4201e9e6b806046490ec40a7a6c96b906 100644 --- a/src/assets/i18n/eo-EO.json +++ b/src/assets/i18n/eo-EO.json @@ -171,7 +171,7 @@ "HOUR": "Post {{value}}h de neatktiveco", "ALWAYS": "Fine de la seanco" }, - "REDEEM_UD_PERIOD_OPTION": { + "CLAIM_UD_PERIOD_OPTION": { "DAILY": "Ĉiutage", "WEEKLY": "Ĉiusemajne", "MONTHLY": "Ĉiumonate" @@ -255,7 +255,7 @@ "TAB_WOT": "Reto de fido", "TAB_NETWORK": "Reto", "TAB_BLOCKS": "Blokoj", - "CURRENCY_SHORT_DESCRIPTION": "{{currency}} estas <b>libera mono</b>, kiu ekis {{firstBlockTime|formatFromNow}}. Äœi nombras nun <b>{{N}} membrojn</b>, kiuj produktas kaj ricevas <a ng-click=\"showHelpModal('ud')\">Universalan Dividendon</a> (UD), ĉiun {{dt|formatPeriod}}n.", + "CURRENCY_SHORT_DESCRIPTION": "{{currency}} estas <b>libera mono</b>, kiu ekis {{firstBlockTime}}. Äœi nombras nun <b>{{N}} membrojn</b>, kiuj produktas kaj ricevas <a data-help-topic='UD' tappable>Universalan Dividendon</a> (UD), ĉiun {{dt}}n.", "NETWORK_RULES_DIVIDER": "Reguloj de la reto", "CURRENCY_NAME": "Nomo de la mono", "MEMBERS": "Nombro de membroj", @@ -501,7 +501,7 @@ "EVENTS": "Okazaĵoj", "OUT_DISTANCED": "Viaj nunaj atestaĵoj venas de tro izolita grupo de la <a ng-click=\"showHelpModal('wot')\">Reto de Fido</a> (RdF): al la <a ng-click=\"showHelpModal('distance_rule')\">regulo de maksimuma distanco</a> vi ne konformiÄas.<br/>Vi devas akiri atestaĵojn venantajn de aliaj lokoj de la RdF, aÅ atendi ke tiu ĉi densiÄos.", "WAITING_MEMBERSHIP": "AliÄo-peto sendita. Atendanta akcepton.", - "WAITING_CERTIFICATIONS": "Vi devas <b>akiri {{needCertificationCount}} atestaĵo(j)n</b> por fariÄi membro kaj produkti la <a ng-click=\"showHelpModal('ud')\">Universalan Dividendon</a>. Via konto tamen estas jam funkcianta, por ricevi kaj efektivigi pagojn.", + "WAITING_CERTIFICATIONS": "Vi devas <b>akiri {{needCertificationCount}} atestaĵo(j)n</b> por fariÄi membro kaj produkti la <a data-help-topic='UD' tappable>Universalan Dividendon</a>. Via konto tamen estas jam funkcianta, por ricevi kaj efektivigi pagojn.", "WAITING_CERTIFICATIONS_HELP": "Por akiri viajn atestaĵojn, petu nur membrojn <b>kiuj sufiĉe konas vin</b>, kiel postulas <a ng-click=\"showLicenseModal()\">la licenco de la mono</a>, kiun vi akceptis.<br/>Se vi ne konas sufiĉe da membroj, sciigu tion ĉe <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">la forumo por uzantoj</a>.", "WILL_MISSING_CERTIFICATIONS": "BaldaÅ <b>mankos al vi atestaĵoj</b> (almenaÅ {{willNeedCertificationCount}} estas necesaj)", "WILL_NEED_RENEW_MEMBERSHIP": "Via aliÄo kiel membro <b>estas finiÄonta {{membershipExpiresIn|formatDurationTo}}</b>. Pensu <a ng-click=\"doQuickFix('renew')\">revalidigi vian aliÄon</a> Äis tiam.", @@ -674,6 +674,7 @@ "INFOS": "La sekureco de la monero Äž1 dependas de ĉiu membro. AntaÅ atesti la identon de tiu ĉi persono, vi devus fari kelkajn kontroladetojn. Bonvolu respondi la jenajn demandojn:", "BTN_ALL_CHECK": "Atesti", "CHECKLIST_CONDITIONS_NOT_MET": "La atesto ne estis sendita. La kontrolado Åajnas nesufiĉa. Bonvolu rekontroli ĉiun punkton kun la persono, kiun vi volas atesti.", + "REMINDER_TITLE": "Memorigo", "QUESTIONS": { "WELL_KNOWN": "<b>Ĉu vi bone konas</b> la personon, kiun vi volas atesti, kaj ĉu vi konas aliajn homojn, kiuj ankaÅ bone konas tiun personon?", "REVOCATION": "Ĉu tiu ĉi persono elÅutis sian <b>malkonfirmadon dokumenton</b> kaj ĉu Åi scias, kie trovi Äin?", @@ -684,7 +685,7 @@ "CREDENTIALS": "Ĉu la konto estis kreita kun <b>longa kaj kompleksa identigilo/pasvorto</b> (ekz. pasfrazoj)? Ĉu la persono komprenis, ke ambaÅ la identigilo kaj la pasvorto devas resti sekretaj? Ĉu Åi estas <b>certa, ke Åi memoros ilin</b> aÅ povos retrovi ilin?", "PUBLIC_KEY_DIFFERENT": "La montrata <b>publika Ålosilo</b> devas esti <b>identa</b> al tiu, kiun la persono donis al vi. Ĉu la publika Ålosiloj estas <b>malsamaj</b>?" }, - "SHORT_LICENSE_REMINDER": "Vi povas rememorigi al la atestota persono diversajn parametrojn pri atestoj:<br/><br/><ul><li> - Ĉiu membro povas atesti maksimume 100 aliajn identecojn.</li><li> - La atestoj estas konservataj kun intervolo de 5 tagoj.</li><li> - Nova membro devas kolekti minimume 5 atestojn en malpli ol 2 monatoj.</li><li> - Membro devas renovigi sian membrecon minimume unufoje jare.</li><li> - Atestoj estas validaj dum du jaroj.</li></ul>" + "SHORT_LICENSE_REMINDER": "Vi povas rememorigi al la atestota persono diversajn parametrojn pri atestoj:<br/><br/><ul><li>Ĉiu membro povas atesti maksimume 100 aliajn identecojn.</li><li>La atestoj estas konservataj kun intervolo de 5 tagoj.</li><li>Nova membro devas kolekti minimume 5 atestojn en malpli ol 2 monatoj.</li><li>Membro devas renovigi sian membrecon minimume unufoje jare.</li><li>Atestoj estas validaj dum du jaroj.</li></ul>" } }, "TRANSFER": { diff --git a/src/assets/i18n/es-ES.json b/src/assets/i18n/es-ES.json index a63293ee653804ff20856c21100098d34e63964e..8a5909c1699698f2ffc9559551b89a1e58dc2fc9 100644 --- a/src/assets/i18n/es-ES.json +++ b/src/assets/i18n/es-ES.json @@ -165,7 +165,7 @@ "HOUR": "Después de {{value}}h de inactividad", "ALWAYS": "Al finalizar la sesión" }, - "REDEEM_UD_PERIOD_OPTION": { + "CLAIM_UD_PERIOD_OPTION": { "DAILY": "Todos los dÃas", "WEEKLY": "Todas las semanas", "MONTHLY": "Todos los meses" @@ -250,7 +250,7 @@ "TAB_WOT": "Red de confianza", "TAB_NETWORK": "Red", "TAB_BLOCKS": "Bloques", - "CURRENCY_SHORT_DESCRIPTION": "{{currency}} es una <b>moneda libre</b>, originada {{firstBlockTime|formatFromNow}}. Cuenta actualmente con <b>{{N}} miembros</b>, que producen y reciben un <a ng-click=\"showHelpModal('ud')\">Dividendo Universal</a> (DU) cada {{dt|formatPeriod}}.", + "CURRENCY_SHORT_DESCRIPTION": "{{currency}} es una <b>moneda libre</b>, originada {{firstBlockTime}}. Cuenta actualmente con <b>{{N}} miembros</b>, que producen y reciben un <a data-help-topic='UD' tappable>Dividendo Universal</a> (DU) cada {{dt}}.", "NETWORK_RULES_DIVIDER": "Reglas de la red", "CURRENCY_NAME": "Nombre de la moneda", "MEMBERS": "Cantidad de miembros", @@ -767,6 +767,7 @@ "INFOS": "La seguridad de la moneda Äž1 depende de cada miembro. Antes de certificar la identidad de este ser humano, debes realizar algunas verificaciones. Por favor, responde a las siguientes preguntas:", "BTN_ALL_CHECK": "Certificar", "CHECKLIST_CONDITIONS_NOT_MET": "La certificación no se ha enviado. Las verificaciones parecen insuficientes. Por favor, verifica nuevamente cada punto con la persona a certificar.", + "REMINDER_TITLE": "Recordatorio", "QUESTIONS": { "WELL_KNOWN": "<b>¿Conoces bien</b> al ser humano que vas a certificar y conoces a otras personas que también lo conocen bien?", "REVOCATION": "¿Ha descargado su <b>documento de revocación</b> y sabe dónde encontrarlo?", @@ -777,7 +778,7 @@ "CREDENTIALS": "¿Las credenciales de su cuenta, como el identificador y la contraseña, son suficientemente <b>largas y complejas</b>? ¿Ha comprendido que tanto la frase secreta como la contraseña deben mantenerse en secreto? ¿Está segura de recordarlos o de poder encontrarlos?", "PUBLIC_KEY_DIFFERENT": "La <b>clave pública</b> indicada debe ser <b>idéntica</b> a la que esta persona te ha proporcionado. ¿Son <b>diferentes</b> las claves?" }, - "SHORT_LICENSE_REMINDER": "Puedes recordarle a la persona certificada los parámetros de las certificaciones:<br/><br/><ul><li> - Cada miembro puede emitir un máximo de 100 certificaciones válidas.</li><li> - Las certificaciones se registran con un intervalo de 5 dÃas.</li><li> - Una nueva identidad de miembro debe reunir al menos 5 certificaciones en menos de dos meses.</li><li> - Un miembro debe renovar su membresÃa cada año.</li><li> - Las certificaciones son válidas durante dos años.</li></ul>" + "SHORT_LICENSE_REMINDER": "Puedes recordarle a la persona certificada los parámetros de las certificaciones:<br/><br/><ul><li>Cada miembro puede emitir un máximo de 100 certificaciones válidas.</li><li>Las certificaciones se registran con un intervalo de 5 dÃas.</li><li>Una nueva identidad de miembro debe reunir al menos 5 certificaciones en menos de dos meses.</li><li>Un miembro debe renovar su membresÃa cada año.</li><li>Las certificaciones son válidas durante dos años.</li></ul>" } }, "TRANSFER": { diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 8dcf339e7a9275094c213e35acfeaaccbd652f0b..31d511d4a08ed98d219ef3d4499bf08e407b136e 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -178,7 +178,7 @@ "HOUR": "Après {{value}}h d'inactivité", "ALWAYS": "A la fin de la session" }, - "REDEEM_UD_PERIOD_OPTION": { + "CLAIM_UD_PERIOD_OPTION": { "DAILY": "Tous les jours", "WEEKLY": "Toutes les semaines", "MONTHLY": "Tous les mois" @@ -266,7 +266,7 @@ "TAB_WOT": "Toile de confiance", "TAB_NETWORK": "Réseau", "TAB_BLOCKS": "Blocs", - "CURRENCY_SHORT_DESCRIPTION": "{{currency}} est une <b>monnaie libre</b>, démarrée {{firstBlockTime}}. Elle compte actuellement <b>{{N}} membres</b>, qui produisent et perçoivent un <a class='open-modal' (click)='onDividendeClick()' style='cursor: pointer;'>Dividende Universel</a> (DU), chaque {{dt}}.", + "CURRENCY_SHORT_DESCRIPTION": "{{currency}} est une <b>monnaie libre</b>, démarrée {{firstBlockTime}}. Elle compte actuellement <b>{{N}} membres</b>, qui produisent et perçoivent un <a data-help-topic='UD' tappable>Dividende Universel</a> (DU), chaque {{dt}}.", "NETWORK_RULES_DIVIDER": "Règles du réseau", "CURRENCY_NAME": "Nom de la monnaie", "MEMBERS": "Nombre de membres", @@ -533,7 +533,7 @@ "EVENTS": "Evénements", "OUT_DISTANCED": "Vos certifications actuelles proviennent d'un groupe trop isolé de la <a ng-click=\"showHelpModal('wot')\">Toile de Confiance</a> (TdC) : la <a ng-click=\"showHelpModal('distance_rule')\">règle de distance maximale</a> n'est pas respectée.<br/>Vous devez obtenir des certifications provenant d'autres secteurs de la TdC, ou bien attendre que celle-ci se resserre.", "WAITING_MEMBERSHIP": "Demande d'adhésion envoyée. En attente d'acceptation.", - "WAITING_CERTIFICATIONS": "Vous devez <b>obtenir {{needCertificationCount}} certification(s)</b> pour devenir membre et produire le <a ng-click=\"showHelpModal('ud')\">Dividende Universel</a>. Votre compte est cependant déjà opérationnel, pour recevoir et effectuer des paiements.", + "WAITING_CERTIFICATIONS": "Vous devez <b>obtenir {{needCertificationCount}} certification(s)</b> pour devenir membre et produire le <a data-help-topic='UD' tappable>Dividende Universel</a>. Votre compte est cependant déjà opérationnel, pour recevoir et effectuer des paiements.", "WAITING_CERTIFICATIONS_HELP": "Pour obtenir vos certifications, sollicitez uniquement des membres <b>qui vous connaissent suffisamment</b>, comme l'exige <a ng-click=\"showLicenseModal()\">la licence de la monnaie</a> que vous avez acceptée.<br/>Si vous ne connaissez pas (encore) suffisamment de membres, allez aux rencontres ou proposez en sur <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">le forum utilisateur</a>.", "WILL_MISSING_CERTIFICATIONS": "Vous allez bientôt <b>manquer de certifications</b> (au moins {{willNeedCertificationCount}} sont requises)", "WILL_NEED_RENEW_MEMBERSHIP": "Votre adhésion comme membre <b>va expirer {{membershipExpiresIn|formatDurationTo}}</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a> d'ici là .", @@ -712,6 +712,7 @@ "CERTIFICATION_MODAL": { "CHECKLIST_TITLE": "Vérifications avant certification", "INFOS": "La sécurité de la monnaie Äž1 repose sur chaque membre. Avant de certifier l'identité de cette personne, vous devez avoir fait quelques vérifications à son propos. Veuillez répondre aux questions suivantes :", + "REMINDER_TITLE": "Rappel", "CHECKLIST_CONDITIONS_NOT_MET": "La certification n'a pas été envoyée. Les vérifications semblent insuffisantes. Veuillez vérifier de nouveau chaque point auprès de la personne à certifier.", "QUESTIONS": { "WELL_KNOWN": "<b>Connaissez-vous bien</b> la personne que vous certifiez, et connaissez-vous des gens qui la connaissent bien également ?", @@ -723,7 +724,7 @@ "CREDENTIALS": "L’identifiant secret et le mot de passe de son compte sont-ils <b>longs et complexes</b> (phrases de passe) ? A-t-elle compris que l’identifiant doit également rester secret ? Est-elle <b>certaine de s’en souvenir</b> ou de pouvoir les retrouver ?", "PUBLIC_KEY_DIFFERENT": "La <b>clef publique</b> indiquée doit être <b>identique</b> à celle que vous a communiqué cette personne. Les clefs sont-elles <b>différentes</b> ?" }, - "SHORT_LICENSE_REMINDER": "Vous pouvez rappeler à la personne certifiée les paramètres des certifications :<br/><br/><ul><li> - Chaque membre peut avoir émis 100 certifications valides au maximum.</li><li> - Les certifications sont enregistrées à un intervalle de 5 jours.</li><li> - Une nouvelle identité membre doit réunir au minimum 5 certifications en moins de deux mois.</li><li> - Un membre doit renouveler son adhésion chaque année.</li><li> - Les certifications sont valides durant deux ans.</li></ul>" + "SHORT_LICENSE_REMINDER": "Vous pouvez rappeler à la personne certifiée les paramètres des certifications :<br/><br/><ul><li> Chaque membre peut avoir émis 100 certifications valides au maximum.</li><li> Les certifications sont enregistrées à un intervalle de 5 jours.</li><li> Une nouvelle identité membre doit réunir au minimum 5 certifications en moins de deux mois.</li><li>Un membre doit renouveler son adhésion chaque année.</li><li>Les certifications sont valides durant deux ans.</li></ul>" } }, "TRANSFER": { diff --git a/src/assets/i18n/it-IT.json b/src/assets/i18n/it-IT.json index f534666d71fbc99323d27a3fd33366213ec69728..651722526ca42216f2ce916fb684e7c472a876bf 100644 --- a/src/assets/i18n/it-IT.json +++ b/src/assets/i18n/it-IT.json @@ -161,7 +161,7 @@ "HOUR": "Dopo {{value}}h d'inattività ", "ALWAYS": "Alla fine della sessione" }, - "REDEEM_UD_PERIOD_OPTION": { + "CLAIM_UD_PERIOD_OPTION": { "DAILY": "Ogni giorno", "WEEKLY": "Ogni settimana", "MONTHLY": "Ogni mese" @@ -236,7 +236,7 @@ "TAB_WOT": "Rete di Fiducia", "TAB_NETWORK": "Rete", "TAB_BLOCKS": "Blocchi", - "CURRENCY_SHORT_DESCRIPTION": "{{currency|capitalize}} è <b>una moneta libera</b>, {{firstBlockTime | formatFromNow}}. La rete comprende <b>{{N}} membri </b>, che produccono e ricevono un <a ng-click=\"showHelpModal('ud')\">Dividendo Universale</a> (DU), ogni {{dt | formatPeriod}}.", + "CURRENCY_SHORT_DESCRIPTION": "{{currency}} è <b>una moneta libera</b>, {{firstBlockTime}}. La rete comprende <b>{{N}} membri </b>, che produccono e ricevono un <a data-help-topic='UD' tappable>Dividendo Universale</a> (DU), ogni {{dt}}.", "NETWORK_RULES_DIVIDER": "Regole della rete", "CURRENCY_NAME": "Nome della moneta", "MEMBERS": "Numero di membri", @@ -617,6 +617,7 @@ "INFOS": "La sicurezza della valuta Äž1 dipende da ogni membro. Prima di certificare l'identità di questa persona, è necessario effettuare alcuni controlli. Si prega di rispondere alle seguenti domande:", "BTN_ALL_CHECK": "Certifica", "CHECKLIST_CONDITIONS_NOT_MET": "La certificazione non è stata inviata. I controlli sembrano insufficienti. Si prega di verificare nuovamente ogni punto con la persona che si desidera certificare.", + "REMINDER_TITLE": "Promemoria", "QUESTIONS": { "WELL_KNOWN": "<b>Conosci bene</b> la persona che stai per certificare e conosci altre persone che la conoscono bene?", "REVOCATION": "Ha scaricato il suo <b>documento di revoca</b> e sa dove trovarlo?", @@ -627,7 +628,7 @@ "CREDENTIALS": "L'account è stato creato con un <b>ID/password lungo e complesso</b> (frasi segrete)? La persona ha compreso che sia l'ID che la password devono rimanere segreti? È sicura di ricordarli o di poterli recuperare?", "PUBLIC_KEY_DIFFERENT": "La <b>chiave pubblica</b> mostrata deve essere <b>identica</b> a quella che la persona ti ha comunicato. Le chiavi pubbliche sono <b>diverse</b>?" }, - "SHORT_LICENSE_REMINDER": "Puoi ricordare alla persona da certificare i parametri delle certificazioni:<br/><br/><ul><li> - Ogni membro può certificare al massimo 100 identità .</li><li> - Le certificazioni vengono registrate con un intervallo di 5 giorni.</li><li> - Una nuova identità deve raccogliere almeno 5 certificazioni in meno di 2 mesi.</li><li> - Un membro deve rinnovare la sua adesione almeno una volta all'anno.</li><li> - Le certificazioni sono valide per due anni.</li></ul>" + "SHORT_LICENSE_REMINDER": "Puoi ricordare alla persona da certificare i parametri delle certificazioni:<br/><br/><ul><li>Ogni membro può certificare al massimo 100 identità .</li><li>Le certificazioni vengono registrate con un intervallo di 5 giorni.</li><li>Una nuova identità deve raccogliere almeno 5 certificazioni in meno di 2 mesi.</li><li>Un membro deve rinnovare la sua adesione almeno una volta all'anno.</li><li>Le certificazioni sono valide per due anni.</li></ul>" } }, "TRANSFER": { diff --git a/src/assets/i18n/nl-NL.json b/src/assets/i18n/nl-NL.json index 861bee0aedb01ba68abb4ef41b34d676d40ad7f9..e125e6440d054cccfa9e13a9601bb39bcf93170e 100644 --- a/src/assets/i18n/nl-NL.json +++ b/src/assets/i18n/nl-NL.json @@ -150,7 +150,7 @@ "HOUR": "Na {{value}}u inactiviteit", "ALWAYS": "Aan het einde van de sessie" }, - "REDEEM_UD_PERIOD_OPTION": { + "CLAIM_UD_PERIOD_OPTION": { "DAILY": "Elke dag", "WEEKLY": "Elke week", "MONTHLY": "Elke maand" @@ -215,6 +215,7 @@ "TAB_CURRENCY": "Valuta", "TAB_WOT": "Gemeenschap", "TAB_NETWORK": "Netwerk", + "CURRENCY_SHORT_DESCRIPTION": "{{currency}} is een <b>vrije munt</b>, gestart op {{firstBlockTime}}. Het heeft momenteel <b>{{N}} leden</b>, die elke {{dt}} een <a data-help-topic='UD' tappable>Universeel Dividend</a> (UD) produceren en ontvangen.", "CURRENCY_NAME": "Valuta naam", "MEMBERS": "Ledental", "MEMBERS_VARIATION": "Variatie since {{duration | formatDuration}}", @@ -423,6 +424,7 @@ "INFOS": "De veiligheid van de munteenheid Äž1 is gebaseerd op elk lid. Voordat je de identiteit van deze persoon certificeert, moet je enkele controles over haar hebben uitgevoerd. Beantwoord de volgende vragen:", "BTN_ALL_CHECK": "Certificeren", "CHECKLIST_CONDITIONS_NOT_MET": "De certificering is niet verzonden. De controles lijken onvoldoende. Controleer elk punt opnieuw bij de persoon die moet worden gecertificeerd.", + "REMINDER_TITLE": "Herinnering", "QUESTIONS": { "WELL_KNOWN": "<b>Ken je</b> de persoon die je certificeert goed, en ken je ook mensen die haar goed kennen?", "REVOCATION": "Heeft ze haar <b>herroepingsdocument</b> gedownload en weet ze waar ze het kan vinden?", @@ -433,7 +435,7 @@ "CREDENTIALS": "Zijn de geheime identificatie en het wachtwoord van haar rekening <b>lang en complex</b> (wachtwoordzinnen)? Heeft ze begrepen dat de identificatie ook geheim moet blijven? Is ze er <b>zeker van dat ze deze zal onthouden</b> of terugvinden?", "PUBLIC_KEY_DIFFERENT": "De <b>openbare sleutel</b> moet <b>identiek</b> zijn aan die welke deze persoon je heeft meegedeeld. Zijn de sleutels <b>verschillend</b>?" }, - "SHORT_LICENSE_REMINDER": "Je kunt de persoon eraan herinneren verschillende certificeringsparameters te certificeren:<br/><br/><ul><li> - Elk lid kan maximaal 100 andere identiteiten certificeren.</li><li> - De certificeringen worden met een interval van 5 dagen opgeslagen.</li><li> - Een nieuwe identiteit moet in minder dan 2 maanden minstens 5 certificeringen verzamelen.</li><li> - Een lid moet minstens eenmaal per jaar zijn lidmaatschap vernieuwen.</li><li> - Certificeringen hebben een levensduur van twee jaar.</li></ul>" + "SHORT_LICENSE_REMINDER": "Je kunt de persoon eraan herinneren verschillende certificeringsparameters te certificeren:<br/><br/><ul><li>Elk lid kan maximaal 100 andere identiteiten certificeren.</li><li>De certificeringen worden met een interval van 5 dagen opgeslagen.</li><li>Een nieuwe identiteit moet in minder dan 2 maanden minstens 5 certificeringen verzamelen.</li><li>Een lid moet minstens eenmaal per jaar zijn lidmaatschap vernieuwen.</li><li>Certificeringen hebben een levensduur van twee jaar.</li></ul>" } }, "TRANSFER": { diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 1cbbe7fd61f4f8767ed488626e94fec8773ac8f3..b8a906d4b00bf5e6c9108517c562d9f21f4686b6 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -16,7 +16,7 @@ export const environment = <Environment>{ officialUrl: 'https://www.cesium.app', sourceUrl: 'https://git.duniter.org/clients/cesium-grp/cesium', reportIssueUrl: 'https://git.duniter.org/clients/cesium-grp/cesium/-/issues/new', - forumUrl: 'https://git.duniter.org/', + forumUrl: 'https://forum.monnaie-libre.fr', graphql: { fetchPolicy: 'cache-first', @@ -30,7 +30,12 @@ export const environment = <Environment>{ name: 'cesium2', driverOrder: [StorageDrivers.IndexedDB, StorageDrivers.WebSQL, StorageDrivers.LocalStorage], }, - + feed: { + jsonFeed: new Map<string, string[]>([['fr', ['https://forum.monnaie-libre.fr/t/actu-generale-la-1-bouge/31318.json']]]), + maxContentLength: 1300, + maxAgeInMonths: 3, + maxCount: 1, + }, defaultPeers: [ /* Local endpoint */ //'ws://127.0.0.1:9944', diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 77f12849b6ca92d883b936b354260706d275e14a..a08e292f4037bbe08546c2bc0b3cb244e0006382 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -17,7 +17,7 @@ export const environment = <Environment>{ // About sourceUrl: 'https://git.duniter.org/clients/cesium-grp/cesium', reportIssueUrl: 'https://git.duniter.org/clients/cesium-grp/cesium/-/issues/new', - forumUrl: 'https://forum.duniter.org/', + forumUrl: 'https://forum.monnaie-libre.fr', officialUrl: 'https://www.cesium.app', graphql: { @@ -38,22 +38,10 @@ export const environment = <Environment>{ }, feed: { - jsonFeed: new Map<string, string[]>([ - ['en', ['https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/1.1/feed-en.json']], - ['en-GB', ['https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/1.1/feed-en-GB.json']], - ['eo-EO', ['https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/1.1/feed-eo-EO.json']], - // ['fr', ['https://forum.duniter.org/t/nouvelle-version-1-7-9-de-cesium/11458/2.json']], - // ['fr', ['https://forum.duniter.org/c/clients/cesium/22']], - ['fr', ['https://forum.duniter.org/c/clients/cesium/22', 'https://forum.duniter.org/t/nouvelle-version-1-7-9-de-cesium/11458/2.json']], - ['nl-Nl', ['https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/1.1/feed-nl-NL.json']], - ['es-ES', ['https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/1.1/feed-es-ES.json']], - ['ca', ['https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/1.1/feed-ca.json']], - ['it-IT', ['https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/1.1/feed-it-IT.json']], - ]), + jsonFeed: new Map<string, string[]>([['fr', ['https://forum.monnaie-libre.fr/t/actu-generale-la-1-bouge/31318.json']]]), maxContentLength: 1300, - // maxAgeInMonths: 1, - maxAgeInMonths: 120, - maxCount: 3, + maxAgeInMonths: 3, + maxCount: 1, }, dev: { diff --git a/src/theme/_ionic.globals.scss b/src/theme/_ionic.globals.scss index 664c0e4f137bf79e769cb468501dc4ca42d410fe..ae8e6af18b67815ed22526dc0cdd8f68c81c6c85 100644 --- a/src/theme/_ionic.globals.scss +++ b/src/theme/_ionic.globals.scss @@ -63,7 +63,7 @@ $dark-disabled-text: rgba(black, 0.38); $light-primary-text: white; $light-secondary-text: rgba(white, 0.7); $light-disabled-text: rgba(white, 0.5); -$text-color: rgba(black, 1); +$text-color: rgba(black, 0.87); // Default General Colors // --------------------------------------------------