BACKLOG-28: To GitHub Actions (#1)

This commit is contained in:
Rinat Arsaev 2022-01-11 20:07:27 +03:00 committed by GitHub
parent fc6dab6c0a
commit 5707146118
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
102 changed files with 2726 additions and 3643 deletions

View File

@ -1,18 +1,28 @@
const rules = require('@rbkmoney/eslint-plugin/lib/rules');
const rules = require('./tools/eslint-config/rules');
const baseTsRules = {
...rules.createImportOrderRule({
internalPathsPattern: '@cc/**',
}),
// TODO: pretenders for error
'@typescript-eslint/no-unsafe-call': 'warn',
'@typescript-eslint/no-unsafe-member-access': 'warn',
'@typescript-eslint/no-unsafe-assignment': 'warn',
'@typescript-eslint/no-unsafe-return': 'warn',
'@typescript-eslint/no-misused-promises': 'warn',
'@typescript-eslint/unbound-method': 'warn',
'@typescript-eslint/restrict-plus-operands': 'warn',
'@typescript-eslint/restrict-template-expressions': 'warn',
parserOptions: {
project: ['tsconfig.json'],
createDefaultProgram: true,
},
extends: [
'./tools/eslint-config/typescript',
'./tools/eslint-config/angular',
'./tools/eslint-config/lodash',
'prettier',
],
rules: {
...rules.createImportOrderRule({ internalPathsPattern: '@cc/**' }),
// TODO: pretenders for error
'@typescript-eslint/no-unsafe-call': 'warn',
'@typescript-eslint/no-unsafe-member-access': 'warn',
'@typescript-eslint/no-unsafe-assignment': 'warn',
'@typescript-eslint/no-unsafe-return': 'warn',
'@typescript-eslint/no-misused-promises': 'warn',
'@typescript-eslint/unbound-method': 'warn',
'@typescript-eslint/restrict-plus-operands': 'warn',
'@typescript-eslint/restrict-template-expressions': 'warn',
},
};
module.exports = {
@ -21,38 +31,19 @@ module.exports = {
ignorePatterns: ['**/gen-*/**/*'],
overrides: [
{
...baseTsRules,
files: ['*.ts'],
parserOptions: {
project: ['tsconfig.json', 'e2e/tsconfig.json'],
createDefaultProgram: true,
},
extends: [
'plugin:@rbkmoney/typescript',
'plugin:@rbkmoney/angular',
'plugin:@rbkmoney/lodash',
'plugin:@rbkmoney/prettier',
],
rules: {
...baseTsRules,
...baseTsRules.rules,
...rules.createAngularSelectorRules({ prefix: 'cc' }),
// TODO: pretenders for error
'@typescript-eslint/no-floating-promises': 'warn',
},
},
{
...baseTsRules,
files: ['*.spec.ts'],
parserOptions: {
project: ['tsconfig.json', 'e2e/tsconfig.json'],
createDefaultProgram: true,
},
extends: [
'plugin:@rbkmoney/typescript',
'plugin:@rbkmoney/angular',
'plugin:@rbkmoney/jasmine',
'plugin:@rbkmoney/lodash',
'plugin:@rbkmoney/prettier',
],
rules: baseTsRules,
extends: [...baseTsRules.extends, './tools/eslint-config/jasmine'],
},
{
files: ['*.html'],

View File

@ -1,71 +0,0 @@
<!--
Название ветки:
fr-0/<name>
(fr-0/bump-angular-to-12)
Название PR'a:
FR-0: <НАЗВАНИЕ>
FR-0,FR-1: <ОБЩЕЕ НАЗВАНИЕ> или <НАЗВАНИЕ 1>; <НАЗВАНИЕ 2>
-->
## ⛵ JIRA
- [ ] [FR-0](https://rbkmoney.atlassian.net/browse/FR-0)
## 📑 Изменения
```
✍️(^◡^)
```
### 📦 Новые NPM пакеты
- [ ] Добавлены новые NPM пакеты
<!-- Описание NPM пакета и возможно стоит добавить в Guidelin'ы
- [NPM](https://www.npmjs.com/)
-->
### 📚 Обновлен Guideline
- [ ] Добавлено описание в [wiki](https://github.com/rbkmoney/dashboard/wiki)
<!-- Ссылка и возможно коротко об изменениях
- [Wiki](https://github.com/rbkmoney/dashboard/wiki)
-->
## 🖥️ Изменения в интерфейсе
- [ ] Да
- [ ] Выглядит отлично на мобильных устройствах
### 🔗 Страницы с изменениями либо как их воспроизвести
- http://localhost:7000/
### 🖼 Скриншоты
<!--
<details>
<summary>Скриншоты</summary>
</details>
-->
<!--
- На измененные поля нужно ставить "x", для понимания что это было отредактировано.
JIRA:
- Если несколько, то нужно добавить каждый
Описание изменений:
- Например: Обновление Angular до 12 версии
Страницы с изменениями:
- Например: http://localhost:8000/invoices или диалог на http://localhost:8000/payments
Скриншоты:
- Можно просто скопировать и вставить изображение (CTRL-V)
- Шаблон для изображения: ![Название](URL)
- Если есть скриншоты которые занимаю много места, то их нужно вложить в details
-->

32
.github/workflows/build-push.yaml vendored Normal file
View File

@ -0,0 +1,32 @@
name: Build
on:
push:
branches: [master]
pull_request:
branches: ["*"]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Init Thrift
uses: valitydev/action-setup-thrift@v0.0.1
- name: Init NodeJS
uses: actions/setup-node@v2
with:
node-version: '16.4.2'
cache: 'npm'
- name: Install Packages
run: npm ci
- name: Compile Thrift
run: npm run compile
- name: Check & Build
run: npm run ci:build

View File

@ -2,6 +2,7 @@ name: 'PR Title Checker'
on:
pull_request:
types: [edited, opened, synchronize, reopened]
branches: [disabled]
jobs:
title-check:

2
.npmrc
View File

@ -1 +1 @@
@rbkmoney:registry=https://npm.pkg.github.com/
engine-strict=true

View File

@ -1,23 +0,0 @@
#!/bin/bash
cat <<EOF
FROM $BASE_IMAGE
MAINTAINER Ildar Galeev <i.galeev@rbkmoney.com>
COPY dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/vhosts.d/control-center.conf
EXPOSE 8080
LABEL base_image_tag=$BASE_IMAGE_TAG
LABEL build_image_tag=$BUILD_IMAGE_TAG
# A bit of magic to get a proper branch name
# even when the HEAD is detached (Hey Jenkins!
# BRANCH_NAME is available in Jenkins env).
LABEL branch=$( \
if [ "HEAD" != $(git rev-parse --abbrev-ref HEAD) ]; then \
echo $(git rev-parse --abbrev-ref HEAD); \
elif [ -n "$BRANCH_NAME" ]; then \
echo $BRANCH_NAME; \
else \
echo $(git name-rev --name-only HEAD); \
fi)
LABEL commit=$(git rev-parse HEAD)
LABEL commit_number=$(git rev-list --count HEAD)
EOF

51
Jenkinsfile vendored
View File

@ -1,51 +0,0 @@
#!groovy
build('control-center', 'docker-host') {
checkoutRepo()
loadBuildUtils()
def pipeDefault
def withWsCache
runStage('load pipeline') {
env.JENKINS_LIB = "build_utils/jenkins_lib"
pipeDefault = load("${env.JENKINS_LIB}/pipeDefault.groovy")
withWsCache = load("${env.JENKINS_LIB}/withWsCache.groovy")
}
def pipeline = {
runStage('init') {
withGithubSshCredentials {
withGithubToken {
sh 'make wc_init'
}
}
}
if (env.BRANCH_NAME == 'master') {
runStage('build') {
withCredentials([string(credentialsId: 'SENTRY_AUTH_TOKEN', variable: 'SENTRY_AUTH_TOKEN')]) {
sh 'make wc_build'
}
}
} else {
runStage('build') {
sh "make wc_cmd WC_CMD='make build_pr'"
}
}
runStage('build image') {
sh 'make build_image'
}
runFESecurityTools()
try {
if (env.BRANCH_NAME == 'master') {
runStage('push image') {
sh 'make push_image'
}
}
} finally {
runStage('rm local image') {
sh 'make rm_local_image'
}
}
}
pipeDefault(pipeline)
}

View File

@ -1,49 +0,0 @@
SUBMODULES = build_utils
SUBTARGETS = $(patsubst %,%/.git,$(SUBMODULES))
UTILS_PATH := build_utils
TEMPLATES_PATH := .
# Name of the service
SERVICE_NAME := control-center
# Service image default tag
SERVICE_IMAGE_TAG ?= $(shell git rev-parse HEAD)
# The tag for service image to be pushed with
SERVICE_IMAGE_PUSH_TAG ?= $(SERVICE_IMAGE_TAG)
REGISTRY ?= dr2.rbkmoney.com
# Base image for the service
BASE_IMAGE_NAME := service-fe
BASE_IMAGE_TAG := 647d66a59ba89ea42b326ca5156f5d1e1395febc
BUILD_IMAGE_TAG := 25c031edd46040a8745334570940a0f0b2154c5c
GIT_SSH_COMMAND :=
DOCKER_RUN_OPTS = -e GIT_SSH_COMMAND='$(GIT_SSH_COMMAND)' -e NG_CLI_ANALYTICS=ci -e NPM_TOKEN='$(GITHUB_TOKEN)' -e SENTRY_AUTH_TOKEN='$(SENTRY_AUTH_TOKEN)'
CALL_W_CONTAINER := init build clean submodules
.PHONY: $(CALL_W_CONTAINER)
all: build
-include $(UTILS_PATH)/make_lib/utils_image.mk
-include $(UTILS_PATH)/make_lib/utils_container.mk
$(SUBTARGETS): %/.git: %
git submodule update --init $<
touch $@
submodules: $(SUBTARGETS)
init:
echo -e "//npm.pkg.github.com/:_authToken=$(NPM_TOKEN)" >> .npmrc
npm ci
npm run compile
build:
SENTRY_AUTH_TOKEN=$(SENTRY_AUTH_TOKEN) npm run ci:build
build_pr:
npm run ci:build

View File

@ -1,14 +1,14 @@
# Control Center
## Компиляция thrift:
## Installation
```sh
make wc_shell
npm ci
npm run compile
```
## Запуск Sonar'a
## Usage
```sh
sonar-scanner -Dsonar.host.url=http://morphling-2.bst1.rbkmoney.net:9000 -Dsonar.sources=./src -Dsonar.projectKey=control-center -Dsonar.exclusions=src/app/gen-*/**,src/app/thrift/gen-*/**,src/app/fistful/gen-*/**,src/app/machinegun/gen-*/**,src/assets/meta-*.json
npm start
```

View File

@ -29,7 +29,6 @@
"rxjs",
"thrift-ts",
"buffer",
"@rbkmoney/partial-fetcher",
"humanize-duration"
],
"outputPath": "dist",

@ -1 +0,0 @@
Subproject commit be44d69fc87b22a0bb82d98d6eae7658d1647f98

5240
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,13 @@
{
"name": "control-center",
"version": "0.0.0",
"engines": {
"node": "^16.0.0",
"npm": "^7.0.0"
},
"scripts": {
"postinstall": "ngcc",
"start": "ng serve --proxy-config proxy.conf.json --port 7000",
"start": "ng serve --proxy-config proxy.conf.js --port 4200",
"build": "ng build --extra-webpack-config webpack.extra.js",
"test": "ng test",
"lint": "eslint \"src/**/*.{ts,js,html}\" --max-warnings 2070 --cache",
@ -36,38 +40,26 @@
"@angular/router": "~12.1.4",
"@ngneat/reactive-forms": "^2.0.0",
"@ngneat/until-destroy": "^8.0.3",
"@rbkmoney/partial-fetcher": "~0.4.0",
"@rbkmoney/sentry": "^0.1.0",
"@rbkmoney/utils": "~0.4.0",
"@rbkmoney/woody_js": "^0.1.0",
"@s-libs/js-core": "^12.0.0",
"@s-libs/micro-dash": "^12.0.0",
"@s-libs/ng-core": "^12.0.0",
"@s-libs/rxjs-core": "^12.0.0",
"@vality/thrift-ts": "^2.2.0-alpha",
"@vality/woody": "^0.1.0",
"angular-file": "3.0.1",
"angular2-prettyjson": "3.0.1",
"ank-proto": "git+ssh://git@github.com:rbkmoney/ank-proto.git#d638e44eb8632fd62f0d6730294e51637babcc78",
"coerce-property": "^0.3.2",
"damsel": "git+ssh://git@github.com/rbkmoney/damsel.git#b7f092ef41db810b79c03ad4f1f229d79091e172",
"deanonimus-proto": "github:rbkmoney/deanonimus-proto#b9fab4fd1c7690186efdc5974d113c82bd5765e9",
"dominant-cache-proto": "github:rbkmoney/dominant-cache-proto",
"file-storage-proto": "git+ssh://git@github.com:rbkmoney/file-storage-proto.git#281e1ca4cea9bf32229a6c389f0dcf5d49c05a0b",
"fistful-proto": "git+ssh://git@github.com/rbkmoney/fistful-proto.git#e340259cdd3add024f0139e21f0a2453312ef901",
"humanize-duration": "~3.21.0",
"jsonc-parser": "~2.0.2",
"keycloak-angular": "^8.3.0",
"keycloak-js": "^14.0.0",
"lodash-es": "~4.17.15",
"machinegun_proto": "git+ssh://git@github.com/rbkmoney/machinegun_proto.git#d814d6948d4ff13f6f41d12c6613f59c805750b2",
"messages-proto": "git+ssh://git@github.com:rbkmoney/messages-proto.git#a177efb574136961bcd0a8236b4bfc425264de29",
"moment": "~2.22.2",
"monaco-editor": "^0.21.2",
"ngx-mat-select-search": "^3.3.0",
"pdfmake": "^0.1.64",
"rxjs": "^6.6.3",
"short-uuid": "^4.1.0",
"skipper-proto": "git+ssh://git@github.com/rbkmoney/skipper-proto.git#d33d87cd9080925861f755b11ee1f16378076f74",
"thrift-ts": "git+ssh://git@github.com/rbkmoney/thrift-ts.git#b0624317043bbeb3c4882d2102e631b3b75a5abb",
"transliteration": "^2.1.8",
"tslib": "^2.0.0",
"utility-types": "^3.10.0",
@ -76,13 +68,11 @@
},
"devDependencies": {
"@angular-devkit/build-angular": "^12.1.4",
"@angular-eslint/eslint-plugin-template": "~4.0.0",
"@angular-eslint/template-parser": "~4.0.0",
"@angular-eslint/eslint-plugin": "^12.7.0",
"@angular-eslint/eslint-plugin-template": "^12.7.0",
"@angular-eslint/template-parser": "^12.7.0",
"@angular/cli": "^12.1.4",
"@angular/compiler-cli": "^12.1.4",
"@rbkmoney/angular-templates": "^0.2.2",
"@rbkmoney/eslint-plugin": "~0.2.0",
"@sentry/webpack-plugin": "^1.17.1",
"@types/del": "^4.0.0",
"@types/glob": "^7.1.3",
"@types/humanize-duration": "~3.18.0",
@ -92,12 +82,26 @@
"@types/node": "^16.4.12",
"@types/pdfmake": "^0.1.9",
"@types/uuid": "~3.4.3",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "~4.22.0",
"ank-proto": "github:valitydev/ank-proto#d638e44eb8632fd62f0d6730294e51637babcc78",
"chalk": "^4.1.0",
"codelyzer": "^6.0.0",
"concurrently": "^6.2.0",
"concurrently": "^6.5.1",
"damsel": "github:valitydev/damsel#b7f092ef41db810b79c03ad4f1f229d79091e172",
"deanonimus-proto": "github:valitydev/deanonimus-proto#b9fab4fd1c7690186efdc5974d113c82bd5765e9",
"del": "^5.1.0",
"dominant-cache-proto": "github:valitydev/dominant-cache-proto#ebd35c3096cb5e3222aa29317277b59a01c41fbe",
"eslint": "^7.25.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jasmine": "^4.1.2",
"eslint-plugin-jsdoc": "^32.3.1",
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-unused-imports": "^1.1.1",
"eslint-plugin-you-dont-need-lodash-underscore": "^6.11.0",
"file-storage-proto": "github:valitydev/file-storage-proto#281e1ca4cea9bf32229a6c389f0dcf5d49c05a0b",
"fistful-proto": "github:valitydev/fistful-proto#e340259cdd3add024f0139e21f0a2453312ef901",
"glob": "^7.1.6",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
@ -107,8 +111,11 @@
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"machinegun_proto": "github:valitydev/machinegun_proto#d814d6948d4ff13f6f41d12c6613f59c805750b2",
"messages-proto": "github:valitydev/messages-proto#a177efb574136961bcd0a8236b4bfc425264de29",
"ngx-build-plus": "^12.2.0",
"prettier": "~2.0.4",
"skipper-proto": "github:valitydev/skipper-proto#d33d87cd9080925861f755b11ee1f16378076f74",
"ts-mockito": "^2.6.1",
"ts-node": "~8.8.2",
"typescript": "~4.3.5"

11
proxy.conf.js Normal file
View File

@ -0,0 +1,11 @@
const THRIFT_PROXY_CONFIG = {
context: ['/v1', '/stat', '/fistful', '/papi', '/file_storage', '/deanonimus'],
target: '',
secure: false,
logLevel: 'debug',
changeOrigin: true,
};
if (!THRIFT_PROXY_CONFIG.target) throw new Error('proxy.conf.js - set the thrift proxy target!');
module.exports = [THRIFT_PROXY_CONFIG];

View File

@ -1,9 +0,0 @@
[
{
"context": ["/v1", "/stat", "/fistful", "/papi", "/file_storage", "/deanonimus"],
"target": "https://iddqd.rbk.money",
"secure": false,
"logLevel": "debug",
"changeOrigin": true
}
]

View File

@ -1,5 +1,5 @@
import connectClient from '@rbkmoney/woody_js';
import { ConnectOptions } from '@rbkmoney/woody_js/src/connect-options';
import connectClient from '@vality/woody';
import { ConnectOptions } from '@vality/woody/src/connect-options';
import { Observable } from 'rxjs';
import { ThriftService, ThriftServiceConnection } from './types';

View File

@ -1,4 +1,4 @@
import { ConnectOptions } from '@rbkmoney/woody_js/src/connect-options';
import { ConnectOptions } from '@vality/woody/src/connect-options';
import { KeycloakToken } from '@cc/app/shared/services';

View File

@ -13,8 +13,6 @@ import { MatSidenavModule } from '@angular/material/sidenav';
import { MatToolbarModule } from '@angular/material/toolbar';
import { BrowserModule, DomSanitizer } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import { createSentryProviders } from '@rbkmoney/sentry';
import * as moment from 'moment';
import { KeycloakTokenInfoModule } from '@cc/app/shared/services';
@ -92,7 +90,6 @@ moment.locale('en');
{ provide: SEARCH_LIMIT, useValue: DEFAULT_SEARCH_LIMIT },
{ provide: SMALL_SEARCH_LIMIT, useValue: DEFAULT_SMALL_SEARCH_LIMIT },
{ provide: DIALOG_CONFIG, useValue: DEFAULT_DIALOG_CONFIG },
...createSentryProviders([Router], { logErrors: true }),
],
bootstrap: [AppComponent],
})

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import Int64 from 'thrift-ts/lib/int64';
import Int64 from '@vality/thrift-ts/lib/int64';
import { ClaimManagementService } from '../../thrift-services/damsel/claim-management.service';
import { ClaimService } from './claim.service';

View File

@ -1,11 +1,12 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import * as moment from 'moment';
import { forkJoin, merge, Observable, of, Subject } from 'rxjs';
import { catchError, filter, map, shareReplay, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { Modification } from '../../../../thrift-services/damsel/gen-model/claim_management';
import { FileStorageService } from '../../../../thrift-services/file-storage/file-storage.service';
import { NewFileResult } from '../../../../thrift-services/file-storage/gen-model/file_storage';

View File

@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import Int64 from '@vality/thrift-ts/lib/int64';
import isEqual from 'lodash-es/isEqual';
import { forkJoin, Observable, of, ReplaySubject, Subject } from 'rxjs';
import {
@ -13,7 +14,6 @@ import {
switchMap,
tap,
} from 'rxjs/operators';
import Int64 from 'thrift-ts/lib/int64';
import { ClaimManagementService } from '../../../thrift-services/damsel/claim-management.service';
import { Modification } from '../../../thrift-services/damsel/gen-model/claim_management';

View File

@ -1,12 +1,13 @@
import { Injectable } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import get from 'lodash-es/get';
import { BehaviorSubject, forkJoin, merge, Observable, of, Subject } from 'rxjs';
import { catchError, filter, pluck, switchMap, tap } from 'rxjs/operators';
import * as uuid from 'uuid/v4';
import { progress } from '@cc/app/shared/custom-operators';
import { KeycloakTokenInfoService } from '../../../../keycloak-token-info.service';
import { Modification } from '../../../../thrift-services/damsel/gen-model/claim_management';
import { ConversationId, User } from '../../../../thrift-services/messages/gen-model/messages';

View File

@ -1,7 +1,6 @@
import { Injectable } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import { ConnectableObservable, Observable, Subject } from 'rxjs';
import {
catchError,
@ -14,6 +13,8 @@ import {
switchMap,
} from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { ClaimManagementService } from '../../../thrift-services/damsel/claim-management.service';
import { ClaimID } from '../../../thrift-services/damsel/gen-model/claim_management';
import { ClaimStatuses } from '../claim-statuses';

View File

@ -1,7 +1,7 @@
<div fxLayout="column" fxLayoutGap="5px">
<mat-card>
<mat-card-subtitle>{{
type == 'ShopUnitContainer'
type === 'ShopUnitContainer'
? 'Shop modification units'
: type === 'ContractUnitContainer'
? 'Contract modification units'

View File

@ -1,9 +1,7 @@
import { CommonModule } from '@angular/common';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { initSentry, TraceService } from '@rbkmoney/sentry';
import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
import { environment } from '../../environments/environment';
import { KeycloakTokenInfoService } from '../keycloak-token-info.service';
import { ConfigService } from './config.service';
@ -15,10 +13,6 @@ const initializer = (
Promise.all([
configService.load().then(() =>
Promise.all([
initSentry({
dsn: configService.config.sentryDsn,
environment: environment.production ? 'production' : 'development',
}),
keycloak
.init({
config: '/assets/authConfig.json',
@ -45,13 +39,7 @@ const initializer = (
provide: APP_INITIALIZER,
useFactory: initializer,
multi: true,
deps: [
KeycloakService,
ConfigService,
KeycloakTokenInfoService,
// Need for https://docs.sentry.io/platforms/javascript/guides/angular/
TraceService,
],
deps: [KeycloakService, ConfigService, KeycloakTokenInfoService],
},
],
})

View File

@ -1,4 +1,4 @@
import Int64 from 'thrift-ts/lib/int64';
import Int64 from '@vality/thrift-ts/lib/int64';
import {
ArrayASTNode,

View File

@ -1,8 +1,8 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Field } from '@vality/thrift-ts';
import { Observable, of } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { Field } from 'thrift-ts';
import { Reference } from '../thrift-services/damsel/gen-model/domain';
import { ASTDefinition } from './model';

View File

@ -1,4 +1,4 @@
import { Enums, Field, JsonAST, Structs, TypeDefs, Unions } from 'thrift-ts';
import { Enums, Field, JsonAST, Structs, TypeDefs, Unions } from '@vality/thrift-ts';
import {
ASTDefinition,

View File

@ -1,4 +1,4 @@
import { ListType, MapType, SetType, ValueType } from 'thrift-ts';
import { ListType, MapType, SetType, ValueType } from '@vality/thrift-ts';
import {
CollectionType,

View File

@ -1,5 +1,5 @@
import { ValueType } from '@vality/thrift-ts';
import isObject from 'lodash-es/isObject';
import { ValueType } from 'thrift-ts';
import { PrimitiveType } from '../model';

View File

@ -1,4 +1,4 @@
import { JsonAST } from 'thrift-ts';
import { JsonAST } from '@vality/thrift-ts';
// eslint-disable-next-line @typescript-eslint/naming-convention
export interface ASTDefinition {

View File

@ -1,4 +1,4 @@
import { Field } from 'thrift-ts';
import { Field } from '@vality/thrift-ts';
import { clearNullFields } from '@cc/utils/thrift-utils';

View File

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { Field } from '@vality/thrift-ts';
import { AsyncSubject, combineLatest, Observable, Subject } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { Field } from 'thrift-ts';
import { Snapshot } from '../../thrift-services/damsel/gen-model/domain_config';
import { DomainService } from '../domain.service';

View File

@ -1,8 +1,8 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Field, JsonAST } from '@vality/thrift-ts';
import { Observable, of } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { Field, JsonAST } from 'thrift-ts';
import { Reference } from '../thrift-services/damsel/gen-model/domain';

View File

@ -1,12 +1,12 @@
import { Injectable } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { progress } from '@rbkmoney/utils';
import Int64 from '@vality/thrift-ts/lib/int64';
import { EMPTY, merge, ReplaySubject, Subject } from 'rxjs';
import { catchError } from 'rxjs/internal/operators';
import { map, shareReplay, switchMap, withLatestFrom } from 'rxjs/operators';
import Int64 from 'thrift-ts/lib/int64';
import { DepositManagementService } from '@cc/app/api/fistful';
import { progress } from '@cc/app/shared/custom-operators';
import { UserInfoBasedIdGeneratorService } from '@cc/app/shared/services';
import { toMinor } from '@cc/utils/to-minor';

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { FetchResult, PartialFetcher } from '@rbkmoney/partial-fetcher';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { FetchResult, PartialFetcher } from '@cc/app/shared/services';
import { FistfulStatisticsService } from '../../../../../thrift-services/fistful/fistful-stat.service';
import { StatDepositRevert } from '../../../../../thrift-services/fistful/gen-model/fistful_stat';
import { FetchRevertsParams } from '../../types/fetch-reverts-params';

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import { merge, NEVER, ReplaySubject, Subject } from 'rxjs';
import { catchError, switchMap, pluck, shareReplay } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { FistfulStatisticsService } from '../../../../thrift-services/fistful/fistful-stat.service';
@Injectable()

View File

@ -1,13 +1,13 @@
import { Injectable } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { progress } from '@rbkmoney/utils';
import Int64 from '@vality/thrift-ts/lib/int64';
import { KeycloakService } from 'keycloak-angular';
import * as moment from 'moment';
import { EMPTY, forkJoin, merge, Observable, of, Subject } from 'rxjs';
import { catchError } from 'rxjs/internal/operators';
import { map, switchMap } from 'rxjs/operators';
import Int64 from 'thrift-ts/lib/int64';
import { progress } from '@cc/app/shared/custom-operators';
import { UserInfoBasedIdGeneratorService } from '@cc/app/shared/services';
import { createDepositStopPollingCondition } from '@cc/app/shared/utils';
import { poll } from '@cc/utils/poll';

View File

@ -1,8 +1,8 @@
import { Injectable } from '@angular/core';
import { FetchResult, PartialFetcher } from '@rbkmoney/partial-fetcher';
import { Observable } from 'rxjs';
import { shareReplay } from 'rxjs/operators';
import { FetchResult, PartialFetcher } from '@cc/app/shared/services';
import { booleanDelay } from '@cc/utils/boolean-delay';
import { FistfulStatisticsService } from '../../../../thrift-services/fistful/fistful-stat.service';

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import { merge, of, Subject } from 'rxjs';
import { catchError, pluck, shareReplay, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { ConversationId } from '../../../../../thrift-services/messages/gen-model/messages';
import { MessagesService } from '../../../../../thrift-services/messages/messages.service';

View File

@ -1,9 +1,10 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import * as moment from 'moment';
import { merge, Observable, of, Subject } from 'rxjs';
import { catchError, filter, map, shareReplay, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { FileStorageService } from '../../../../../thrift-services/file-storage/file-storage.service';
import { FileData } from '../../../../../thrift-services/file-storage/gen-model/file_storage';
import { download } from './download';

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import { merge, Observable, of, Subject } from 'rxjs';
import { catchError, pluck, shareReplay, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { AnkService } from '../../../../../thrift-services/ank/ank.service';
import {
Questionary,

View File

@ -1,8 +1,8 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import Int64 from '@vality/thrift-ts/lib/int64';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import Int64 from 'thrift-ts/lib/int64';
import { ClaimManagementService } from '../../../../thrift-services/damsel/claim-management.service';
import { Modification } from '../../../../thrift-services/damsel/gen-model/claim_management';

View File

@ -1,9 +1,9 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import { BehaviorSubject, forkJoin, merge, Observable, of, Subject } from 'rxjs';
import { catchError, first, map, shareReplay, switchMap, tap } from 'rxjs/operators';
import { PartyModificationEmitter } from '@cc/app/shared/components';
import { progress } from '@cc/app/shared/custom-operators';
import { KeycloakTokenInfoService } from '../../../../keycloak-token-info.service';
import {

View File

@ -1,9 +1,10 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import Int64 from '@vality/thrift-ts/lib/int64';
import { of, ReplaySubject } from 'rxjs';
import { catchError, filter, shareReplay, switchMap } from 'rxjs/operators';
import Int64 from 'thrift-ts/lib/int64';
import { progress } from '@cc/app/shared/custom-operators';
import { ClaimManagementService } from '../../thrift-services/damsel/claim-management.service';
import { PartyID } from '../../thrift-services/damsel/gen-model/domain';

View File

@ -1,11 +1,12 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import * as moment from 'moment';
import { forkJoin, merge, Observable, of, Subject } from 'rxjs';
import { catchError, filter, map, shareReplay, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { Modification } from '../../../../thrift-services/damsel/gen-model/claim_management';
import { FileStorageService } from '../../../../thrift-services/file-storage/file-storage.service';
import { NewFileResult } from '../../../../thrift-services/file-storage/gen-model/file_storage';

View File

@ -1,11 +1,12 @@
import { Injectable } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import { forkJoin, merge, of, Subject } from 'rxjs';
import { catchError, filter, shareReplay, switchMap, tap } from 'rxjs/operators';
import * as uuid from 'uuid/v4';
import { progress } from '@cc/app/shared/custom-operators';
import { KeycloakTokenInfoService } from '../../../../keycloak-token-info.service';
import { Modification } from '../../../../thrift-services/damsel/gen-model/claim_management';
import { ConversationId, User } from '../../../../thrift-services/messages/gen-model/messages';

View File

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import Int64 from '@vality/thrift-ts/lib/int64';
import { merge, of, Subject } from 'rxjs';
import {
catchError,
@ -13,7 +13,8 @@ import {
switchMap,
tap,
} from 'rxjs/operators';
import Int64 from 'thrift-ts/lib/int64';
import { progress } from '@cc/app/shared/custom-operators';
import { ClaimStatus } from '../../../../papi/model';
import { ClaimManagementService } from '../../../../thrift-services/damsel/claim-management.service';

View File

@ -1,10 +1,10 @@
import { Injectable } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { FetchResult, PartialFetcher } from '@rbkmoney/partial-fetcher';
import { Observable } from 'rxjs';
import { map, pluck, switchMap } from 'rxjs/operators';
import { ClaimSearchQuery } from '@cc/app/api/damsel/gen-model/claim_management';
import { FetchResult, PartialFetcher } from '@cc/app/shared/services';
import { ClaimManagementService } from '../../thrift-services/damsel/claim-management.service';
import {

View File

@ -1,10 +1,11 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ActivatedRoute } from '@angular/router';
import { progress } from '@rbkmoney/utils';
import { combineLatest, of } from 'rxjs';
import { map, pluck, shareReplay, switchMap, tap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { PartyService } from '../../papi/party.service';
import { QueryDsl } from '../../query-dsl';
import { MerchantStatisticsService } from '../../thrift-services/damsel/merchant-statistics.service';

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import { forkJoin, merge, Observable, of, Subject } from 'rxjs';
import { catchError, filter, map, shareReplay, startWith, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { PartyService } from '../../../../papi/party.service';
import { ContractID, PartyID } from '../../../../thrift-services/damsel/gen-model/domain';

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import { merge, of, Subject } from 'rxjs';
import { catchError, filter, map, shareReplay, startWith, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { DomainCacheService } from '../../../../thrift-services/damsel/domain-cache.service';
@Injectable()

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import { merge, of, Subject } from 'rxjs';
import { catchError, filter, map, shareReplay, startWith, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { DomainCacheService } from '../../../../thrift-services/damsel/domain-cache.service';
@Injectable()

View File

@ -1,8 +1,8 @@
import { Injectable } from '@angular/core';
import { FetchResult, PartialFetcher } from '@rbkmoney/partial-fetcher';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { FetchResult, PartialFetcher } from '@cc/app/shared/services';
import { booleanDelay } from '@cc/utils/boolean-delay';
import { QueryDsl } from '../../../query-dsl';

View File

@ -1,9 +1,9 @@
import { Injectable } from '@angular/core';
import { FetchResult, PartialFetcher } from '@rbkmoney/partial-fetcher';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { PartyID } from '@cc/app/api/damsel/gen-model/domain';
import { FetchResult, PartialFetcher } from '@cc/app/shared/services';
import { ClaimManagementService } from '../../thrift-services/damsel/claim-management.service';
import {

View File

@ -1,9 +1,10 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import { BehaviorSubject, merge, of, Subject } from 'rxjs';
import { catchError, filter, shareReplay, startWith, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { PartyService } from '../../../papi/party.service';
import { PartyID, ShopID } from '../../../thrift-services/damsel/gen-model/domain';

View File

@ -1,9 +1,10 @@
import { Injectable } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { progress } from '@rbkmoney/utils';
import { merge, Observable, Subject } from 'rxjs';
import { map, shareReplay, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { AddDecisionToProvider, ProviderService } from '../../../../../../thrift-services/damsel';
import { DomainCacheService } from '../../../../../../thrift-services/damsel/domain-cache.service';
import {

View File

@ -1,5 +1,5 @@
import Int64 from '@vality/thrift-ts/lib/int64';
import get from 'lodash-es/get';
import Int64 from 'thrift-ts/lib/int64';
import { getUnionKey, getUnionValue } from '@cc/utils/get-union-key';

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import { combineLatest, defer, ReplaySubject } from 'rxjs';
import { map, shareReplay, startWith, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { DomainCacheService } from '../../../../../thrift-services/damsel/domain-cache.service';
import { PartyID, ShopID } from '../../../../../thrift-services/damsel/gen-model/domain';
import { toProvidersInfo } from './to-providers-info';

View File

@ -1,10 +1,10 @@
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import { combineLatest, EMPTY, merge, of, Subject } from 'rxjs';
import { catchError, filter, map, shareReplay, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { ConfirmActionDialogComponent } from '@cc/components/confirm-action-dialog';
import { ProviderService } from '../../../../../thrift-services/damsel';

View File

@ -1,4 +1,4 @@
import Int64 from 'thrift-ts/lib/int64';
import Int64 from '@vality/thrift-ts/lib/int64';
import { TerminalID } from '../../../../thrift-services/fistful/gen-model/fistful';
import { PredicateType } from './predicate-type';

View File

@ -1,4 +1,4 @@
import Int64 from 'thrift-ts/lib/int64';
import Int64 from '@vality/thrift-ts/lib/int64';
import { TerminalID } from '../../../../thrift-services/fistful/gen-model/fistful';
import { PredicateType } from './predicate-type';

View File

@ -1,4 +1,4 @@
import Int64 from 'thrift-ts/lib/int64';
import Int64 from '@vality/thrift-ts/lib/int64';
import { TerminalObject } from '../../../../thrift-services/damsel/gen-model/domain';
import { PredicateType } from './predicate-type';

View File

@ -1,10 +1,10 @@
import { Injectable } from '@angular/core';
import { FetchResult, PartialFetcher } from '@rbkmoney/partial-fetcher';
import pickBy from 'lodash-es/pickBy';
import moment from 'moment';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { FetchResult, PartialFetcher } from '@cc/app/shared/services';
import { booleanDelay } from '@cc/utils/boolean-delay';
import { ChargebacksParams, createDsl } from '../../../query-dsl';

View File

@ -1,10 +1,11 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import { combineLatest, merge, Observable, of, Subject } from 'rxjs';
import { catchError, map, switchMap, tap } from 'rxjs/internal/operators';
import { filter } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { PartyService } from '../../../../../papi/party.service';
import { Modification } from '../../../../../thrift-services/damsel/gen-model/claim_management';
import {

View File

@ -1,9 +1,10 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import { combineLatest, merge, Observable, of, Subject } from 'rxjs';
import { catchError, filter, map, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { PartyService } from '../../../../../papi/party.service';
import { ChangesetInfo } from '../../../../../sections/party-claim/changeset/changeset-infos';
import { PartyID } from '../../../../../thrift-services/damsel/gen-model/domain';

View File

@ -1,9 +1,9 @@
import { Injectable } from '@angular/core';
import { FetchResult, PartialFetcher } from '@rbkmoney/partial-fetcher';
import * as moment from 'moment';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { FetchResult, PartialFetcher } from '@cc/app/shared/services';
import { booleanDelay } from '@cc/utils/boolean-delay';
import { QueryDsl } from '../../../query-dsl';

View File

@ -0,0 +1 @@
export * from './progress';

View File

@ -0,0 +1,13 @@
import { merge, Observable, of } from 'rxjs';
import { catchError, distinctUntilChanged, map, startWith } from 'rxjs/operators';
export const progress = (
start$: Observable<any>,
end$: Observable<any>,
startValue = false
): Observable<boolean> =>
merge(start$.pipe(map(() => true)), end$.pipe(map(() => false))).pipe(
catchError(() => of(false)),
startWith(startValue),
distinctUntilChanged()
);

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { progress } from '@rbkmoney/utils';
import { Observable, of, Subject } from 'rxjs';
import { catchError, map, shareReplay, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { DeanonimusService } from '../../thrift-services/deanonimus';
import { Party } from '../../thrift-services/deanonimus/gen-model/deanonimus';

View File

@ -3,3 +3,4 @@ export * from './app-auth-guard';
export * from './fetch-parties.service';
export * from './keycloak-token-info';
export * from './user-info-based-id-generator';
export * from './partial-fetcher';

View File

@ -0,0 +1,4 @@
import { InjectionToken } from '@angular/core';
export const DEBOUNCE_FETCHER_ACTION_TIME = new InjectionToken<number>('debounceFetcherActionTime');
export const DEFAULT_FETCHER_DEBOUNCE_ACTION_TIME = 300;

View File

@ -0,0 +1,4 @@
export interface FetchAction<P extends any = any> {
type: 'search' | 'fetchMore';
value?: P;
}

View File

@ -0,0 +1,5 @@
import { Observable } from 'rxjs';
import { FetchResult } from './fetch-result';
export type FetchFn<P, R> = (params: P, continuationToken?: string) => Observable<FetchResult<R>>;

View File

@ -0,0 +1,5 @@
export interface FetchResult<T> {
result?: T[];
continuationToken?: string;
error?: any;
}

View File

@ -0,0 +1,4 @@
export * from './partial-fetcher';
export * from './fetch-result';
export * from './fetch-action';
export * from './consts';

View File

@ -0,0 +1,2 @@
export * from './scan-action';
export * from './scan-search-result';

View File

@ -0,0 +1,5 @@
import { Observable } from 'rxjs';
import { scan } from 'rxjs/operators';
export const scanAction = <T>(s: Observable<T>) =>
s.pipe(scan<T, T>((lastAction, currentAction) => ({ ...lastAction, ...currentAction }), null));

View File

@ -0,0 +1,44 @@
import { Observable, of } from 'rxjs';
import { catchError, first, map, mergeScan } from 'rxjs/operators';
import { FetchAction } from '../fetch-action';
import { FetchFn } from '../fetch-fn';
import { FetchResult } from '../fetch-result';
export const handleFetchResultError = <R>(result: R[] = [], continuationToken?: string) => (
s: Observable<FetchResult<R>>
): Observable<FetchResult<R>> =>
s.pipe(
catchError((error) =>
of<FetchResult<R>>({
result,
continuationToken,
error,
})
)
);
export const scanFetchResult = <P, R>(fn: FetchFn<P, R>) => (
s: Observable<FetchAction<P>>
): Observable<FetchResult<R>> =>
s.pipe(
mergeScan<FetchAction<P>, FetchResult<R>>(
({ result, continuationToken }, { type, value }) => {
switch (type) {
case 'search':
return fn(value).pipe(first(), handleFetchResultError());
case 'fetchMore':
return fn(value, continuationToken).pipe(
first(),
map((r) => ({
result: result.concat(r.result),
continuationToken: r.continuationToken,
})),
handleFetchResultError(result, continuationToken)
);
}
},
{ result: [] },
1
)
);

View File

@ -0,0 +1,124 @@
import { Observable } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { FetchResult } from './fetch-result';
import { PartialFetcher } from './partial-fetcher';
function assertDeepEqual(actual: any, expected: any) {
expect(actual).toEqual(expected);
}
function createScheduler() {
return new TestScheduler(assertDeepEqual);
}
describe('PartialFetch', () => {
class PartialFetched extends PartialFetcher<any, any> {
constructor(
private fetchFn: (params?: any, continuationToken?: string) => Observable<any>,
debounce?: number
) {
super(debounce);
}
protected fetch(params: any, continuationToken: string) {
return this.fetchFn(params, continuationToken);
}
}
it('should init', () => {
createScheduler().run(({ cold, expectObservable }) => {
const result: FetchResult<any> = { result: ['test'] };
const partialFetched = new PartialFetched(() => cold('--x|', { x: result }), 100);
expectObservable(partialFetched.searchResult$).toBe('');
expectObservable(partialFetched.errors$).toBe('');
expectObservable(partialFetched.doAction$).toBe('0', [true]);
expectObservable(partialFetched.hasMore$).toBe('0', [null]);
});
});
it('should search with debounce', () => {
createScheduler().run(({ cold, expectObservable }) => {
const result: FetchResult<any> = { result: ['test'] };
const partialFetched = new PartialFetched(() => cold('--x|', { x: result }), 100);
partialFetched.search(null);
expectObservable(partialFetched.searchResult$).toBe('100ms --0', [['test']]);
expectObservable(partialFetched.errors$).toBe('');
expectObservable(partialFetched.doAction$).toBe('0 100ms -1', [true, false]);
expectObservable(partialFetched.hasMore$).toBe('0 100ms -1', [null, false]);
});
});
it('should load more with last token', () => {
createScheduler().run(({ cold, expectObservable }) => {
const partialFetched = new PartialFetched(
(_params, token) =>
cold('--x|', {
x: { result: [token], continuationToken: token ? token + '0' : 'token' },
} as FetchResult<any>),
0
);
partialFetched.search('token');
partialFetched.fetchMore();
partialFetched.fetchMore();
partialFetched.fetchMore();
expectObservable(partialFetched.searchResult$).toBe('--0-1-2-3', [
[undefined],
[undefined, 'token'],
[undefined, 'token', 'token0'],
[undefined, 'token', 'token0', 'token00'],
]);
expectObservable(partialFetched.errors$).toBe('');
expectObservable(partialFetched.doAction$).toBe('0-1', [true, false]);
expectObservable(partialFetched.hasMore$).toBe('0-1', [null, true]);
});
});
it('should reload with old params', () => {
createScheduler().run(({ cold, expectObservable }) => {
const partialFetched = new PartialFetched(
(params) =>
cold('--x|', {
x: { result: [params], continuationToken: 'token' } as FetchResult<any>,
}),
0
);
partialFetched.search('params');
partialFetched.fetchMore();
partialFetched.refresh();
expectObservable(partialFetched.searchResult$).toBe('--0-1-2', [
['params'],
['params', 'params'],
['params'],
]);
expectObservable(partialFetched.errors$).toBe('');
expectObservable(partialFetched.doAction$).toBe('0-1', [true, false]);
expectObservable(partialFetched.hasMore$).toBe('0-1', [null, true]);
});
});
describe('throw error', () => {
it('should return error with delay', () => {
createScheduler().run(({ cold, expectObservable }) => {
const partialFetched = new PartialFetched(() => cold('--#|'), 100);
partialFetched.search(null);
expectObservable(partialFetched.searchResult$).toBe('100ms --0', [[]]);
expectObservable(partialFetched.errors$).toBe('100ms --0', ['error']);
expectObservable(partialFetched.doAction$).toBe('0 100ms -1', [true, false]);
expectObservable(partialFetched.hasMore$).toBe('0 100ms -1', [null, false]);
});
});
it('should fetch after error', () => {
createScheduler().run(({ cold, expectObservable }) => {
const partialFetched = new PartialFetched(() => cold('--#|'), 0);
partialFetched.search(null);
partialFetched.fetchMore();
expectObservable(partialFetched.searchResult$).toBe('--0-1', [[], []]);
expectObservable(partialFetched.errors$).toBe('--0-1', ['error', 'error']);
expectObservable(partialFetched.doAction$).toBe('0-1', [true, false]);
expectObservable(partialFetched.hasMore$).toBe('0-1', [null, false]);
});
});
});
});

View File

@ -0,0 +1,122 @@
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { EMPTY, merge, Observable, of, Subject } from 'rxjs';
import {
debounceTime,
distinctUntilChanged,
filter,
map,
pluck,
share,
shareReplay,
startWith,
switchMap,
tap,
} from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { FetchAction } from './fetch-action';
import { FetchFn } from './fetch-fn';
import { FetchResult } from './fetch-result';
import { scanAction, scanFetchResult } from './operators';
import { SHARE_REPLAY_CONF } from './utils/share-replay-conf';
// TODO: make free of subscription & UntilDestroy
// TODO: share public props together
// TODO: make fetcher injectable
@UntilDestroy()
export abstract class PartialFetcher<R, P> {
readonly fetchResultChanges$: Observable<{
result: R[];
hasMore: boolean;
continuationToken: string;
}>;
readonly searchResult$: Observable<R[]>;
readonly hasMore$: Observable<boolean>;
readonly doAction$: Observable<boolean>;
readonly doSearchAction$: Observable<boolean>;
readonly errors$: Observable<any>;
private action$ = new Subject<FetchAction<P>>();
// TODO: make a dependency for DI
constructor(debounceActionTime: number = 300) {
const actionWithParams$ = this.getActionWithParams(debounceActionTime);
const fetchResult$ = this.getFetchResult(actionWithParams$);
this.fetchResultChanges$ = fetchResult$.pipe(
map(({ result, continuationToken }) => ({
result: result ?? [],
continuationToken,
hasMore: !!continuationToken,
})),
share()
);
this.searchResult$ = this.fetchResultChanges$.pipe(
pluck('result'),
shareReplay(SHARE_REPLAY_CONF)
);
this.hasMore$ = this.fetchResultChanges$.pipe(
pluck('hasMore'),
startWith(null as boolean),
distinctUntilChanged(),
shareReplay(SHARE_REPLAY_CONF)
);
this.doAction$ = progress(actionWithParams$, fetchResult$, true).pipe(
shareReplay(SHARE_REPLAY_CONF)
);
this.doSearchAction$ = progress(
actionWithParams$.pipe(filter(({ type }) => type === 'search')),
fetchResult$,
true
).pipe(shareReplay(SHARE_REPLAY_CONF));
this.errors$ = fetchResult$.pipe(
switchMap(({ error }) => (error ? of(error) : EMPTY)),
tap((error) => console.error('Partial fetcher error: ', error)),
share()
);
merge(
this.searchResult$,
this.hasMore$,
this.doAction$,
this.doSearchAction$,
this.errors$,
this.fetchResultChanges$
)
.pipe(untilDestroyed(this))
.subscribe();
}
search(value: P) {
this.action$.next({ type: 'search', value });
}
refresh() {
this.action$.next({ type: 'search' });
}
fetchMore() {
this.action$.next({ type: 'fetchMore' });
}
protected abstract fetch(...args: Parameters<FetchFn<P, R>>): ReturnType<FetchFn<P, R>>;
private getActionWithParams(debounceActionTime: number): Observable<FetchAction<P>> {
return this.action$.pipe(
scanAction,
debounceActionTime ? debounceTime(debounceActionTime) : tap(),
share()
);
}
private getFetchResult(
actionWithParams$: Observable<FetchAction<P>>
): Observable<FetchResult<R>> {
const fetchFn = this.fetch.bind(this) as FetchFn<P, R>;
return actionWithParams$.pipe(scanFetchResult(fetchFn), shareReplay(SHARE_REPLAY_CONF));
}
}

View File

@ -0,0 +1,4 @@
import { ShareReplayConfig } from 'rxjs/internal/operators/shareReplay';
// Default share replay config
export const SHARE_REPLAY_CONF: ShareReplayConfig = { bufferSize: 1, refCount: true };

View File

@ -1,9 +1,10 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { progress } from '@rbkmoney/utils';
import { EMPTY, merge, Subject } from 'rxjs';
import { catchError, shareReplay, switchMap } from 'rxjs/operators';
import { progress } from '@cc/app/shared/custom-operators';
import { DomainCacheService } from '../domain-cache.service';
import { editTerminalDecisionPropertyForShopCommit } from '../operations/edit-terminal-decision-property-for-shop-commit';
import { EditTerminalDecisionPropertyParams } from '../operations/edit-terminal-decision-property-params';

View File

@ -1,8 +1,8 @@
import { Inject, Injectable, NgZone } from '@angular/core';
import { FetchResult } from '@rbkmoney/partial-fetcher';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { FetchResult } from '@cc/app/shared/services';
import { removeEmptyProperties } from '@cc/utils/remove-empty-properties';
import { KeycloakTokenInfoService } from '../../keycloak-token-info.service';

View File

@ -1,5 +1,5 @@
import { NgZone } from '@angular/core';
import connectClient from '@rbkmoney/woody_js';
import connectClient from '@vality/woody';
import { Observable } from 'rxjs';
import { timeout } from 'rxjs/operators';

View File

@ -1,5 +1,5 @@
import { ValueType } from '@vality/thrift-ts';
import difference from 'lodash-es/difference';
import { ValueType } from 'thrift-ts';
import { createThriftInstance } from './create-thrift-instance';
import { thriftInstanceToObject } from './thrift-instance-to-object';

View File

@ -1,5 +1,5 @@
import type { ValueType } from 'thrift-ts';
import Int64 from 'thrift-ts/lib/int64';
import type { ValueType } from '@vality/thrift-ts';
import Int64 from '@vality/thrift-ts/lib/int64';
import {
isComplexType,

View File

@ -1,4 +1,4 @@
import type { ListType, MapType, SetType, ThriftType, ValueType } from 'thrift-ts';
import type { ListType, MapType, SetType, ThriftType, ValueType } from '@vality/thrift-ts';
export const PRIMITIVE_TYPES = [
'int',

View File

@ -1,5 +1,5 @@
import type { Int64, ValueType } from '@vality/thrift-ts';
import isNil from 'lodash-es/isNil';
import type { Int64, ValueType } from 'thrift-ts';
import {
isComplexType,

View File

@ -1,5 +1,4 @@
{
"papiEndpoint": "https://iddqd.rbk.money/papi/v1",
"sentryDsn": "https://88c8c7fde70b40afbe2e92338966ce1e@o572161.ingest.sentry.io/5956705",
"fileStorageEndpoint": "https://storage.rbk.money/files"
"papiEndpoint": "",
"fileStorageEndpoint": ""
}

View File

@ -1,6 +1,6 @@
{
"realm": "internal",
"auth-server-url": "https://auth.rbk.money/auth/",
"auth-server-url": "",
"ssl-required": "external",
"resource": "control-center",
"public-client": true

View File

@ -6,7 +6,6 @@ import * as path from 'path';
import * as config from '../thrift-config.json';
const ROOT_DIR = path.join(__dirname, '..');
const THRIFT_PATH = '@rbkmoney/woody_js/dist/thrift';
const OUTPUT_PATH = './src/app/thrift-services';
const GEN_MODEL_DIR = 'gen-model';
@ -38,9 +37,7 @@ async function execWithLog(cmd: string) {
async function genClient(name: string, thriftPath: string) {
const out = path.join(OUTPUT_PATH, name);
await del([path.join(OUTPUT_PATH, GEN_CLIENT_DIR)]);
return await execWithLog(
`thrift -r -gen js:node,runtime_package=${THRIFT_PATH} -o ${out} ${thriftPath};`
);
return await execWithLog(`thrift -r -gen js:node -o ${out} ${thriftPath};`);
}
async function genModel(name: string, protoPath: string) {

View File

@ -83,9 +83,7 @@ async function compileJsonMetadata(definitionsPath: string, outputFilePath: stri
async function compileService(definitionFilePath: string, outputPath: string) {
try {
log(`Compiling service: ${definitionFilePath}`);
await execute(
`thrift -r -gen js:node,runtime_package=@rbkmoney/woody_js/dist/thrift -o ${outputPath} ${definitionFilePath};`
);
await execute(`thrift -r -gen js:node -o ${outputPath} ${definitionFilePath};`);
} catch (err) {
log(`Service: ${definitionFilePath} ${chalk.red('compilation failed')}`);
throw err;

10
tools/eslint-config/angular.js vendored Normal file
View File

@ -0,0 +1,10 @@
'use strict';
module.exports = {
plugins: ['@angular-eslint', 'import', '@typescript-eslint'],
extends: [
'plugin:@angular-eslint/recommended',
'plugin:@angular-eslint/template/process-inline-templates',
require.resolve('./typescript.js'),
],
};

View File

@ -0,0 +1,11 @@
'use strict';
module.exports = {
plugins: ['import'],
extends: ['plugin:import/errors', 'plugin:import/warnings', 'plugin:import/typescript'],
rules: {
'import/no-unresolved': 'off',
'import/namespace': 'off',
...require('./rules').createImportOrderRule(),
},
};

View File

@ -0,0 +1,10 @@
'use strict';
module.exports = {
plugins: ['jasmine', '@typescript-eslint'],
extends: ['plugin:jasmine/recommended'],
rules: {
'jasmine/new-line-before-expect': 'off',
'@typescript-eslint/no-floating-promises': 'off',
},
};

View File

@ -0,0 +1,9 @@
'use strict';
module.exports = {
plugins: ['you-dont-need-lodash-underscore'],
extends: ['plugin:you-dont-need-lodash-underscore/compatible'],
rules: {
'you-dont-need-lodash-underscore/is-nil': 'off',
},
};

View File

@ -0,0 +1,59 @@
'use strict';
module.exports = {
/**
* @param prefix app
*/
createAngularSelectorRules({ prefix } = {}) {
return {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: prefix,
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: prefix,
style: 'kebab-case',
},
],
};
},
/**
* @param internalPathsPattern @app/**
*/
createImportOrderRule({ internalPathsPattern } = {}) {
return {
'import/order': [
'error',
{
groups: [
['builtin', 'external'],
'internal',
['parent', 'sibling', 'index'],
'object',
],
pathGroups: internalPathsPattern
? [
{
pattern: internalPathsPattern,
group: 'internal',
},
]
: [],
pathGroupsExcludedImportTypes: ['builtin'],
'newlines-between': 'always',
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
};
},
};

View File

@ -0,0 +1,97 @@
'use strict';
module.exports = {
plugins: ['@typescript-eslint'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
require.resolve('./import.js'),
require.resolve('./unused-imports.js'),
],
rules: {
'no-console': ['error', { allow: ['warn', 'error'] }],
'no-restricted-imports': [
'error',
{
paths: ['rxjs/Rx', 'rxjs/internal', 'lodash', 'lodash-es', '.'],
patterns: ['src/*'],
},
],
'@typescript-eslint/no-unused-expressions': 'error',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/member-ordering': [
'error',
{
default: [
'signature',
'public-field',
'protected-field',
'private-field',
'constructor',
'public-method',
'protected-method',
'private-method',
],
},
],
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'default',
// TODO: strictCamelCase
format: ['camelCase'],
leadingUnderscore: 'allow',
},
{
selector: 'default',
modifiers: ['destructured'],
format: null,
},
{
selector: 'typeLike',
format: ['StrictPascalCase'],
},
{
selector: 'variable',
modifiers: ['const', 'global'],
format: ['UPPER_CASE'],
},
{
selector: 'variable',
modifiers: ['const', 'global'],
// Objects are functions too
types: ['function'],
format: ['UPPER_CASE', 'strictCamelCase'],
},
{
selector: 'enumMember',
format: ['StrictPascalCase'],
},
{
selector: ['objectLiteralProperty', 'typeProperty'],
format: ['camelCase', 'snake_case'],
leadingUnderscore: 'allow',
trailingUnderscore: 'allow',
},
{
selector: [
'classProperty',
'objectLiteralProperty',
'typeProperty',
'classMethod',
'objectLiteralMethod',
'typeMethod',
'accessor',
'enumMember',
],
modifiers: ['requiresQuotes'],
format: null,
},
],
},
};

View File

@ -0,0 +1,18 @@
'use strict';
module.exports = {
plugins: ['@typescript-eslint', 'unused-imports'],
rules: {
'@typescript-eslint/no-unused-vars': 'off',
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': [
'error',
{
vars: 'all',
varsIgnorePattern: '^_',
args: 'after-used',
argsIgnorePattern: '^_',
},
],
},
};

Some files were not shown because too many files have changed in this diff Show More