Pull request #122: Audit screen
Merge in RED/ui from audit-screen to master * commit '4eb466f6267b6987e1ce4daafaa295c60406fe70': Hide audit outside of dev mode Filter by date Filter by user Audit screen
This commit is contained in:
commit
a9f6cd672a
@ -88,7 +88,7 @@ import { ColorPickerModule } from 'ngx-color-picker';
|
|||||||
import { AceEditorModule } from 'ng2-ace-editor';
|
import { AceEditorModule } from 'ng2-ace-editor';
|
||||||
import { TeamMembersComponent } from './components/team-members/team-members.component';
|
import { TeamMembersComponent } from './components/team-members/team-members.component';
|
||||||
import { AdminBreadcrumbsComponent } from './components/admin-page-header/admin-breadcrumbs.component';
|
import { AdminBreadcrumbsComponent } from './components/admin-page-header/admin-breadcrumbs.component';
|
||||||
import { UserListingScreenComponent } from './screens/admin/users/user-listing-screen.component';
|
import { UserListingScreenComponent } from './screens/admin/user-listing-screen/user-listing-screen.component';
|
||||||
import { NotificationsComponent } from './components/notifications/notifications.component';
|
import { NotificationsComponent } from './components/notifications/notifications.component';
|
||||||
import { RulesScreenComponent } from './screens/admin/rules-screen/rules-screen.component';
|
import { RulesScreenComponent } from './screens/admin/rules-screen/rules-screen.component';
|
||||||
import { WatermarkScreenComponent } from './screens/admin/watermark-screen/watermark-screen.component';
|
import { WatermarkScreenComponent } from './screens/admin/watermark-screen/watermark-screen.component';
|
||||||
@ -116,6 +116,8 @@ import { NgxChartsModule } from '@swimlane/ngx-charts';
|
|||||||
import { ComboChartComponent, ComboSeriesVerticalComponent } from './screens/admin/license-information-screen/combo-chart';
|
import { ComboChartComponent, ComboSeriesVerticalComponent } from './screens/admin/license-information-screen/combo-chart';
|
||||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||||
import { ForceRedactionDialogComponent } from './dialogs/force-redaction-dialog/force-redaction-dialog.component';
|
import { ForceRedactionDialogComponent } from './dialogs/force-redaction-dialog/force-redaction-dialog.component';
|
||||||
|
import { AuditScreenComponent } from './screens/admin/audit-screen/audit-screen.component';
|
||||||
|
import { PaginationComponent } from './components/pagination/pagination.component';
|
||||||
|
|
||||||
export function HttpLoaderFactory(httpClient: HttpClient) {
|
export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||||
@ -278,6 +280,14 @@ const routes = [
|
|||||||
data: {
|
data: {
|
||||||
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard]
|
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'audit',
|
||||||
|
component: AuditScreenComponent,
|
||||||
|
canActivate: [CompositeRouteGuard],
|
||||||
|
data: {
|
||||||
|
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -378,7 +388,9 @@ const matImports = [
|
|||||||
DigitalSignatureScreenComponent,
|
DigitalSignatureScreenComponent,
|
||||||
RemoveAnnotationsDialogComponent,
|
RemoveAnnotationsDialogComponent,
|
||||||
ComboChartComponent,
|
ComboChartComponent,
|
||||||
ComboSeriesVerticalComponent
|
ComboSeriesVerticalComponent,
|
||||||
|
AuditScreenComponent,
|
||||||
|
PaginationComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
@ -26,6 +26,15 @@
|
|||||||
*ngIf="root && permissionService.isAdmin()"
|
*ngIf="root && permissionService.isAdmin()"
|
||||||
></a>
|
></a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
class="breadcrumb"
|
||||||
|
[routerLink]="'/ui/admin/audit'"
|
||||||
|
[routerLinkActiveOptions]="{ exact: true }"
|
||||||
|
routerLinkActive="active"
|
||||||
|
translate="audit"
|
||||||
|
*ngIf="root && permissionService.isAdmin() && userPreferenceService.areDevFeaturesEnabled"
|
||||||
|
></a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
class="breadcrumb"
|
class="breadcrumb"
|
||||||
[routerLink]="'/ui/admin/users'"
|
[routerLink]="'/ui/admin/users'"
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
<div translate="pagination.previous" class="page" [class.disabled]="currentPage < 2" (click)="selectPage(currentPage - 1)"></div>
|
||||||
|
<span>|</span>
|
||||||
|
<div *ngFor="let page of displayedPages" class="page" [class.dots]="page === '...'" [class.active]="page === currentPage" (click)="selectPage(page)">
|
||||||
|
{{ displayValue(page) }}
|
||||||
|
</div>
|
||||||
|
<span>|</span>
|
||||||
|
<div translate="pagination.next" class="page" [class.disabled]="currentPage === totalPages - 1" (click)="selectPage(currentPage + 1)"></div>
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
@import '../../../assets/styles/red-variables';
|
||||||
|
|
||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
> *:not(:last-child) {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled,
|
||||||
|
span {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.disabled,
|
||||||
|
&.dots {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: $primary;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
|
||||||
|
const DISPLAYED_ITEMS = 5;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-pagination',
|
||||||
|
templateUrl: './pagination.component.html',
|
||||||
|
styleUrls: ['./pagination.component.scss']
|
||||||
|
})
|
||||||
|
export class PaginationComponent implements OnInit {
|
||||||
|
private _currentPage: number;
|
||||||
|
private _totalPages: number;
|
||||||
|
|
||||||
|
public displayedPages: (number | string)[];
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
public set settings(value: { currentPage: number; totalPages: number }) {
|
||||||
|
this._currentPage = value.currentPage;
|
||||||
|
this._totalPages = value.totalPages;
|
||||||
|
this._updatePagesArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public get currentPage() {
|
||||||
|
return this._currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get totalPages() {
|
||||||
|
return this._totalPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Output() pageChanged = new EventEmitter<number>();
|
||||||
|
|
||||||
|
public displayed;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
private _updatePagesArray() {
|
||||||
|
this.displayedPages = [0];
|
||||||
|
if (Math.max(1, this.currentPage - 1) > 1) {
|
||||||
|
this.displayedPages.push('...');
|
||||||
|
}
|
||||||
|
for (let page = Math.max(1, this.currentPage - 1); page <= Math.min(this.currentPage + 1, this.totalPages - 1); ++page) {
|
||||||
|
this.displayedPages.push(page);
|
||||||
|
}
|
||||||
|
if (Math.min(this.currentPage + 1, this.totalPages - 1) !== this.totalPages - 1) {
|
||||||
|
if (this.currentPage + 1 < this.totalPages - 2) {
|
||||||
|
this.displayedPages.push('...');
|
||||||
|
}
|
||||||
|
this.displayedPages.push(this.totalPages - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get allDisplayed(): boolean {
|
||||||
|
return this.totalPages > DISPLAYED_ITEMS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public selectPage(page: number | string) {
|
||||||
|
if (page !== '...') {
|
||||||
|
this.pageChanged.emit(page as number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public displayValue(page: number | string) {
|
||||||
|
return page === '...' ? page : (page as number) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
<section>
|
||||||
|
<div class="page-header">
|
||||||
|
<redaction-admin-breadcrumbs class="flex-1" [root]="true"></redaction-admin-breadcrumbs>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
<redaction-circle-button
|
||||||
|
class="ml-6"
|
||||||
|
*ngIf="permissionsService.isUser()"
|
||||||
|
[routerLink]="['/ui/projects/']"
|
||||||
|
tooltip="common.close"
|
||||||
|
tooltipPosition="before"
|
||||||
|
icon="red:close"
|
||||||
|
></redaction-circle-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="red-content-inner">
|
||||||
|
<div class="left-container">
|
||||||
|
<div class="header-item">
|
||||||
|
<span class="all-caps-label">
|
||||||
|
{{ 'audit-screen.table-header.title' | translate: { length: logs?.totalHits || 0 } }}
|
||||||
|
</span>
|
||||||
|
<div class="actions-wrapper">
|
||||||
|
<redaction-pagination
|
||||||
|
[settings]="{ currentPage: logs?.page || 0, totalPages: totalPages }"
|
||||||
|
(pageChanged)="pageChanged($event)"
|
||||||
|
></redaction-pagination>
|
||||||
|
<div class="separator">·</div>
|
||||||
|
<form [formGroup]="filterForm">
|
||||||
|
<div class="red-input-group w-150 mr-20">
|
||||||
|
<mat-form-field class="no-label">
|
||||||
|
<mat-select formControlName="category">
|
||||||
|
<mat-option *ngFor="let category of categories" [value]="category">
|
||||||
|
{{ category | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="red-input-group w-150">
|
||||||
|
<mat-form-field class="no-label">
|
||||||
|
<mat-select formControlName="userId">
|
||||||
|
<mat-select-trigger>
|
||||||
|
<redaction-initials-avatar
|
||||||
|
*ngIf="filterForm.get('userId').value !== ALL_USERS"
|
||||||
|
size="small"
|
||||||
|
[userId]="filterForm.get('userId').value"
|
||||||
|
[withName]="true"
|
||||||
|
></redaction-initials-avatar>
|
||||||
|
<div *ngIf="filterForm.get('userId').value === ALL_USERS" [translate]="ALL_USERS"></div>
|
||||||
|
</mat-select-trigger>
|
||||||
|
<mat-option *ngFor="let userId of userIds" [value]="userId">
|
||||||
|
<redaction-initials-avatar
|
||||||
|
*ngIf="userId !== ALL_USERS"
|
||||||
|
size="small"
|
||||||
|
[userId]="userId"
|
||||||
|
[withName]="true"
|
||||||
|
></redaction-initials-avatar>
|
||||||
|
<div *ngIf="userId === ALL_USERS" [translate]="ALL_USERS"></div>
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="separator">·</div>
|
||||||
|
<div class="red-input-group datepicker-wrapper mr-20">
|
||||||
|
<input placeholder="dd/mm/yy" [matDatepicker]="fromPicker" formControlName="from" />
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="fromPicker">
|
||||||
|
<mat-icon matDatepickerToggleIcon svgIcon="red:calendar"></mat-icon>
|
||||||
|
</mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #fromPicker></mat-datepicker>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mr-20" translate="audit-screen.to"></div>
|
||||||
|
|
||||||
|
<div class="red-input-group datepicker-wrapper">
|
||||||
|
<input placeholder="dd/mm/yy" [matDatepicker]="toPicker" formControlName="to" />
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="toPicker">
|
||||||
|
<mat-icon matDatepickerToggleIcon svgIcon="red:calendar"></mat-icon>
|
||||||
|
</mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #toPicker></mat-datepicker>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-header" redactionSyncWidth="table-item">
|
||||||
|
<redaction-table-col-name label="audit-screen.table-col-names.message" column="message"></redaction-table-col-name>
|
||||||
|
<redaction-table-col-name label="audit-screen.table-col-names.date" column="date"></redaction-table-col-name>
|
||||||
|
<redaction-table-col-name label="audit-screen.table-col-names.user" column="user"></redaction-table-col-name>
|
||||||
|
<redaction-table-col-name label="audit-screen.table-col-names.category" column="category"></redaction-table-col-name>
|
||||||
|
<div class="scrollbar-placeholder"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<cdk-virtual-scroll-viewport [itemSize]="100" redactionHasScrollbar>
|
||||||
|
<div class="table-item pointer" *cdkVirtualFor="let log of logs?.data">
|
||||||
|
<div>
|
||||||
|
{{ log.message }}
|
||||||
|
</div>
|
||||||
|
<div class="small-label">
|
||||||
|
{{ log.recordDate | date: 'd MMM. yyyy, hh:mm a' }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<redaction-initials-avatar size="small" [userId]="log.userId" [withName]="true"></redaction-initials-avatar>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ log.category }}
|
||||||
|
</div>
|
||||||
|
<div class="scrollbar-placeholder"></div>
|
||||||
|
</div>
|
||||||
|
</cdk-virtual-scroll-viewport>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<redaction-full-page-loading-indicator [displayed]="!viewReady"></redaction-full-page-loading-indicator>
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
.left-container {
|
||||||
|
width: 100vw;
|
||||||
|
|
||||||
|
.header-item {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions-wrapper,
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.red-input-group {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
margin: 0 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-20 {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cdk-virtual-scroll-viewport {
|
||||||
|
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr 11px;
|
||||||
|
|
||||||
|
.table-item {
|
||||||
|
> div {
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-scrollbar:hover {
|
||||||
|
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { PermissionsService } from '../../../common/service/permissions.service';
|
||||||
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
|
import { AuditControllerService, AuditResponse, AuditSearchRequest } from '@redaction/red-ui-http';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { Moment } from 'moment';
|
||||||
|
|
||||||
|
const PAGE_SIZE = 5;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-audit-screen',
|
||||||
|
templateUrl: './audit-screen.component.html',
|
||||||
|
styleUrls: ['./audit-screen.component.scss']
|
||||||
|
})
|
||||||
|
export class AuditScreenComponent {
|
||||||
|
public filterForm: FormGroup;
|
||||||
|
public viewReady = false;
|
||||||
|
public categories: string[] = [];
|
||||||
|
public userIds: Set<string>;
|
||||||
|
public logs: AuditResponse;
|
||||||
|
public currentPage = 1;
|
||||||
|
|
||||||
|
public ALL_CATEGORIES = 'audit-screen.all-categories';
|
||||||
|
public ALL_USERS = 'audit-screen.all-users';
|
||||||
|
|
||||||
|
private _previousFrom: Moment;
|
||||||
|
private _previousTo: Moment;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public readonly permissionsService: PermissionsService,
|
||||||
|
private readonly _formBuilder: FormBuilder,
|
||||||
|
private readonly _auditControllerService: AuditControllerService,
|
||||||
|
private readonly _translateService: TranslateService
|
||||||
|
) {
|
||||||
|
this.filterForm = this._formBuilder.group({
|
||||||
|
category: [this.ALL_CATEGORIES],
|
||||||
|
userId: [this.ALL_USERS],
|
||||||
|
from: [],
|
||||||
|
to: []
|
||||||
|
});
|
||||||
|
|
||||||
|
this.filterForm.valueChanges.subscribe((value) => {
|
||||||
|
if (!this._updateDateFilters(value)) {
|
||||||
|
this._fetchData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _updateDateFilters(value): boolean {
|
||||||
|
if (!!value.to && !!value.from) {
|
||||||
|
if (this._previousFrom !== value.from) {
|
||||||
|
if (value.to.isBefore(value.from)) {
|
||||||
|
this.filterForm.patchValue({ to: value.from });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (this._previousTo !== value.to) {
|
||||||
|
if (value.to.isBefore(value.from)) {
|
||||||
|
this.filterForm.patchValue({ from: value.to });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._previousFrom = this.filterForm.get('from').value;
|
||||||
|
this._previousTo = this.filterForm.get('to').value;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _fetchData(page?: number) {
|
||||||
|
this.viewReady = false;
|
||||||
|
const promises = [];
|
||||||
|
const category = this.filterForm.get('category').value;
|
||||||
|
const userId = this.filterForm.get('userId').value;
|
||||||
|
const from = this.filterForm.get('from').value;
|
||||||
|
let to = this.filterForm.get('to').value;
|
||||||
|
if (!!to) {
|
||||||
|
to = to.clone().add(1, 'd');
|
||||||
|
}
|
||||||
|
const logsRequestBody: AuditSearchRequest = {
|
||||||
|
pageSize: PAGE_SIZE,
|
||||||
|
withTotalHits: true,
|
||||||
|
page: page,
|
||||||
|
category: category === this.ALL_CATEGORIES ? undefined : category,
|
||||||
|
userId: userId === this.ALL_USERS ? undefined : userId,
|
||||||
|
from,
|
||||||
|
to
|
||||||
|
};
|
||||||
|
|
||||||
|
promises.push(this._auditControllerService.getAuditCategories().toPromise());
|
||||||
|
promises.push(this._auditControllerService.searchAuditLog(logsRequestBody).toPromise());
|
||||||
|
|
||||||
|
Promise.all(promises).then((data) => {
|
||||||
|
this.categories = data[0].map((c) => c.category);
|
||||||
|
this.categories.splice(0, 0, this.ALL_CATEGORIES);
|
||||||
|
this.logs = data[1];
|
||||||
|
this.userIds = new Set<string>([this.ALL_USERS]);
|
||||||
|
for (const id of this.logs.data.map((log) => log.userId).filter((uid) => !!uid)) {
|
||||||
|
this.userIds.add(id);
|
||||||
|
}
|
||||||
|
this.viewReady = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public get totalPages(): number {
|
||||||
|
if (!this.logs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return Math.ceil(this.logs.totalHits / PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public pageChanged(page: number) {
|
||||||
|
this._fetchData(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,8 +6,6 @@ import { PermissionsService } from '../../../common/service/permissions.service'
|
|||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { debounce } from '../../../utils/debounce';
|
import { debounce } from '../../../utils/debounce';
|
||||||
import { RuleSetModel } from '@redaction/red-ui-http';
|
import { RuleSetModel } from '@redaction/red-ui-http';
|
||||||
import { tap } from 'rxjs/operators';
|
|
||||||
import { forkJoin } from 'rxjs';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-rule-sets-listing-screen',
|
selector: 'redaction-rule-sets-listing-screen',
|
||||||
|
|||||||
@ -790,6 +790,25 @@
|
|||||||
"legend": "Legend"
|
"legend": "Legend"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"audit": "Audit",
|
||||||
|
"audit-screen": {
|
||||||
|
"table-header": {
|
||||||
|
"title": "{{length}} Logs"
|
||||||
|
},
|
||||||
|
"table-col-names": {
|
||||||
|
"message": "Message",
|
||||||
|
"user": "User",
|
||||||
|
"date": "Date",
|
||||||
|
"category": "Category"
|
||||||
|
},
|
||||||
|
"all-categories": "All Categories",
|
||||||
|
"all-users": "All Users",
|
||||||
|
"to": "to"
|
||||||
|
},
|
||||||
|
"pagination": {
|
||||||
|
"previous": "Prev",
|
||||||
|
"next": "Next"
|
||||||
|
},
|
||||||
"default-colors": "Default Colors",
|
"default-colors": "Default Colors",
|
||||||
"default-colors-screen": {
|
"default-colors-screen": {
|
||||||
"table-header": {
|
"table-header": {
|
||||||
|
|||||||
@ -13,3 +13,8 @@
|
|||||||
color: $grey-1;
|
color: $grey-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mat-form-field.no-label .mat-form-field-infix {
|
||||||
|
padding: 0 !important;
|
||||||
|
border-top: 0 !important;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user