Merge branch 'master' into ft/to-wachter

This commit is contained in:
Rinat Arsaev 2022-08-29 12:00:25 +03:00
commit 4a469a0751
356 changed files with 3021 additions and 4880 deletions

View File

@ -43,7 +43,7 @@ module.exports = {
{
...baseTsRules,
// TODO: add fixed directories
files: ['**/src/app/core/**/*.ts'],
files: ['**/src/app/core/**/*.ts', '**/projects/**/*.ts'],
},
{
...baseTsRules,

2
.github/settings.yml vendored Normal file
View File

@ -0,0 +1,2 @@
# These settings are synced to GitHub by https://probot.github.io/apps/settings/
_extends: .github

10
.github/workflows/basic-linters.yml vendored Normal file
View File

@ -0,0 +1,10 @@
name: Vality basic linters
on:
pull_request:
branches:
- "*"
jobs:
lint:
uses: valitydev/base-workflows/.github/workflows/basic-linters.yml@v1

View File

@ -9,6 +9,8 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/init
- name: Building libraries
run: npm run build-libs
- name: Cache all
uses: actions/cache@v3
id: cache
@ -16,7 +18,7 @@ jobs:
path: ./*
key: ${{ github.sha }}
eslint:
name: ESLint
name: ESLint App
runs-on: ubuntu-latest
needs: [init]
steps:
@ -27,7 +29,20 @@ jobs:
path: ./*
key: ${{ github.sha }}
- name: Check
run: npm run lint-cmd
run: npm run lint
eslint-libs:
name: ESLint Libs
runs-on: ubuntu-latest
needs: [init]
steps:
- name: Cache all
uses: actions/cache@v3
id: cache
with:
path: ./*
key: ${{ github.sha }}
- name: Check
run: npm run lint-libs
prettier:
name: Prettier
runs-on: ubuntu-latest
@ -53,4 +68,4 @@ jobs:
path: ./*
key: ${{ github.sha }}
- name: Build
run: npm run build
run: npm run build-app

View File

@ -4,3 +4,6 @@ node_modules
dist
src/assets/icons/
.angular
.github/settings.*
.github/workflows/basic-*

View File

@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="App Dev Server" type="js.build_tools.npm" activateToolWindowBeforeRun="false">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="dev" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>

5
.run/Debug.run.xml Normal file
View File

@ -0,0 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Debug" type="JavascriptDebugType" uri="http://localhost:4200">
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Libs Dev Server" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="dev-libs" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>

7
.run/Start.run.xml Normal file
View File

@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Start" type="CompoundRunConfigurationType">
<toRun name="App Dev Server" type="js.build_tools.npm" />
<toRun name="Libs Dev Server" type="js.build_tools.npm" />
<method v="2" />
</configuration>
</component>

View File

@ -1,3 +1,3 @@
FROM nginx:1.21
COPY dist /usr/share/nginx/html
COPY dist/control-center /usr/share/nginx/html
COPY nginx.conf /etc/nginx/vhosts.d/control-center.conf

View File

@ -40,3 +40,10 @@
npm start
```
2. Open [localhost:4200](http://localhost:4200/)
If you want to develop a library, then it's better to start building library separately:
```sh
npm run dev
npm run dev-libs
```

View File

@ -37,9 +37,10 @@
"@vality/payout-manager-proto",
"@vality/repairer-proto",
"@vality/fistful-proto",
"@vality/file-storage-proto"
"@vality/file-storage-proto",
"@vality/thrift-ts"
],
"outputPath": "dist",
"outputPath": "dist/control-center",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
@ -143,6 +144,37 @@
}
}
}
},
"ng-core": {
"projectType": "library",
"root": "projects/ng-core",
"sourceRoot": "projects/ng-core/src",
"prefix": "v",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"project": "projects/ng-core/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "projects/ng-core/tsconfig.lib.prod.json"
},
"development": {
"tsConfig": "projects/ng-core/tsconfig.lib.json"
}
},
"defaultConfiguration": "production"
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/ng-core/src/test.ts",
"tsConfig": "projects/ng-core/tsconfig.spec.json",
"karmaConfig": "projects/ng-core/karma.conf.js"
}
}
}
}
},
"cli": {

1131
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,17 +4,22 @@
"private": true,
"scripts": {
"postinstall": "ngcc",
"start": "ng serve --proxy-config proxy.conf.js --port 4200",
"build": "ng build --extra-webpack-config webpack.extra.js",
"start": "concurrently -n LIB,APP -c magenta,cyan npm:dev-libs \"sleep 0.5 && npm run dev\"",
"dev": "ng serve --proxy-config proxy.conf.js --port 4200",
"dev-libs": "ng build ng-core --watch",
"build-app": "ng build --extra-webpack-config webpack.extra.js",
"build-libs": "ng build ng-core",
"build": "npm run build-libs && npm run build-app",
"test": "ng test",
"lint-cmd": "eslint \"src/**/*.{ts,js,html}\" --max-warnings 1115",
"lint": "npm run lint-cmd -- --cache",
"lint": "eslint \"src/**/*.{ts,js,html}\" --max-warnings 1033",
"lint-fix": "npm run lint -- --fix",
"lint-errors": "npm run lint -- --quiet",
"lint-libs": "eslint \"projects/**/*.{ts,js,html}\" --max-warnings 0",
"lint-libs-fix": "npm run lint -- --fix",
"prettier-preset": "prettier \"**/*.{html,js,ts,css,scss,md,json,prettierrc,svg,huskyrc,yml,yaml}\"",
"prettier": "npm run prettier-preset -- --list-different",
"prettier:fix": "npm run prettier-preset -- --write",
"fix": "npm run lint-fix; npm run prettier:fix"
"prettier-fix": "npm run prettier-preset -- --write",
"fix": "concurrently -n LIB,APP -c magenta,cyan npm:lint-libs-fix npm:lint-fix && npm run prettier-fix"
},
"dependencies": {
"@angular/animations": "14.0.4",
@ -37,7 +42,7 @@
"@s-libs/ng-core": "14.0.0",
"@s-libs/rxjs-core": "14.0.0",
"@vality/deanonimus-proto": "1.0.1-c9a6cae.0",
"@vality/domain-proto": "1.0.1-9362c08.0",
"@vality/domain-proto": "1.0.1-09e7a75.0",
"@vality/dominant-cache-proto": "1.0.1-5b29d81.0",
"@vality/file-storage-proto": "1.0.1-447212b.0",
"@vality/fistful-proto": "1.0.1-ea0fe7a.0",
@ -86,6 +91,7 @@
"@types/uuid": "3.4.3",
"@typescript-eslint/eslint-plugin": "^5.29.0",
"@typescript-eslint/parser": "^5.29.0",
"concurrently": "7.3.0",
"dotenv": "16.0.0",
"eslint": "8.20.0",
"eslint-config-prettier": "8.5.0",
@ -103,11 +109,12 @@
"karma-coverage-istanbul-reporter": "3.0.3",
"karma-jasmine": "5.1.0",
"karma-jasmine-html-reporter": "2.0.0",
"ng-packagr": "14.1.0",
"ngx-build-plus": "14.0.0",
"prettier": "2.7.1",
"prettier-plugin-organize-attributes": "0.0.5",
"ts-mockito": "2.6.1",
"ts-node": "8.8.2",
"ts-node": "10.9.1",
"typescript": "4.7.4"
}
}

