Skip to content

Commit

Permalink
fix(notifications): polish notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
xmlking committed Dec 8, 2018
1 parent db85e50 commit d64f64b
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 59 deletions.
14 changes: 9 additions & 5 deletions apps/api/src/app/external/kubernetes/kubernetes.service.ts
Expand Up @@ -51,7 +51,11 @@ export class KubernetesService implements OnModuleInit {
// }
}

public async listNamespaces(cluster: string) {
getClusterNames() {
return this.clients.keys();
}

async listNamespaces(cluster: string) {
try {
const namespaces = await this.clients.get(cluster).api.v1.namespaces.get();
return namespaces.body.items;
Expand All @@ -60,7 +64,7 @@ export class KubernetesService implements OnModuleInit {
}
}

public async myNamespaces(cluster: string, token: string) {
async myNamespaces(cluster: string, token: string) {
try {
// this.client.get(cluster).setToken(token)
const namespaces = await this.clients.get(cluster).api.v1.namespaces.get();
Expand All @@ -70,7 +74,7 @@ export class KubernetesService implements OnModuleInit {
}
}

public async getNamespace(cluster: string, namespace: string) {
async getNamespace(cluster: string, namespace: string) {
try {
const namespace1 = await this.clients
.get(cluster)
Expand All @@ -82,7 +86,7 @@ export class KubernetesService implements OnModuleInit {
}
}

public async myServiceAccounts(cluster: string, namespace: string) {
async myServiceAccounts(cluster: string, namespace: string) {
try {
const namespaces = await this.clients
.get(cluster)
Expand All @@ -94,7 +98,7 @@ export class KubernetesService implements OnModuleInit {
}
}

public async hasNamespace(cluster: string, namespace: string) {
async hasNamespace(cluster: string, namespace: string) {
try {
const foundNamespace = await this.clients
.get(cluster)
Expand Down
Expand Up @@ -25,7 +25,7 @@ export class CreateNotificationDto {
@IsEnum(TargetType)
readonly targetType: TargetType;

@ApiModelPropertyOptional({ type: String, enum: NotificationIcon, default: NotificationIcon.notifications })
@ApiModelPropertyOptional({ type: String, enum: NotificationIcon, default: NotificationIcon.NOTIFICATIONS })
@IsOptional()
@IsEnum(NotificationIcon)
readonly icon?: NotificationIcon;
Expand Down
Expand Up @@ -2,10 +2,9 @@ import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';

export class SendNotificationDto {
@ApiModelProperty({ type: String })
@ApiModelProperty({ type: Number })
@IsNotEmpty()
@IsString()
id: string;
id: number;

@ApiModelPropertyOptional({ type: String })
@IsOptional()
Expand Down
@@ -1,12 +1,12 @@
import { Body, Controller, Delete, Get, HttpStatus, Param, Post, Put } from '@nestjs/common';
import { CrudController } from '../../core';
import { ApiOAuth2Auth, ApiOperation, ApiResponse, ApiUseTags, ApiExcludeEndpoint } from '@nestjs/swagger';
import { Notification, TargetType } from './notification.entity';
import { ApiExcludeEndpoint, ApiOAuth2Auth, ApiOperation, ApiResponse, ApiUseTags } from '@nestjs/swagger';
import { Notification } from './notification.entity';
import { CreateNotificationDto } from './dto/create-notification.dto';
import { NotificationService } from './notification.service';
import { CurrentUser, Roles, RolesEnum, User } from '../../auth';
import { DeepPartial } from 'typeorm';
import { SendNotificationDto } from './dto/send-notification.dto';
import { UpdateNotificationDto } from './dto/update-notification.dto';

@ApiOAuth2Auth(['read'])
@ApiUseTags('Sumo', 'Notifications')
Expand All @@ -26,7 +26,11 @@ export class NotificationController extends CrudController<Notification> {
}

@ApiOperation({ title: 'find all user and global Notifications' })
@ApiResponse({ status: HttpStatus.OK, description: 'All user Notifications', /* type: Notification, */ isArray: true })
@ApiResponse({
status: HttpStatus.OK,
description: 'All user Notifications',
/* type: Notification, */ isArray: true,
})
@Get('user')
async getUserNotifications(@CurrentUser() user): Promise<[Notification[], number]> {
return this.notificationService.getUserNotifications(user);
Expand Down Expand Up @@ -59,11 +63,13 @@ export class NotificationController extends CrudController<Notification> {
return super.create(entity);
}

@ApiExcludeEndpoint() // TODO
@ApiExcludeEndpoint()
@ApiUseTags('admin')
@Roles(RolesEnum.ADMIN)
@Put(':id')
async update(
@Param('id') id: string,
@Body() entity: DeepPartial<Notification>,
@Body() entity: UpdateNotificationDto,
@CurrentUser() user: User,
): Promise<any> {
return this.notificationService.update(id, entity);
Expand All @@ -74,21 +80,21 @@ export class NotificationController extends CrudController<Notification> {
@ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Record not found' })
@ApiUseTags('admin')
@Roles(RolesEnum.ADMIN)
@Delete('deleteByAdmin/:id')
@Delete(':id')
async deleteByAdmin(@Param('id') id: string): Promise<any> {
return this.notificationService.update({ id: parseInt(id, 10) }, { isActive: false });
}

@ApiOperation({ title: 'Delete record by user' })
@ApiResponse({ status: HttpStatus.NO_CONTENT, description: 'The record has been successfully deleted' })
@ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Record not found' })
@Delete(':id')
async delete(@Param('id') id: string, @CurrentUser() user: User): Promise<any> {
return this.notificationService.update(
{ id: parseInt(id, 10), targetType: TargetType.USER, target: user.userId },
{ isActive: false },
);
}
// @ApiOperation({ title: 'Delete record by user' })
// @ApiResponse({ status: HttpStatus.NO_CONTENT, description: 'The record has been successfully deleted' })
// @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Record not found' })
// @Delete('deleteByUser/:id')
// async delete(@Param('id') id: string, @CurrentUser() user: User): Promise<any> {
// return this.notificationService.update(
// { id: parseInt(id, 10), targetType: TargetType.USER, target: user.userId },
// { isActive: false },
// );
// }

@ApiOperation({ title: 'Send Push Notifications. Admins only' })
@ApiResponse({
Expand Down
26 changes: 13 additions & 13 deletions apps/api/src/app/notifications/notification/notification.entity.ts
Expand Up @@ -15,12 +15,12 @@ export enum NotificationColor {
}

export enum NotificationIcon {
notifications = 'notifications',
notifications_active = 'notifications_active',
shopping_basket = 'shopping_basket',
eject = 'eject',
cached = 'cached',
code = 'code',
NOTIFICATIONS = 'notifications',
NOTIFICATIONS_ACTIVE = 'notifications_active',
SHOPPING_BASKET = 'shopping_basket',
EJECT = 'eject',
CACHED = 'cached',
CODE = 'code',
}

@Entity('notification')
Expand All @@ -42,8 +42,8 @@ export class Notification extends Base {
@Column({ enum: ['all', 'user', 'topic'] })
targetType: string;

@ApiModelProperty({ type: String, enum: NotificationIcon, default: NotificationIcon.notifications })
@Column({ enum: NotificationIcon, default: NotificationIcon.notifications })
@ApiModelProperty({ type: String, enum: NotificationIcon, default: NotificationIcon.NOTIFICATIONS })
@Column({ enum: NotificationIcon, default: NotificationIcon.NOTIFICATIONS })
icon?: NotificationIcon;

@ApiModelProperty({ type: String, enum: NotificationColor, default: NotificationColor.PRIMARY })
Expand All @@ -60,6 +60,11 @@ export class Notification extends Base {
@Column({ default: false })
native?: boolean;

@ApiModelProperty({ type: Boolean, default: true })
@Index()
@Column({ default: true })
isActive?: boolean;

@ApiModelProperty({ type: 'string', format: 'date-time', example: '2018-11-21T06:20:32.232Z' })
@CreateDateColumn()
createdAt?: Date;
Expand All @@ -71,9 +76,4 @@ export class Notification extends Base {
@Exclude()
@VersionColumn()
version?: number;

@ApiModelProperty({ type: Boolean, default: true })
@Index()
@Column({ default: true })
isActive: boolean;
}
Expand Up @@ -4,7 +4,7 @@ import { Any, In, Repository } from 'typeorm';
import { CrudService } from '../../core';
import { Notification, TargetType } from './notification.entity';
import { EventBusGateway } from '../../shared';
import { MarkAsRead, DeleteNotification } from '../index';
import { DeleteNotification, MarkAsRead } from '../index';
import { User } from '../../auth';
import { SubscriptionService } from '../subscription/subscription.service';
import { PushService } from './push.service';
Expand Down Expand Up @@ -69,10 +69,16 @@ export class NotificationService extends CrudService<Notification> {
});
}

async onMarkAsRead(action: MarkAsRead) {
await this.update({ id: parseInt(action.payload.id, 10) }, { read: true });
async onMarkAsRead(action: MarkAsRead, user: User) {
await this.update(
{ id: parseInt(action.payload.id, 10), targetType: TargetType.USER, target: user.userId },
{ read: true },
);
}
async onDeleteNotification(action: DeleteNotification) {
await this.update({ id: parseInt(action.payload.id, 10) }, { isActive: false });
async onDeleteNotification(action: DeleteNotification, user: User) {
await this.update(
{ id: parseInt(action.payload.id, 10), targetType: TargetType.USER, target: user.userId },
{ isActive: false },
);
}
}
2 changes: 1 addition & 1 deletion apps/api/src/app/shared/eventbus.gateway.ts
Expand Up @@ -62,7 +62,7 @@ export class EventBusGateway extends EventEmitter implements OnGatewayInit, OnGa
@SubscribeMessage('actions')
onActions(client: ISocket, action: any) {
// this.logger.log(`actions => ${client.id} ${client.user.userId} ${action.type} ${action.payload}`);
this.emit(action.type, action);
this.emit(action.type, action, client.user);
}

public sendActionToUser<T>(user: User, action: any): void {
Expand Down
14 changes: 7 additions & 7 deletions libs/notifications/src/lib/app-notification.model.ts
Expand Up @@ -12,15 +12,14 @@ export enum NotificationColor {
}

export enum NotificationIcon {
notifications = 'notifications',
notifications_active = 'notifications_active',
shopping_basket = 'shopping_basket',
eject = 'eject',
cached = 'cached',
code = 'code',
NOTIFICATIONS = 'notifications',
NOTIFICATIONS_ACTIVE = 'notifications_active',
SHOPPING_BASKET = 'shopping_basket',
EJECT = 'eject',
CACHED = 'cached',
CODE = 'code',
}


export class AppNotification extends Entity {
public id: number;
public title: string;
Expand All @@ -31,6 +30,7 @@ export class AppNotification extends Entity {
public color: NotificationColor;
public read: boolean;
public native: boolean;
public isActive: boolean;
public createdAt: Date;
public updatedAt?: Date;
}
1 change: 0 additions & 1 deletion libs/notifications/src/lib/notifications.component.ts
Expand Up @@ -27,7 +27,6 @@ export class NotificationsComponent implements OnInit {

markAsRead(notification) {
this.store.dispatch(new MarkAsRead(notification));
notification.read = true;
}

dismiss(notification, event) {
Expand Down
6 changes: 3 additions & 3 deletions libs/notifications/src/lib/notifications.state.ts
Expand Up @@ -51,7 +51,8 @@ export class NotificationsState implements NgxsOnInit {
setState(
getState().map(notification => {
if (notification === payload) {
notification.read = true;
// notification.read = true;
return { ...notification, ...{ read: true } };
}
return notification;
}),
Expand All @@ -62,8 +63,7 @@ export class NotificationsState implements NgxsOnInit {
markAllAsRead({ getState, setState, patchState }: StateContext<AppNotification[]>) {
setState(
getState().map(notification => {
notification.read = true;
return notification;
return { ...notification, ...{ read: true } };
}),
);
}
Expand Down
5 changes: 2 additions & 3 deletions libs/notifications/tsconfig.lib.json
Expand Up @@ -12,16 +12,15 @@
"experimentalDecorators": true,
"importHelpers": true,
"types": [],
"lib": ["dom", "es2015"]
"lib": ["dom", "es2018"]
},
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
"flatModuleId": "AUTOGENERATED",
"flatModuleOutFile": "AUTOGENERATED"
"enableResourceInlining": true
},
"exclude": ["src/test.ts", "**/*.spec.ts"]
}

0 comments on commit d64f64b

Please sign in to comment.