LP1901930 SIP mediator continued
authorBill Erickson <berickxx@gmail.com>
Wed, 25 Nov 2020 20:30:24 +0000 (12:30 -0800)
committerBill Erickson <berickxx@gmail.com>
Mon, 30 Nov 2020 16:38:26 +0000 (08:38 -0800)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/eg2/src/app/share/dialog/prompt.component.html
Open-ILS/src/eg2/src/app/share/dialog/prompt.component.ts
Open-ILS/src/eg2/src/app/staff/admin/server/sip/account-list.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/sip/account-list.component.ts
Open-ILS/src/eg2/src/app/staff/admin/server/sip/account.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/sip/account.component.ts

index 528a125..b8cde7e 100644 (file)
@@ -13489,6 +13489,7 @@ SELECT  usr,
                        <field name="enabled" reporter:datatype="bool" reporter:label="Enabled"/>
                        <field name="setting_group" reporter:datatype="link" reporter:label="Settings Group" oils_obj:required="true"/>
                        <field name="sip_username" reporter:datatype="text" reporter:label="SIP Username" oils_obj:required="true"/>
+                       <field name="sip_password" reporter:datatype="id" reporter:label="SIP Password" oils_obj:required="true"/>
                        <field name="usr" reporter:datatype="link" reporter:label="ILS User" oils_obj:required="true"/>
                        <field name="workstation" reporter:datatype="link" reporter:label="Workstation"/>
                        <field name="transient" reporter:datatype="bool" reporter:label="Transient"/>
index 17a6b50..ca47961 100644 (file)
@@ -9,7 +9,7 @@
   <div class="modal-body">
     <p>{{dialogBody}}</p>
     <div class="text-center">
-        <input class="form-control" [(ngModel)]="promptValue"/>
+        <input type="{{promptType}}" class="form-control" [(ngModel)]="promptValue"/>
     </div>
   </div>
   <div class="modal-footer">
index ab7f77e..a5d8eca 100644 (file)
@@ -14,6 +14,8 @@ export class PromptDialogComponent extends DialogComponent {
     @Input() public dialogBody: string;
     // Value to return to the caller
     @Input() public promptValue: string;
+    // 'password', etc.
+    @Input() promptType = 'text';
 }
 
 
index 1dcf515..e794f01 100644 (file)
@@ -3,6 +3,8 @@
 <eg-grid #grid idlClass="sipacc" [dataSource]="gridSource" 
   persistKey="admin.server.sip.account-list"
   [stickyHeader]="true" [sortable]="true" (onRowActivate)="openAccount($event)">
+  <eg-grid-toolbar-button label="New Account" i18n-label
+    (onClick)="newAccount"></eg-grid-toolbar-button>
   <eg-grid-toolbar-action label="Delete Selected" i18n-label 
     (onClick)="deleteSelected($event)">
   </eg-grid-toolbar-action>
index 3141158..44e2940 100644 (file)
@@ -52,8 +52,15 @@ export class SipAccountListComponent implements OnInit {
         this.router.navigate([`/staff/admin/server/sip/account/${row.id()}`]);
     }
 
+    newAccount() {
+        this.router.navigate([`/staff/admin/server/sip/account/new`]);
+    }
+
     deleteSelected(rows: any[]) {
-        // TODO
+        rows.forEach(row => row.isdeleted(true));
+        this.pcrud.autoApply(rows).subscribe(_ => {
+            this.gridSource.reset();
+        });
     }
 }
 
index ba6b141..ba3766d 100644 (file)
   [fieldOptions]="{name:{isReadonly:true}}">
 </eg-fm-record-editor>
 
+<ng-container *ngIf="createMode">
+  <eg-prompt-dialog #passwordDialog i18n-dialogTitle i18n-dialogBody
+    dialogTitle="Create SIP Password" i18n-dialogBody="Create a new password"
+    promptType="password">
+  </eg-prompt-dialog>
+</ng-container>
+
+<ng-container *ngIf="!createMode">
+  <eg-prompt-dialog #passwordDialog i18n-dialogTitle i18n-dialogBody
+    dialogTitle="Create SIP Password" i18n-dialogBody="Create a new password"
+    promptType="password">
+  </eg-prompt-dialog>
+</ng-container>
 
 <div class="row mt-2" *ngIf="account">
   <div class="col-lg-7">
       </div>
     </ng-template>
 
+    <ng-template #sipPassTemplate>
+      <button class="btn btn-outline-dark" 
+        [ngClass]="{'border-danger' : !account.sip_password()}"
+        (click)="setPassword()">Set Password</button>
+    </ng-template>
 
     <eg-fm-record-editor #editor
-      idlClass="sipacc" mode="update" hiddenFields="id" displayMode="inline"
-      fieldOrder="sip_username,setting_group,usr,workstation,transient,activity_who,enabled"
+      idlClass="sipacc" [mode]="createMode ? 'create' : 'update'" 
+      hiddenFields="id" displayMode="inline"
+      fieldOrder="sip_username,sip_password,setting_group,usr,workstation,transient,activity_who,enabled"
       [fieldOptions]="{
         setting_group:{customTemplate:{template:grpTemplate}},