View File

@ -0,0 +1,16 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR

View File

@ -0,0 +1 @@
package.json

View File

@ -0,0 +1,25 @@
# NgCore
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 14.0.0.
## Code scaffolding
Run `ng generate component component-name --project ng-core` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ng-core`.
> Note: Don't forget to add `--project ng-core` or else it will be added to the default project in your `angular.json` file.
## Build
Run `ng build ng-core` to build the project. The build artifacts will be stored in the `dist/` directory.
## Publishing
After building your library with `ng build ng-core`, go to the dist folder `cd dist/ng-core` and run `npm publish`.
## Running unit tests
Run `ng test ng-core` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.

View File

@ -0,0 +1,41 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true, // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, '../../coverage/ng-core'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }],
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true,
});
};

View File

@ -0,0 +1,7 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/ng-core",
"lib": {
"entryFile": "src/public-api.ts"
}
}

View File

@ -0,0 +1,11 @@
{
"name": "@vality/ng-core",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^14.0.0",
"@angular/core": "^14.0.0"
},
"dependencies": {
"tslib": "^2.3.0"
}
}

View File

@ -0,0 +1,2 @@
export * from './actions.module';
export * from './actions.component';

View File

@ -9,7 +9,7 @@ import { BaseDialogResponseStatus } from './types/base-dialog-response-status';
styleUrls: ['base-dialog.component.scss'],
})
export class BaseDialogComponent {
@Input() title: string;
@Input() title!: string;
@coerceBoolean @Input() disabled = false;
@coerceBoolean @Input() inProgress = false;

View File

@ -7,8 +7,7 @@ import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { ActionsModule } from '@cc/components/actions';
import { ActionsModule } from '../actions';
import { BaseDialogComponent } from './base-dialog.component';
import { BaseDialogActionsComponent } from './components/base-dialog-actions/base-dialog-actions.component';
@ -21,7 +20,6 @@ const SHARED_DECLARATIONS = [BaseDialogComponent, BaseDialogActionsComponent];
MatDividerModule,
MatButtonModule,
ActionsModule,
ActionsModule,
MatIconModule,
MatProgressBarModule,
MatDialogModule,

View File

@ -0,0 +1,8 @@
export * from './base-dialog.module';
export * from './types/base-dialog-response-status';
export * from './types/base-dialog-response';
export * from './utils/base-dialog-superclass';
export * from './tokens';
export * from './base-dialog.component';
export * from './components/base-dialog-actions/base-dialog-actions.component';
export * from './services/base-dialog.service';

View File

@ -1,9 +1,10 @@
import { ComponentType } from '@angular/cdk/overlay';
import { Inject, Injectable } from '@angular/core';
import { Inject, Injectable, Optional } from '@angular/core';
import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
import { DIALOG_CONFIG, DialogConfig } from '@cc/app/tokens';
import { BaseDialogResponse, BaseDialogSuperclass } from '@cc/components/base-dialog';
import { DEFAULT_DIALOG_CONFIG, DIALOG_CONFIG, DialogConfig } from '../tokens';
import { BaseDialogResponse } from '../types/base-dialog-response';
import { BaseDialogSuperclass } from '../utils/base-dialog-superclass';
@Injectable({
providedIn: 'root',
@ -11,8 +12,12 @@ import { BaseDialogResponse, BaseDialogSuperclass } from '@cc/components/base-di
export class BaseDialogService {
constructor(
private dialog: MatDialog,
@Inject(DIALOG_CONFIG) private dialogConfig: DialogConfig
) {}
@Optional()
@Inject(DIALOG_CONFIG)
private readonly dialogConfig: DialogConfig
) {
if (!dialogConfig) this.dialogConfig = DEFAULT_DIALOG_CONFIG;
}
open<C, D, R, S>(
dialogComponent: ComponentType<BaseDialogSuperclass<C, D, R, S>>,
@ -25,12 +30,16 @@ export class BaseDialogService {
? []
: [data: D, configOrConfigName?: Omit<MatDialogConfig<D>, 'data'> | keyof DialogConfig]
): MatDialogRef<C, BaseDialogResponse<R, S>> {
let config: Partial<MatDialogConfig<D>>;
if (!configOrConfigName) config = {};
else if (typeof configOrConfigName === 'string')
config = this.dialogConfig[configOrConfigName];
else config = configOrConfigName;
return this.dialog.open(dialogComponent as never, {
data,
...(dialogComponent as typeof BaseDialogSuperclass).defaultDialogConfig,
...(typeof configOrConfigName === 'string'
? this.dialogConfig[configOrConfigName]
: configOrConfigName),
...config,
});
}
}

View File

@ -0,0 +1,20 @@
import { InjectionToken } from '@angular/core';
import { MatDialogConfig } from '@angular/material/dialog';
import { ValuesType } from 'utility-types';
export type DialogConfig = Record<'small' | 'medium' | 'large', MatDialogConfig<undefined>>;
export const DIALOG_CONFIG = new InjectionToken<DialogConfig>('dialogConfig');
export const BASE_CONFIG: ValuesType<DialogConfig> = {
maxHeight: '90vh',
disableClose: true,
autoFocus: false,
width: '552px',
};
export const DEFAULT_DIALOG_CONFIG: DialogConfig = {
small: { ...BASE_CONFIG, width: '360px' },
medium: BASE_CONFIG,
large: { ...BASE_CONFIG, width: '800px' },
};

View File

@ -1,4 +1,4 @@
import { BaseDialogResponseStatus } from '@cc/components/base-dialog';
import { BaseDialogResponseStatus } from './base-dialog-response-status';
export interface BaseDialogResponse<T = void, S = void> {
status: S | BaseDialogResponseStatus;

View File

@ -1,9 +1,9 @@
import { Directive, Injector } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DEFAULT_DIALOG_CONFIG } from '@cc/app/tokens';
import { DEFAULT_DIALOG_CONFIG } from '../tokens';
import { BaseDialogResponse } from '../types/base-dialog-response';
import { BaseDialogResponseStatus } from '../types/base-dialog-response-status';
@Directive()
export class BaseDialogSuperclass<
@ -19,4 +19,25 @@ export class BaseDialogSuperclass<
dialogRef = this.injector.get(MatDialogRef) as MatDialogRef<DialogComponent, DialogResponse>;
constructor(private injector: Injector) {}
closeWithCancellation(data?: DialogResponseData) {
this.dialogRef.close({
status: BaseDialogResponseStatus.Cancelled,
data,
} as never);
}
closeWithSuccess(data?: DialogResponseData) {
this.dialogRef.close({
status: BaseDialogResponseStatus.Success,
data,
} as never);
}
closeWithError(data?: DialogResponseData) {
this.dialogRef.close({
status: BaseDialogResponseStatus.Error,
data,
} as never);
}
}

View File

@ -0,0 +1,2 @@
export * from './actions';
export * from './base-dialog';

View File

@ -0,0 +1,2 @@
export * from './components';
export * from './utils';

View File

@ -0,0 +1,45 @@
import isEmpty from 'lodash-es/isEmpty';
import isNil from 'lodash-es/isNil';
import isObject from 'lodash-es/isObject';
import { ValuesType } from 'utility-types';
function isEmptyPrimitive(value: unknown): boolean {
return isNil(value) || value === '';
}
function isEmptyObjectOrPrimitive(value: unknown): boolean {
return isObject(value) ? isEmpty(value) : isEmptyPrimitive(value);
}
export function clean<T>(
value: T,
allowRootRemoval = false,
isNotDeep = false,
filterPredicate: (v: unknown, k?: PropertyKey) => boolean = (v) => !isEmptyObjectOrPrimitive(v)
): T | null {
if (!isObject(value)) return value;
if (allowRootRemoval && !filterPredicate(value as never)) return null;
let result: unknown;
const cleanChild = (v: unknown) =>
isNotDeep ? v : clean(v as never, allowRootRemoval, isNotDeep, filterPredicate);
if (Array.isArray(value))
result = (value as ValuesType<T>[])
.slice()
.map((v) => cleanChild(v))
.filter((v, idx) => filterPredicate(v, idx));
else
result = Object.fromEntries(
(Object.entries(value) as [keyof T, ValuesType<T>][])
.map(([k, v]) => [k, cleanChild(v)] as const)
.filter(([k, v]) => filterPredicate(v, k))
);
return allowRootRemoval && !filterPredicate(result) ? null : (result as never);
}
export function cleanPrimitiveProps<T extends object>(
obj: T,
allowRootRemoval = false,
isNotDeep = false
) {
return clean(obj, allowRootRemoval, isNotDeep, (v) => !isEmptyPrimitive(v));
}

View File

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

View File

@ -0,0 +1,5 @@
/*
* Public API Surface of ng-core
*/
export * from './lib';

View File

@ -0,0 +1,29 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js';
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
// eslint-disable-next-line @typescript-eslint/naming-convention
declare const require: {
context(
path: string,
deep?: boolean,
filter?: RegExp
): {
<T>(id: string): T;
keys(): string[];
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().forEach(context);

View File

@ -0,0 +1,21 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": [],
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitAny": true
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
"strictTemplates": true
},
"exclude": ["src/test.ts", "**/*.spec.ts"]
}

View File

@ -0,0 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"compilationMode": "partial"
}
}

View File

@ -0,0 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": ["jasmine"]
},
"files": ["src/test.ts"],
"include": ["**/*.spec.ts", "**/*.d.ts"]
}

View File

@ -1 +1,2 @@
export * from './party-management.service';
export * from './invoicing.service';

View File

@ -0,0 +1,22 @@
import { Injectable, Injector } from '@angular/core';
import {
codegenClientConfig,
CodegenClient,
} from '@vality/domain-proto/lib/payment_processing-Invoicing';
import context from '@vality/domain-proto/lib/payment_processing/context';
import * as service from '@vality/domain-proto/lib/payment_processing/gen-nodejs/Invoicing';
import { createThriftApi } from '@cc/app/api/utils';
@Injectable({ providedIn: 'root' })
export class InvoicingService extends createThriftApi<CodegenClient>() {
constructor(injector: Injector) {
super(injector, {
service,
path: '/v1/processing/invoicing',
metadata: () => import('@vality/domain-proto/lib/metadata.json').then((m) => m.default),
context,
...codegenClientConfig,
});
}
}

View File

@ -26,7 +26,6 @@ import { DomainModule } from './domain';
import icons from './icons.json';
import { NotFoundModule } from './not-found';
import { RepairingModule } from './repairing/repairing.module';
import { ClaimModule } from './sections/claim';
import { DomainConfigModule } from './sections/domain-config';
import { OperationsModule } from './sections/operations/operations.module';
import { PaymentAdjustmentModule } from './sections/payment-adjustment/payment-adjustment.module';
@ -36,12 +35,10 @@ import { SearchPartiesModule } from './sections/search-parties/search-parties.mo
import { SectionsModule } from './sections/sections.module';
import { ThemeManager, ThemeManagerModule, ThemeName } from './theme-manager';
import {
DEFAULT_DIALOG_CONFIG,
DEFAULT_MAT_DATE_FORMATS,
DEFAULT_QUERY_PARAMS_SERIALIZERS,
DEFAULT_SEARCH_LIMIT,
DEFAULT_SMALL_SEARCH_LIMIT,
DIALOG_CONFIG,
SEARCH_LIMIT,
SMALL_SEARCH_LIMIT,
} from './tokens';
@ -49,7 +46,7 @@ import {
/**
* For use in specific locations (for example, questionary PDF document)
*/
moment.locale('en');
moment.locale('en-GB');
@NgModule({
declarations: [AppComponent],
@ -74,7 +71,6 @@ moment.locale('en');
DomainConfigModule,
KeycloakTokenInfoModule,
PayoutsModule,
ClaimModule,
SectionsModule,
// It is important that NotFoundModule module should be last
NotFoundModule,
@ -83,11 +79,10 @@ moment.locale('en');
{ provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } },
{ provide: MAT_DATE_FORMATS, useValue: DEFAULT_MAT_DATE_FORMATS },
{ provide: DateAdapter, useClass: MomentUtcDateAdapter, deps: [MAT_DATE_LOCALE] },
{ provide: MAT_DATE_LOCALE, useValue: 'en' },
{ provide: MAT_DATE_LOCALE, useValue: 'ru' },
{ provide: LOCALE_ID, useValue: 'en' },
{ provide: SEARCH_LIMIT, useValue: DEFAULT_SEARCH_LIMIT },
{ provide: SMALL_SEARCH_LIMIT, useValue: DEFAULT_SMALL_SEARCH_LIMIT },
{ provide: DIALOG_CONFIG, useValue: DEFAULT_DIALOG_CONFIG },
{ provide: QUERY_PARAMS_SERIALIZERS, useValue: DEFAULT_QUERY_PARAMS_SERIALIZERS },
],
bootstrap: [AppComponent],

View File

@ -9,7 +9,7 @@ import { ClaimComponent } from './claim.component';
imports: [
RouterModule.forChild([
{
path: 'party/:partyID/claim/:claimID/new',
path: '',
component: ClaimComponent,
canActivate: [AppAuthGuardService],
data: {

View File

@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { BaseDialogResponseStatus, BaseDialogService } from '@vality/ng-core';
import {
BehaviorSubject,
combineLatest,
@ -19,8 +20,6 @@ import { ChangeStatusDialogComponent } from '@cc/app/sections/claim/components/c
import { AllowedClaimStatusesService } from '@cc/app/sections/claim/services/allowed-claim-statuses.service';
import { UploadFileService } from '@cc/app/sections/claim/services/upload-file.service';
import { NotificationService } from '@cc/app/shared/services/notification';
import { BaseDialogResponseStatus } from '@cc/components/base-dialog';
import { BaseDialogService } from '@cc/components/base-dialog/services/base-dialog.service';
import { getUnionKey, inProgressFrom, progressTo } from '@cc/utils';
import { AddModificationDialogComponent } from './components/add-modification-dialog/add-modification-dialog.component';

View File

@ -15,16 +15,15 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
import { RouterModule } from '@angular/router';
import { ActionsModule, BaseDialogModule } from '@vality/ng-core';
import { ngfModule } from 'angular-file';
import { MetadataFormModule, StatusModule } from '@cc/app/shared/components';
import { JsonViewerModule } from '@cc/app/shared/components/json-viewer/json-viewer.module';
import { ThriftPipesModule } from '@cc/app/shared/pipes';
import { ActionsModule } from '@cc/components/actions';
import { BaseDialogModule } from '@cc/components/base-dialog';
import { TimelineModule } from '@cc/components/timeline';
import { TimelineComponentsModule } from '../party-claim/changeset/timeline-components';
import { HumanizeDurationModule } from '../../shared/pipes/humanize-duration';
import { ClaimRoutingModule } from './claim-routing.module';
import { ClaimComponent } from './claim.component';
import { AddModificationDialogComponent } from './components/add-modification-dialog/add-modification-dialog.component';
@ -34,6 +33,8 @@ import { ModificationFormComponent } from './components/modification-form/modifi
import { ModificationUnitTimelineItemComponent } from './components/modification-unit-timeline-item/modification-unit-timeline-item.component';
import { ShopModificationTimelineItemComponent } from './components/shop-modification-timeline-item/shop-modification-timeline-item.component';
import { StatusModificationTimelineItemComponent } from './components/status-modification-timeline-item/status-modification-timeline-item.component';
import { TimelineItemHeaderComponent } from './components/timeline-item-header/timeline-item-header.component';
import { TimelineItemLoadingComponent } from './components/timeline-item-loading/timeline-item-loading.component';
@NgModule({
declarations: [
@ -45,6 +46,8 @@ import { StatusModificationTimelineItemComponent } from './components/status-mod
AddModificationDialogComponent,
ChangeStatusDialogComponent,
ModificationFormComponent,
TimelineItemHeaderComponent,
TimelineItemLoadingComponent,
],
imports: [
CommonModule,
@ -53,7 +56,6 @@ import { StatusModificationTimelineItemComponent } from './components/status-mod
RouterModule,
TimelineModule,
MatIconModule,
TimelineComponentsModule,
ThriftPipesModule,
MatExpansionModule,
JsonViewerModule,
@ -73,6 +75,7 @@ import { StatusModificationTimelineItemComponent } from './components/status-mod
MatProgressBarModule,
BaseDialogModule,
ActionsModule,
HumanizeDurationModule,
],
})
export class ClaimModule {}

View File

@ -9,12 +9,15 @@ import {
PartyModificationChange,
} from '@vality/domain-proto/lib/claim_management';
import { Party } from '@vality/domain-proto/lib/domain';
import {
BaseDialogResponseStatus,
BaseDialogSuperclass,
DEFAULT_DIALOG_CONFIG,
} from '@vality/ng-core';
import { BehaviorSubject } from 'rxjs';
import { ClaimManagementService } from '@cc/app/api/claim-management';
import { NotificationService } from '@cc/app/shared/services/notification';
import { DEFAULT_DIALOG_CONFIG } from '@cc/app/tokens';
import { BaseDialogResponseStatus, BaseDialogSuperclass } from '@cc/components/base-dialog';
import { inProgressFrom, progressTo } from '@cc/utils';
@UntilDestroy()

View File

@ -2,12 +2,12 @@ import { Component, Injector } from '@angular/core';
import { Validators, FormBuilder } from '@angular/forms';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { Claim, ClaimStatus } from '@vality/domain-proto/lib/claim_management';
import { BaseDialogResponseStatus, BaseDialogSuperclass } from '@vality/ng-core';
import { BehaviorSubject, Observable } from 'rxjs';
import { ClaimManagementService } from '@cc/app/api/claim-management';
import { AllowedClaimStatusesService } from '@cc/app/sections/claim/services/allowed-claim-statuses.service';
import { NotificationService } from '@cc/app/shared/services/notification';
import { BaseDialogResponseStatus, BaseDialogSuperclass } from '@cc/components/base-dialog';
import { getUnionKey, inProgressFrom, progressTo } from '@cc/utils';
@UntilDestroy()

View File

@ -2,10 +2,10 @@ import { Component, Injector, Input, OnChanges } from '@angular/core';
import { Validator } from '@angular/forms';
import { Claim } from '@vality/domain-proto/lib/claim_management';
import { Party } from '@vality/domain-proto/lib/domain';
import { from, Observable } from 'rxjs';
import { from, combineLatest, ReplaySubject, defer } from 'rxjs';
import { map } from 'rxjs/operators';
import { ComponentChanges, MetadataFormExtension } from '@cc/app/shared';
import { ComponentChanges } from '@cc/app/shared';
import { DomainMetadataFormExtensionsService } from '@cc/app/shared/services/domain-metadata-form-extensions';
import { createControlProviders, ValidatedFormControlSuperclass } from '@cc/utils';
@ -25,7 +25,14 @@ export class ModificationFormComponent
@Input() type: string;
metadata$ = from(import('@vality/domain-proto/lib/metadata.json').then((m) => m.default));
extensions$: Observable<MetadataFormExtension[]>;
extensions$ = combineLatest([
defer(() => this.claimOrPartyChanged$).pipe(
map(() => createPartyClaimMetadataFormExtensions(this.party, this.claim))
),
this.domainMetadataFormExtensionsService.extensions$,
]).pipe(map((extensionGroups) => extensionGroups.flat()));
private claimOrPartyChanged$ = new ReplaySubject<void>(1);
constructor(
injector: Injector,
@ -37,12 +44,7 @@ export class ModificationFormComponent
ngOnChanges(changes: ComponentChanges<ModificationFormComponent>) {
super.ngOnChanges(changes);
if (changes.party || changes.claim) {
this.extensions$ = this.domainMetadataFormExtensionsService.extensions$.pipe(
map((e) => [
...createPartyClaimMetadataFormExtensions(this.party, this.claim),
...e,
])
);
this.claimOrPartyChanged$.next();
}
}
}

View File

@ -109,9 +109,5 @@ export function createPartyClaimMetadataFormExtensions(
isIdentifier: true,
}),
},
{
determinant: (data) => of(isTypeWithAliases(data, 'ID', 'base')),
extension: () => of({ generate, isIdentifier: true }),
},
];
}

View File

@ -1,6 +1,7 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { Claim, ModificationUnit } from '@vality/domain-proto/lib/claim_management';
import { BaseDialogResponseStatus, BaseDialogService } from '@vality/ng-core';
import { coerceBoolean } from 'coerce-property';
import isEmpty from 'lodash-es/isEmpty';
import { BehaviorSubject, switchMap } from 'rxjs';
@ -12,8 +13,6 @@ import { getModificationName } from '@cc/app/sections/claim/utils/get-modificati
import { Patch } from '@cc/app/shared/components/json-viewer';
import { NotificationService } from '@cc/app/shared/services/notification';
import { Color, StatusColor } from '@cc/app/styles';
import { BaseDialogResponseStatus } from '@cc/components/base-dialog';
import { BaseDialogService } from '@cc/components/base-dialog/services/base-dialog.service';
import { ConfirmActionDialogComponent } from '@cc/components/confirm-action-dialog';
import { inProgressFrom, progressTo } from '@cc/utils';
import { getUnionValue } from '@cc/utils/get-union-key';

View File

@ -1,5 +1,6 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BaseDialogResponseStatus, BaseDialogService } from '@vality/ng-core';
import moment from 'moment';
import { switchMap } from 'rxjs';
import { filter, map } from 'rxjs/operators';
@ -7,8 +8,6 @@ import { filter, map } from 'rxjs/operators';
import { ClaimManagementService } from '@cc/app/api/claim-management';
import { FileStorageService } from '@cc/app/api/file-storage';
import { NotificationService } from '@cc/app/shared/services/notification';
import { BaseDialogResponseStatus } from '@cc/components/base-dialog';
import { BaseDialogService } from '@cc/components/base-dialog/services/base-dialog.service';
import { ConfirmActionDialogComponent } from '@cc/components/confirm-action-dialog';
@Injectable()

View File

@ -1,7 +0,0 @@
@import './changeset/timeline-components/timeline-item-loading/timeline-item-loading-theme';
@import './party-claim-title/party-claim-title-theme';
@mixin cc-party-claim-theme($theme) {
@include cc-party-claim-title-theme($theme);
@include cc-timeline-item-loading-theme($theme);
}

View File

@ -1,27 +0,0 @@
import { Modification, UserInfo } from '@vality/domain-proto/lib/claim_management';
/* eslint-disable @typescript-eslint/naming-convention */
export enum ChangesetInfoType {
partyModification = 'partyModification',
commentModification = 'commentModification',
fileModification = 'fileModification',
documentModification = 'documentModification',
statusModification = 'statusModification',
}
export enum ChangesetInfoModificationType {
creation = 'creation',
deletion = 'deletion',
}
/* eslint-enable @typescript-eslint/naming-convention */
export interface ChangesetInfo {
createdAt: string;
modification: Modification;
userInfo: UserInfo;
type: ChangesetInfoType;
modificationType: ChangesetInfoModificationType;
hash: string;
outdated?: boolean;
removed?: boolean;
}

View File

@ -1,2 +0,0 @@
export * from './to-changeset-infos';
export * from './changeset-info';

View File

@ -1,9 +0,0 @@
import { ChangesetInfo } from './changeset-info';
export const markOutdated = (infos: ChangesetInfo[], hash: string): ChangesetInfo[] =>
infos.map((info) => {
if (info.hash === hash) {
info.outdated = true;
}
return info;
});

View File

@ -1,9 +0,0 @@
import { ChangesetInfo } from './changeset-info';
export const markRemoved = (infos: ChangesetInfo[], hash: string): ChangesetInfo[] =>
infos.map((info) => {
if (info.hash === hash) {
info.removed = true;
}
return info;
});

View File

@ -1,43 +0,0 @@
import { ModificationUnit } from '@vality/domain-proto/lib/claim_management';
import { ChangesetInfo, ChangesetInfoType } from './changeset-info';
import { toCommentModificationChangesetInfo } from './to-comment-modification-changeset-info';
import { toDocumentModificationChangesetInfo } from './to-document-modification-changeset-info';
import { toFileModificationChangesetInfo } from './to-file-modification-changeset-info';
import { toPartyModificationChangesetInfo } from './to-party-modification-changeset-info';
import { toStatusModificationChangesetInfo } from './to-status-modification-changeset-info';
const getModificationType = (unit: ModificationUnit): ChangesetInfoType | null => {
if (unit.modification.party_modification) {
return ChangesetInfoType.partyModification;
} else if (unit.modification.claim_modification.comment_modification) {
return ChangesetInfoType.commentModification;
} else if (unit.modification.claim_modification.file_modification) {
return ChangesetInfoType.fileModification;
} else if (unit.modification.claim_modification.document_modification) {
return ChangesetInfoType.documentModification;
} else if (unit.modification.claim_modification.status_modification) {
return ChangesetInfoType.statusModification;
} else {
return null;
}
};
export const toChangesetInfos = (units: ModificationUnit[]): ChangesetInfo[] =>
units.reduce((acc, cur) => {
switch (getModificationType(cur)) {
case ChangesetInfoType.partyModification:
return toPartyModificationChangesetInfo(acc, cur);
case ChangesetInfoType.commentModification:
return toCommentModificationChangesetInfo(acc, cur);
case ChangesetInfoType.fileModification:
return toFileModificationChangesetInfo(acc, cur);
case ChangesetInfoType.documentModification:
return toDocumentModificationChangesetInfo(acc, cur);
case ChangesetInfoType.statusModification:
return toStatusModificationChangesetInfo(acc, cur);
default:
console.error('Changeset infos: Unknown type', cur);
return acc;
}
}, []);

View File

@ -1,38 +0,0 @@
import { CommentModification, ModificationUnit } from '@vality/domain-proto/lib/claim_management';
import { getUnionKey } from '@cc/utils/get-union-key';
import { ChangesetInfo, ChangesetInfoModificationType, ChangesetInfoType } from './changeset-info';
import { markRemoved } from './mark-removed';
const getCommentChangesetInfoHash = (unit: ModificationUnit): string =>
`${ChangesetInfoType.commentModification}.${unit.modification.claim_modification.comment_modification.id}`;
const commentModificationType = (mod: CommentModification): ChangesetInfoModificationType => {
switch (getUnionKey(mod)) {
case 'creation':
return ChangesetInfoModificationType.creation;
case 'deletion':
return ChangesetInfoModificationType.deletion;
}
};
const makeCommentChangesetInfo = (unit: ModificationUnit): ChangesetInfo =>
({
createdAt: unit.created_at,
modification: unit.modification,
userInfo: unit.user_info,
type: ChangesetInfoType.commentModification,
hash: getCommentChangesetInfoHash(unit),
modificationType: commentModificationType(
unit.modification.claim_modification.comment_modification.modification
),
} as ChangesetInfo);
export const toCommentModificationChangesetInfo = (
infos: ChangesetInfo[],
unit: ModificationUnit
): ChangesetInfo[] => {
const commentChangesetInfo = makeCommentChangesetInfo(unit);
return [...markRemoved(infos, commentChangesetInfo.hash), commentChangesetInfo];
};

View File

@ -1,23 +0,0 @@
import { ModificationUnit } from '@vality/domain-proto/lib/claim_management';
import { ChangesetInfo, ChangesetInfoType } from './changeset-info';
import { markOutdated } from './mark-outdated';
const getDocumentChangesetInfoHash = (): string => `${ChangesetInfoType.documentModification}`;
const makeDocumentChangesetInfo = (unit: ModificationUnit): ChangesetInfo =>
({
createdAt: unit.created_at,
modification: unit.modification,
userInfo: unit.user_info,
type: ChangesetInfoType.documentModification,
hash: getDocumentChangesetInfoHash(),
} as ChangesetInfo);
export const toDocumentModificationChangesetInfo = (
infos: ChangesetInfo[],
unit: ModificationUnit
): ChangesetInfo[] => {
const documentChangesetInfo = makeDocumentChangesetInfo(unit);
return [...markOutdated(infos, documentChangesetInfo.hash), documentChangesetInfo];
};

View File

@ -1,38 +0,0 @@
import { FileModification, ModificationUnit } from '@vality/domain-proto/lib/claim_management';
import { getUnionKey } from '@cc/utils/get-union-key';
import { ChangesetInfo, ChangesetInfoModificationType, ChangesetInfoType } from './changeset-info';
import { markRemoved } from './mark-removed';
const getFileChangesetInfoHash = (unit: ModificationUnit): string =>
`${ChangesetInfoType.fileModification}.${unit.modification.claim_modification.file_modification.id}`;
const fileModificationType = (mod: FileModification): ChangesetInfoModificationType => {
switch (getUnionKey(mod)) {
case 'creation':
return ChangesetInfoModificationType.creation;
case 'deletion':
return ChangesetInfoModificationType.deletion;
}
};
const makeFileChangesetInfo = (unit: ModificationUnit): ChangesetInfo =>
({
createdAt: unit.created_at,
modification: unit.modification,
userInfo: unit.user_info,
type: ChangesetInfoType.fileModification,
hash: getFileChangesetInfoHash(unit),
modificationType: fileModificationType(
unit.modification.claim_modification.file_modification.modification
),
} as ChangesetInfo);
export const toFileModificationChangesetInfo = (
infos: ChangesetInfo[],
unit: ModificationUnit
): ChangesetInfo[] => {
const fileChangesetInfo = makeFileChangesetInfo(unit);
return [...markRemoved(infos, fileChangesetInfo.hash), fileChangesetInfo];
};

View File

@ -1,31 +0,0 @@
import { ModificationUnit } from '@vality/domain-proto/lib/claim_management';
import { getUnionKey } from '@cc/utils/get-union-key';
import { ChangesetInfo, ChangesetInfoType } from './changeset-info';
import { markOutdated } from './mark-outdated';
const getHash = (m: any, acc: string = ''): string => {
if (m.id && m.modification) {
return `${acc}.${getUnionKey(m.modification) as string}`;
}
const unionKey = getUnionKey(m) as string;
return getHash(m[unionKey], `${acc}.${unionKey}`);
};
const makePartyChangesetInfo = (unit: ModificationUnit): ChangesetInfo =>
({
createdAt: unit.created_at,
modification: unit.modification,
userInfo: unit.user_info,
type: ChangesetInfoType.partyModification,
hash: getHash(unit.modification),
} as ChangesetInfo);
export const toPartyModificationChangesetInfo = (
infos: ChangesetInfo[],
unit: ModificationUnit
): ChangesetInfo[] => {
const partyChangesetInfo = makePartyChangesetInfo(unit);
return [...markOutdated(infos, partyChangesetInfo.hash), partyChangesetInfo];
};

View File

@ -1,17 +0,0 @@
import { ModificationUnit } from '@vality/domain-proto/lib/claim_management';
import { ChangesetInfo, ChangesetInfoType } from './changeset-info';
const makeStatusChangesetInfo = (unit: ModificationUnit): ChangesetInfo =>
({
createdAt: unit.created_at,
modification: unit.modification,
userInfo: unit.user_info,
type: ChangesetInfoType.statusModification,
hash: ChangesetInfoType.statusModification,
} as ChangesetInfo);
export const toStatusModificationChangesetInfo = (
infos: ChangesetInfo[],
unit: ModificationUnit
): ChangesetInfo[] => [...infos, makeStatusChangesetInfo(unit)];

View File

@ -1,35 +0,0 @@
<form [formGroup]="changesetsFilterForm">
<mat-form-field fxFlex>
<mat-label>Changeset filters</mat-label>
<mat-select formControlName="filters" multiple>
<mat-option class="changeset-filter-option" value="outdated"
>Hide outdated changes</mat-option
>
<mat-option class="changeset-filter-option" value="removed"
>Hide removed changes</mat-option
>
<mat-optgroup label="Modification filters">
<mat-option
[value]="changesetInfoType.partyModification"
class="changeset-filter-option"
>Party mods</mat-option
>
<mat-option
[value]="changesetInfoType.fileModification"
class="changeset-filter-option"
>Files</mat-option
>
<mat-option
[value]="changesetInfoType.commentModification"
class="changeset-filter-option"
>Comments</mat-option
>
<mat-option
[value]="changesetInfoType.documentModification"
class="changeset-filter-option"
>Documents</mat-option
>
</mat-optgroup>
</mat-select>
</mat-form-field>
</form>

View File

@ -1,3 +0,0 @@
::ng-deep .mat-select-panel {
max-height: 300px !important;
}

View File

@ -1,31 +0,0 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ChangesetInfo, ChangesetInfoType } from '../changeset-infos';
import { ChangesetsFilterService } from './changesets-filter.service';
@Component({
selector: 'cc-changesets-filter',
templateUrl: 'changesets-filter.component.html',
styleUrls: ['changesets-filter.component.scss'],
providers: [ChangesetsFilterService],
})
export class ChangesetsFilterComponent implements OnInit {
@Input()
set changesetInfos(v: ChangesetInfo[]) {
this.changesetsFilterService.setChangesetInfos(v);
}
@Output()
filterChange: EventEmitter<ChangesetInfo[]> = new EventEmitter();
changesetsFilterForm = this.changesetsFilterService.changesetsFilterForm;
changesetInfoType = ChangesetInfoType;
constructor(private changesetsFilterService: ChangesetsFilterService) {}
ngOnInit(): void {
this.changesetsFilterService.filteredChangesetInfos$.subscribe((infos) => {
this.filterChange.emit(infos);
});
}
}

View File

@ -1,14 +0,0 @@
import { NgModule } from '@angular/core';
import { FlexModule } from '@angular/flex-layout';
import { ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { ChangesetsFilterComponent } from './changesets-filter.component';
@NgModule({
declarations: [ChangesetsFilterComponent],
imports: [ReactiveFormsModule, MatFormFieldModule, MatSelectModule, FlexModule],
exports: [ChangesetsFilterComponent],
})
export class ChangesetsFilterModule {}

View File

@ -1,42 +0,0 @@
import { Injectable } from '@angular/core';
import { UntypedFormBuilder } from '@angular/forms';
import { combineLatest, Subject } from 'rxjs';
import { map, shareReplay, startWith } from 'rxjs/operators';
import { ChangesetInfo, ChangesetInfoType } from '../changeset-infos';
import { infosFilter } from './infos-filter';
@Injectable()
export class ChangesetsFilterService {
private changesetInfos$ = new Subject<ChangesetInfo[]>();
// eslint-disable-next-line @typescript-eslint/member-ordering
changesetsFilterForm = this.fb.group({
filters: [
[
ChangesetInfoType.documentModification,
ChangesetInfoType.commentModification,
ChangesetInfoType.fileModification,
ChangesetInfoType.partyModification,
ChangesetInfoType.statusModification,
],
],
});
// eslint-disable-next-line @typescript-eslint/member-ordering
filteredChangesetInfos$ = combineLatest([
this.changesetInfos$,
this.changesetsFilterForm.valueChanges.pipe(startWith(this.changesetsFilterForm.value)),
]).pipe(
map(([infos, { filters }]) => infos.filter((info) => infosFilter(info, filters))),
shareReplay(1)
);
constructor(private fb: UntypedFormBuilder) {
this.filteredChangesetInfos$.subscribe();
}
setChangesetInfos(changesetInfos: ChangesetInfo[]) {
this.changesetInfos$.next(changesetInfos);
}
}

View File

@ -1 +0,0 @@
export * from './changesets-filter.module';

View File

@ -1,13 +0,0 @@
import { ChangesetInfo } from '../changeset-infos';
export const infosFilter = (info: ChangesetInfo, filters: string[]) => {
if (
filters.length === 0 ||
(info.outdated && filters.includes('outdated')) ||
(info.removed && filters.includes('removed'))
) {
return false;
} else {
return filters.includes(info.type);
}
};

View File

@ -1,39 +0,0 @@
<div fxLayout="column" fxLayoutGap="24px">
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center" fxLayoutGap="16px">
<h3 class="cc-title">Changeset</h3>
<cc-changesets-filter
[changesetInfos]="changesetInfos$ | async"
fxFlex="0 1 266px"
(filterChange)="filterChange($event)"
></cc-changesets-filter>
</div>
<cc-timeline>
<cc-created-timeline-item [createdAt]="createdAt"></cc-created-timeline-item>
<ng-container
*ngFor="let info of filteredChangesetInfos; let i = index; trackBy: simpleTrackBy"
>
<cc-file-timeline-item
*ngIf="info.type === changesetInfoType.fileModification"
[changesetInfo]="info"
[menuConfig]="fileMenuConfig"
(menuItemSelected)="menuItemSelected($event, i)"
></cc-file-timeline-item>
<cc-comment-timeline-item
*ngIf="info.type === changesetInfoType.commentModification"
[changesetInfo]="info"
[menuConfig]="commentMenuConfig"
(menuItemSelected)="menuItemSelected($event, i)"
></cc-comment-timeline-item>
<cc-party-modification-timeline-item
*ngIf="info.type === changesetInfoType.partyModification"
[changesetInfo]="info"
[menuConfig]="partyModMenuConfig"
(menuItemSelected)="menuItemSelected($event, i)"
></cc-party-modification-timeline-item>
<cc-status-timeline-item
*ngIf="info.type === changesetInfoType.statusModification"
[changesetInfo]="info"
></cc-status-timeline-item>
</ng-container>
</cc-timeline>
</div>

View File

@ -1,53 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { PartyID } from '@vality/domain-proto';
import { ClaimChangeset } from '@vality/domain-proto/lib/claim_management';
import { BehaviorSubject } from 'rxjs';
import { ChangesetInfo, ChangesetInfoType, toChangesetInfos } from '../changeset-infos';
import { MenuConfigAction, MenuConfigItem } from '../timeline-items/menu-config';
import { ClaimChangesetService } from './claim-changeset.service';
@Component({
selector: 'cc-claim-changeset',
templateUrl: 'claim-changeset.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [ClaimChangesetService],
})
export class ClaimChangesetComponent {
@Input()
createdAt: string;
@Input()
set changeset(v: ClaimChangeset) {
this.changesetInfos$.next(toChangesetInfos(v));
}
@Input()
partyID: PartyID;
fileMenuConfig: MenuConfigItem[] = [
{ action: MenuConfigAction.deleteFile, label: 'Delete file' },
];
commentMenuConfig: MenuConfigItem[] = [
{ action: MenuConfigAction.deleteComment, label: 'Delete comment' },
];
partyModMenuConfig: MenuConfigItem[] = [];
changesetInfoType = ChangesetInfoType;
changesetInfos$ = new BehaviorSubject<ChangesetInfo[]>([]);
filteredChangesetInfos: ChangesetInfo[] = [];
constructor(private claimChangesetService: ClaimChangesetService) {}
simpleTrackBy(index: number): number {
return index;
}
filterChange($event: ChangesetInfo[]) {
this.filteredChangesetInfos = $event;
}
menuItemSelected($event: MenuConfigItem, i: number) {
this.claimChangesetService.menuItemSelected($event, this.changesetInfos$.getValue(), i);
}
}

View File

@ -1,38 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FlexModule } from '@angular/flex-layout';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { PartyModificationFormsModule } from '@cc/app/shared/components';
import { TimelineModule } from '@cc/components/timeline';
import { ChangesetsFilterModule } from '../changesets-filter';
import { CommentTimelineItemModule } from '../timeline-items/comment-timeline-item/comment-timeline-item.module';
import { CreatedTimelineItemModule } from '../timeline-items/created-timeline-item';
import { FileTimelineItemModule } from '../timeline-items/file-timeline-item/file-timeline-item.module';
import { PartyModificationTimelineItemModule } from '../timeline-items/party-modification-timeline-item/party-modification-timeline-item.module';
import { StatusTimelineItemModule } from '../timeline-items/status-timeline-item/status-timeline-item.module';
import { SaveClaimChangesetService } from '../unsaved-changeset/save-claim-changeset.service';
import { ClaimChangesetComponent } from './claim-changeset.component';
@NgModule({
imports: [
FlexModule,
CommonModule,
ChangesetsFilterModule,
TimelineModule,
MatDialogModule,
MatButtonModule,
PartyModificationFormsModule,
CreatedTimelineItemModule,
FileTimelineItemModule,
CommentTimelineItemModule,
PartyModificationTimelineItemModule,
StatusTimelineItemModule,
],
declarations: [ClaimChangesetComponent],
providers: [SaveClaimChangesetService],
exports: [ClaimChangesetComponent],
})
export class ClaimChangesetModule {}

View File

@ -1,30 +0,0 @@
import { Injectable } from '@angular/core';
import { ChangesetInfo } from '../changeset-infos';
import { MenuConfigAction, MenuConfigItem } from '../timeline-items/menu-config';
import { UnsavedClaimChangesetService } from '../unsaved-changeset/unsaved-claim-changeset.service';
import { createDeleteCommentModification } from './create-delete-comment-modification';
import { createDeleteFileModification } from './create-delete-file-modification';
@Injectable()
export class ClaimChangesetService {
constructor(private unsavedClaimChangesetService: UnsavedClaimChangesetService) {}
menuItemSelected($event: MenuConfigItem, changesetInfos: ChangesetInfo[], index: number) {
const changesetInfo = changesetInfos[index];
switch ($event.action) {
case MenuConfigAction.deleteComment:
this.unsavedClaimChangesetService.addModification(
createDeleteCommentModification(changesetInfo)
);
break;
case MenuConfigAction.deleteFile:
this.unsavedClaimChangesetService.addModification(
createDeleteFileModification(changesetInfo)
);
break;
default:
console.warn('Unsupported method', $event);
}
}
}

View File

@ -1,14 +0,0 @@
import { Modification } from '@vality/domain-proto/lib/claim_management';
import { ChangesetInfo } from '../changeset-infos';
export const createDeleteCommentModification = (info: ChangesetInfo): Modification => ({
claim_modification: {
comment_modification: {
id: info.modification.claim_modification.comment_modification.id,
modification: {
deletion: {},
},
},
},
});

View File

@ -1,14 +0,0 @@
import { Modification } from '@vality/domain-proto/lib/claim_management';
import { ChangesetInfo } from '../changeset-infos';
export const createDeleteFileModification = (info: ChangesetInfo): Modification => ({
claim_modification: {
file_modification: {
id: info.modification.claim_modification.file_modification.id,
modification: {
deletion: {},
},
},
},
});

View File

@ -1,2 +0,0 @@
export * from './claim-changeset/claim-changeset.module';
export * from './unsaved-changeset/unsaved-claim-changeset.module';

View File

@ -1 +0,0 @@
export * from './timeline-components.module';

View File

@ -1,23 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { HumanizeDurationModule } from '@cc/app/shared/pipes/humanize-duration';
import { TimelineItemErrorComponent } from './timeline-item-error/timeline-item-error.component';
import { TimelineItemHeaderComponent } from './timeline-item-header/timeline-item-header.component';
import { TimelineItemLoadingComponent } from './timeline-item-loading/timeline-item-loading.component';
@NgModule({
declarations: [
TimelineItemLoadingComponent,
TimelineItemErrorComponent,
TimelineItemHeaderComponent,
],
imports: [CommonModule, HumanizeDurationModule],
exports: [
TimelineItemLoadingComponent,
TimelineItemErrorComponent,
TimelineItemHeaderComponent,
],
})
export class TimelineComponentsModule {}

View File

@ -1,11 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
@Component({
selector: 'cc-timeline-item-error',
templateUrl: 'timeline-item-error.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TimelineItemErrorComponent {
@Input()
text: string;
}

View File

@ -1,17 +0,0 @@
import { Pipe, PipeTransform } from '@angular/core';
import { ChangesetInfoModificationType } from '../../changeset-infos';
@Pipe({
name: 'ccCommentActionIcon',
})
export class CommentActionIconPipe implements PipeTransform {
transform(type: ChangesetInfoModificationType): string {
return (
{
[ChangesetInfoModificationType.creation]: 'add_comment',
[ChangesetInfoModificationType.deletion]: 'clear',
} as const
)[type];
}
}

View File

@ -1,17 +0,0 @@
import { Pipe, PipeTransform } from '@angular/core';
import { ChangesetInfoModificationType } from '../../changeset-infos';
@Pipe({
name: 'ccCommentBadgeColor',
})
export class CommentBadgeColorPipe implements PipeTransform {
transform(type: ChangesetInfoModificationType): 'primary' | 'warn' | 'error' | 'success' {
return (
{
[ChangesetInfoModificationType.creation]: 'primary',
[ChangesetInfoModificationType.deletion]: null,
} as const
)[type];
}
}

View File

@ -1,5 +0,0 @@
<mat-card>
<mat-card-content>
{{ text }}
</mat-card-content>
</mat-card>

View File

@ -1,10 +0,0 @@
import { Component, Input } from '@angular/core';
@Component({
selector: 'cc-comment-content',
templateUrl: 'comment-content.component.html',
})
export class CommentContentComponent {
@Input()
text: string;
}

View File

@ -1,17 +0,0 @@
import { Pipe, PipeTransform } from '@angular/core';
import { ChangesetInfoModificationType } from '../../changeset-infos';
@Pipe({
name: 'ccCommentHeader',
})
export class CommentHeaderPipe implements PipeTransform {
transform(type: ChangesetInfoModificationType): string {
return (
{
[ChangesetInfoModificationType.creation]: 'added message',
[ChangesetInfoModificationType.deletion]: 'removed message',
} as const
)[type];
}
}

View File

@ -1,39 +0,0 @@
<cc-timeline-item>
<cc-timeline-item-title>
<cc-timeline-item-header
[createdAt]="changesetInfo.createdAt"
[removed]="changesetInfo.removed"
[text]="changesetInfo.modificationType | ccCommentHeader"
[username]="changesetInfo.userInfo.username"
></cc-timeline-item-header>
<div *ngIf="menuConfig.length > 0">
<button [matMenuTriggerFor]="menu" mat-icon-button>
<mat-icon>more_horiz</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button *ngFor="let item of menuConfig" mat-menu-item (click)="action(item)">
{{ item.label }}
</button>
</mat-menu>
</div>
</cc-timeline-item-title>
<cc-timeline-item-badge
[color]="
changesetInfo.removed ? (changesetInfo.modificationType | ccCommentBadgeColor) : null
"
>
<mat-icon>{{ changesetInfo.modificationType | ccCommentActionIcon }}</mat-icon>
</cc-timeline-item-badge>
<cc-timeline-item-content fxLayout="column" fxLayoutGap="24px">
<cc-comment-content
*ngIf="message$ | async as message"
[text]="message.text"
></cc-comment-content>
<cc-timeline-item-loading *ngIf="isLoading$ | async"></cc-timeline-item-loading>
<cc-timeline-item-error
*ngIf="error$ | async as error"
[text]="error"
></cc-timeline-item-error>
</cc-timeline-item-content>
</cc-timeline-item>

View File

@ -1,30 +0,0 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { ChangesetInfo } from '../../changeset-infos';
import { TimelimeItemComponent } from '../timelime-item.component';
import { CommentTimelineItemService } from './comment-timeline-item.service';
@Component({
selector: 'cc-comment-timeline-item',
templateUrl: 'comment-timeline-item.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [CommentTimelineItemService],
})
export class CommentTimelineItemComponent extends TimelimeItemComponent implements OnInit {
@Input()
changesetInfo: ChangesetInfo;
isLoading$ = this.commentTimelineItemService.isLoading$;
message$ = this.commentTimelineItemService.message$;
error$ = this.commentTimelineItemService.error$;
constructor(private commentTimelineItemService: CommentTimelineItemService) {
super();
}
ngOnInit(): void {
this.commentTimelineItemService.getMessage([
this.changesetInfo.modification.claim_modification.comment_modification.id,
]);
}
}

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