Added the new notification provider to the settings page

pull/3554/head
Jamie Rees 4 years ago
parent a6c6894010
commit 03fc7d4c19

@ -1,4 +1,6 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Ombi.Helpers;
using System;
using System.Collections.Generic;
using System.Net.Http;
@ -14,17 +16,18 @@ namespace Ombi.Api.CloudService
{
private readonly IApi _api;
private readonly ILogger _logger;
private const string BaseUrl = "https://ombinotifications.azurewebsites.net/api/";
private readonly string _baseUrl;
public CloudMobileNotification(IApi api, ILogger<CloudMobileNotification> logger)
public CloudMobileNotification(IApi api, ILogger<CloudMobileNotification> logger, IOptions<ApplicationSettings> settings)
{
_api = api;
_baseUrl = settings.Value.NotificationService;
_logger = logger;
}
public async Task<bool> SendMessage(MobileNotificationRequest notification)
{
var request = new Request("MobileNotification", BaseUrl, HttpMethod.Post);
var request = new Request("MobileNotification", _baseUrl, HttpMethod.Post);
request.AddJsonBody(notification);
var response = await _api.Request(request);

@ -3,5 +3,6 @@
public class ApplicationSettings
{
public string OmbiService { get; set; }
public string NotificationService { get; set; }
}
}

@ -71,6 +71,18 @@ export interface IMobileUsersViewModel {
devices: number;
}
export interface ICloudMobileModel {
userId: string;
username: string;
devices: ICloudMobileDevices[];
}
export interface ICloudMobileDevices {
token: string;
userId: string;
addedAt: Date;
user: IUser;
}
export interface IMassEmailUserModel {
user: IUser;
selected: boolean;

@ -0,0 +1,22 @@
import { APP_BASE_HREF } from "@angular/common";
import { Injectable, Inject } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { ICloudMobileDevices, ICloudMobileModel } from "../interfaces";
import { ServiceHelpers } from "./service.helpers";
@Injectable()
export class CloudMobileService extends ServiceHelpers {
constructor(http: HttpClient, @Inject(APP_BASE_HREF) href:string) {
super(http, "/api/v2/mobile/", href);
}
public getDevices(): Observable<ICloudMobileModel[]> {
return this.http.get<ICloudMobileModel[]>(`${this.url}users/`, {headers: this.headers});
}
public send(userId: string, message: string): Promise<boolean> {
return this.http.post<boolean>(`${this.url}send/`, { userId, message }, {headers: this.headers}).toPromise();
}
}

@ -0,0 +1,55 @@
<settings-menu>
</settings-menu>
<div *ngIf="form" class="container">
<fieldset>
<legend>Mobile Notifications</legend>
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
<div class="row">
<div class="col">
<table *ngIf="devices" mat-table [dataSource]="devices" class="mat-elevation-z8">
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
</th>
<td mat-cell *matCellDef="let row">
<mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
</mat-checkbox>
</td>
</ng-container>
<ng-container matColumnDef="username">
<th mat-header-cell *matHeaderCellDef> Username </th>
<td mat-cell *matCellDef="let element"> {{element.username}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<div class="md-form-field">
<mat-form-field>
<mat-label>Message</mat-label>
<textarea matInput [(ngModel)]="message" [ngModelOptions]="{standalone: true}"></textarea>
</mat-form-field>
</div>
<div class="md-form-field">
<button mat-raised-button type="button" color="primary" (click)="sendMessage(form)" [disabled]="selection.selected.length === 0">Send Notification</button>
</div>
</div>
<div class="col">
<notification-templates [templates]="templates" [showSubject]="false"></notification-templates>
</div>
</div>
<div class="md-form-field ">
<div>
<button mat-raised-button type="submit " color="primary" [disabled]="form.invalid ">Submit</button>
</div>
</div>
</form>
</fieldset>
</div>

@ -0,0 +1,82 @@
import { Component, OnInit } from "@angular/core";
import { FormBuilder, FormGroup } from "@angular/forms";
import { IMobileNotifcationSettings, IMobileUsersViewModel, INotificationTemplates, NotificationType, ICloudMobileDevices, ICloudMobileModel } from "../../interfaces";
import { TesterService } from "../../services";
import { NotificationService } from "../../services";
import { MobileService, SettingsService } from "../../services";
import { CloudMobileService } from "../../services/cloudmobile.service";
import { SelectionModel } from "@angular/cdk/collections";
import { MatTableDataSource } from "@angular/material";
@Component({
templateUrl: "./cloudmobile.component.html",
})
export class CloudMobileComponent implements OnInit {
public NotificationType = NotificationType;
public templates: INotificationTemplates[];
public form: FormGroup;
public devices: MatTableDataSource<ICloudMobileModel>;
public selection = new SelectionModel<ICloudMobileModel>(true, []);
displayedColumns: string[] = ['select', 'username'];
public message: string;
constructor(private settingsService: SettingsService,
private notificationService: NotificationService,
private fb: FormBuilder,
private mobileService: CloudMobileService) { }
public async ngOnInit() {
this.settingsService.getMobileNotificationSettings().subscribe(x => {
this.templates = x.notificationTemplates;
this.form = this.fb.group({
});
});
var result = await this.mobileService.getDevices().toPromise();
if (result.length > 0) {
this.devices = new MatTableDataSource(result);
}
}
public onSubmit(form: FormGroup) {
if (form.invalid) {
this.notificationService.error("Please check your entered values");
return;
}
const settings = <IMobileNotifcationSettings> form.value;
settings.notificationTemplates = this.templates;
this.settingsService.saveMobileNotificationSettings(settings).subscribe(x => {
if (x) {
this.notificationService.success("Successfully saved the Mobile settings");
} else {
this.notificationService.success("There was an error when saving the Mobile settings");
}
});
}
public async sendMessage(form: FormGroup) {
if (form.invalid) {
this.notificationService.error("Please check your entered values");
return;
}
if (this.selection.selected.length <= 0) {
this.notificationService.warning("Warning", "Please select a user to send the test notification");
return;
}
await this.selection.selected.forEach(async (u) => {
await this.mobileService.send(u.userId, this.message);
this.notificationService.success(
"Successfully sent a Mobile message");
});
}
}

@ -2,7 +2,7 @@
</settings-menu>
<div *ngIf="form">
<fieldset>
<legend>Mobile Notifications</legend>
<legend>Legacy Mobile Notifications</legend>
<div class="col-md-6">
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
<div class="row">
@ -35,7 +35,7 @@
<div class="row">
<div class="form-group">
<label for="select" class="control-label">Users</label>
<label for="select" class="control-label">Users</label>
<div>
<select class="form-control form-control-custom" id="select" [(ngModel)]="testUserId" [ngModelOptions]="{standalone: true}">
<option value="">Please select</option>

@ -58,6 +58,8 @@ import { HubService } from "../services/hub.service";
import { LogsComponent } from "./logs/logs.component";
import { TwilioComponent } from "./notifications/twilio/twilio.component";
import { WhatsAppComponent } from "./notifications/twilio/whatsapp.component";
import { CloudMobileComponent } from "./notifications/cloudmobile.coponent";
import { CloudMobileService } from "../services/cloudmobile.service";
const routes: Routes = [
{ path: "Ombi", component: OmbiComponent, canActivate: [AuthGuard] },
@ -94,6 +96,7 @@ const routes: Routes = [
{ path: "TheMovieDb", component: TheMovieDbComponent, canActivate: [AuthGuard] },
{ path: "FailedRequests", component: FailedRequestsComponent, canActivate: [AuthGuard] },
{ path: "Logs", component: LogsComponent, canActivate: [AuthGuard] },
{ path: "CloudMobile", component: CloudMobileComponent, canActivate: [AuthGuard] },
];
@NgModule({
@ -157,6 +160,7 @@ const routes: Routes = [
LogsComponent,
TwilioComponent,
WhatsAppComponent,
CloudMobileComponent,
],
exports: [
RouterModule,
@ -181,6 +185,7 @@ const routes: Routes = [
SystemService,
FileDownloadService,
TheMovieDbService,
CloudMobileService,
],
})

@ -38,7 +38,8 @@
<button mat-button [matMenuTriggerFor]="notificationMenu"><i class="fa fa-bell-o" aria-hidden="true"></i> Notifications</button>
<mat-menu #notificationMenu="matMenu">
<button mat-menu-item [routerLink]="['/Settings/Mobile']">Mobile</button>
<button mat-menu-item [routerLink]="['/Settings/CloudMobile']">Mobile</button>
<button mat-menu-item [routerLink]="['/Settings/Mobile']">Legacy Mobile</button>
<button mat-menu-item [routerLink]="['/Settings/Email']">Email</button>
<button mat-menu-item [routerLink]="['/Settings/MassEmail']">MassEmail</button>
<button mat-menu-item [routerLink]="['/Settings/Newsletter']">Newsletter</button>

@ -1,8 +0,0 @@
namespace Ombi.Config
{
public class UserSettings
{
public string WebsiteUrl { get; set; }
public bool UseHttps { get; set; }
}
}

@ -2,7 +2,10 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Ombi.Api.CloudService;
using Ombi.Attributes;
using Ombi.Core.Authentication;
using Ombi.Helpers;
using Ombi.Models.V2;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
@ -19,14 +22,16 @@ namespace Ombi.Controllers.V2
[ApiController]
public class MobileController : ControllerBase
{
public MobileController(IRepository<MobileDevices> mobileDevices, OmbiUserManager user)
public MobileController(IRepository<MobileDevices> mobileDevices, OmbiUserManager user, ICloudMobileNotification mobileNotificationService)
{
_mobileDevices = mobileDevices;
_userManager = user;
_mobileNotificationService = mobileNotificationService;
}
private readonly IRepository<MobileDevices> _mobileDevices;
private readonly OmbiUserManager _userManager;
private readonly ICloudMobileNotification _mobileNotificationService;
[HttpPost("Notification")]
[ApiExplorerSettings(IgnoreApi = true)]
@ -90,5 +95,47 @@ namespace Ombi.Controllers.V2
return Ok();
}
[HttpPost("Send")]
[ApiExplorerSettings(IgnoreApi = true)]
[Admin]
public async Task<IActionResult> SendNotification([FromBody] SendMobileNotification model)
{
var user = await _userManager.Users.FirstOrDefaultAsync(x => x.Id == model.UserId);
if (user == null)
{
return Ok();
}
// Check if we already have this notification id
var currentDevices = await _mobileDevices.GetAll().Where(x => x.UserId == model.UserId).ToListAsync();
if (currentDevices == null || !currentDevices.Any())
{
return Ok();
}
foreach (var d in currentDevices)
{
await _mobileNotificationService.SendMessage(new MobileNotificationRequest
{
To = d.Token,
Body = model.Message,
});
}
return Ok();
}
[HttpGet("Users")] [ApiExplorerSettings(IgnoreApi = true)]
[Admin]
public async Task<IActionResult> GetUsers()
{
var devices = await _mobileDevices.GetAll().Include(x => x.User).ToListAsync();
var unique = devices.GroupBy(x => x.UserId, (key, g) => new { UserId = key, Username = g.Select(x => x.User.UserName).FirstOrDefault(), Devices = g.ToList() });
return Ok(unique);
}
}
}

@ -69,7 +69,6 @@ namespace Ombi
public static void AddAppSettingsValues(this IServiceCollection services, IConfigurationRoot configuration)
{
services.Configure<ApplicationSettings>(configuration.GetSection("ApplicationSettings"));
services.Configure<UserSettings>(configuration.GetSection("UserSettings"));
services.Configure<TokenAuthentication>(configuration.GetSection("TokenAuthentication"));
services.Configure<LandingPageBackground>(configuration.GetSection("LandingPageBackground"));
services.Configure<DemoLists>(configuration.GetSection("Demo"));

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ombi.Models.V2
{
public class SendMobileNotification
{
public string UserId { get; set; }
public string Message { get; set; }
}
}

@ -11,13 +11,8 @@
}
},
"ApplicationSettings": {
"Verison": "{{VERSIONNUMBER}}",
"Branch": "{{BRANCH}}",
"FriendlyVersion": "v3.0.0"
},
"UserSettings": {
"WebsiteUrl": "http://localhost:52038",
"UseHttps": false
"NotificationService": "https://ombinotifications.azurewebsites.net/api/",
"OmbiService": "?"
},
"TokenAuthentication": {
"SecretKey": "secretkey_secretkey1234!"

Loading…
Cancel
Save