+        sip_password:{customTemplate:{template:sipPassTemplate}},
         usr:{customTemplate:{template:usrTemplate}}}"
-      [preSave]="accountPreSave"
-      (recordSaved)="accountSaved()" [recordId]="accountId">
+      [preSave]="accountPreSave" [recordId]="createMode ? accountId : null"
+      (recordSaved)="accountSaved($event)">
     </eg-fm-record-editor>
   </div>
   <div class="col-lg-5">
index 856ed56..2e373ca 100644 (file)
@@ -1,5 +1,5 @@
 import {Component, Input, ViewChild, OnInit} from '@angular/core';
-import {ActivatedRoute} from '@angular/router';
+import {Router, ActivatedRoute} from '@angular/router';
 import {Observable, of} from 'rxjs';
 import {map, tap, switchMap, catchError} from 'rxjs/operators';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
@@ -10,6 +10,7 @@ import {ToastService} from '@eg/share/toast/toast.service';
 import {StringComponent} from '@eg/share/string/string.component';
 import {StringService} from '@eg/share/string/string.service';
 import {DialogComponent} from '@eg/share/dialog/dialog.component';
+import {PromptDialogComponent} from '@eg/share/dialog/prompt.component';
 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
 import {ComboboxEntry, ComboboxComponent} from '@eg/share/combobox/combobox.component';
 import {GridComponent} from '@eg/share/grid/grid.component';
@@ -30,14 +31,17 @@ export class SipAccountComponent implements OnInit {
     settingsSource: GridDataSource = new GridDataSource();
     deleteGroupAccounts: IdlObject[] = [];
     accountPreSave: (mode: string, account: IdlObject) => void;
+    createMode = false;
 
     @ViewChild('cloneDialog') cloneDialog: FmRecordEditorComponent;
     @ViewChild('settingDialog') settingDialog: FmRecordEditorComponent;
     @ViewChild('settingGrid') settingGrid: GridComponent;
     @ViewChild('deleteGroupDialog') deleteGroupDialog: DialogComponent;
+    @ViewChild('passwordDialog') passwordDialog: PromptDialogComponent;
 
     constructor(
         private route: ActivatedRoute,
+        private router: Router,
         private idl: IdlService,
         private pcrud: PcrudService
     ) {}
@@ -45,6 +49,12 @@ export class SipAccountComponent implements OnInit {
     ngOnInit() {
 
         this.route.paramMap.subscribe(map => {
+            if (map.get('id') === 'new') {
+                this.account = this.idl.create('sipacc'); // dummy
+                this.createMode = true;
+                return;
+            }
+
             this.accountId = Number(map.get('id'));
             this.loadAccount().toPromise(); // force it to run
         });
@@ -52,13 +62,19 @@ export class SipAccountComponent implements OnInit {
         this.fetchGroups();
 
         this.usrCboxSource = term => {
-            return this.pcrud.search('au', {
-                deleted: 'f', active: 't',
-                '-or': [
+
+            const filter: any = {deleted: 'f', active: 't'};
+
+            if (this.account && this.account.usr()) {
+                filter['-or'] = [
                     {id: this.account.usr().id()},
                     {usrname: {'ilike': `%${term}%`}}
-                ],
-            }, {
+                ];
+            } else {
+                filter.usrname = {'ilike': `%${term}%`};
+            }
+
+            return this.pcrud.search('au', filter, {
                 order_by: {au: 'usrname'},
                 limit: 50 // Avoid huge lists
             }
@@ -84,7 +100,7 @@ export class SipAccountComponent implements OnInit {
         };
 
         this.accountPreSave = (mode: string, account: IdlObject) => {
-            if (mode === 'update') {
+            if (this.account.setting_group()) {
                 // Migrate the setting group selected in our local group
                 // combobox to the object to be saved.
                 account.setting_group(this.account.setting_group().id());
@@ -163,7 +179,6 @@ export class SipAccountComponent implements OnInit {
     }
 
     openDeleteDialog() {
-
         this.deleteGroupDialog.open().subscribe(
             ok => {
                 if (ok) {
@@ -173,8 +188,13 @@ export class SipAccountComponent implements OnInit {
         );
     }
 
-    accountSaved() {
-        this.refreshAccount();
+    accountSaved(result) {
+        if (this.createMode) {
+            this.router.navigate(
+                [`/staff/admin/server/sip/account/${result.id()}`]);
+        } else {
+            this.refreshAccount();
+        }
     }
 
     editFirstSetting(rows: any) {
@@ -203,5 +223,13 @@ export class SipAccountComponent implements OnInit {
             err => {} // todo toast
         );
     }
+
+
+    setPassword() {
+        this.passwordDialog.open().subscribe(value => {
+            // API will translate this into an actor.passwd entry.
+            this.account.sip_password(value);
+        });
+    }
 }