Skip to content

Commit

Permalink
web app: Support creating search and manual recording schedules
Browse files Browse the repository at this point in the history
  • Loading branch information
bennettpeter committed Jul 5, 2023
1 parent 150eed8 commit 3bacbfc
Show file tree
Hide file tree
Showing 9 changed files with 304 additions and 40 deletions.
31 changes: 26 additions & 5 deletions mythtv/html/assets/i18n/en_US.json
Expand Up @@ -23,7 +23,8 @@
"success": "Success",
"unsaved_heading": "Unsaved Changes",
"unsaved_message": "There are unsaved changes.",
"yes": "Yes"
"yes": "Yes",
"backenderror": "Backend error."
},
"dashboard": {
"backendStatus": "Backend Status",
Expand Down Expand Up @@ -75,7 +76,9 @@
"heading": "Recording Rules",
"lastrec": "Last Recorded",
"nextrec": "Next Recording",
"storgrp": "Storage Group"
"storgrp": "Storage Group",
"new_recrule": "New Recording Rule",
"new_teplate": "New Recording Template"
},
"sched": {
"active_label": "Recording Rule is Active",
Expand Down Expand Up @@ -141,7 +144,17 @@
"this": "Record Only This Showing",
"weekly": "Record one showing every week"
},
"type_label": "Schedule Type"
"type_label": "Schedule Type",
"srchtype_label": "Search Type",
"title_label": "Title",
"subtitle_label": "Subtitle",
"description_label": "Description",
"add_tables_label": "Additional Tables",
"sqlwhere_label": "SQL Where Condition",
"srchValue_label": "Search Value",
"channel_label": "Channel",
"starttime_label": "Start Date and Time",
"duration_label": "Duration"
},
"status": {
"backends_detail": "Backend: {{ Name }} is a {{ Type }} on IP {{ IP }}",
Expand Down Expand Up @@ -341,7 +354,14 @@
"RecordOne": "Record One",
"RecordWeekly": "Record Weekly",
"RecordingTemplate": "Recording Template",
"SingleRecord": "Single Record"
"SingleRecord": "Single Record",
"srch_None": "None",
"srch_PowerSearch": "Power Search",
"srch_TitleSearch": "Title Search",
"srch_KeywordSearch": "Keyword Search",
"srch_PeopleSearch": "People Search",
"srch_ManualSearch": "Manual Search",
"template": "Template"
},
"settings": {
"backendctrl": {
Expand Down Expand Up @@ -965,7 +985,8 @@
"slave_instructions": "This appears to be a slave backend. If it is intended as a slave backend, please disable scheduling on the msster backend while running slave backend setup.",
"slave_warning": "If this is not intended as a slave backend, please go to Setup, General, Host Address Backend Setup, and select \"This server is the Master Backend\" or else set the correct custom identifier on the Database Setup page. Save and Restart the backend,",
"title": "MythTV Setup",
"upcomingrec": "Next upcoming recording: {{Title}} at {{StartTime}}. Status: {{Status}}"
"upcomingrec": "Next upcoming recording: {{Title}} at {{StartTime}}. Status: {{Status}}",
"restarting": "Restarting Backend"
},
"misc": {
"bal_io": "Balanced disk I/O",
Expand Down
Expand Up @@ -33,7 +33,7 @@
<div>
<p-progressSpinner *ngIf="retryCount > 0"></p-progressSpinner>
<p-message *ngIf="retryCount > 0" severity="info"
text="Restarting Backend"></p-message>
text="{{ 'settings.main.restarting' | translate }}"></p-message>
<p>
<p-message *ngIf="this.errorCount > 0 && retryCount == 0" severity="error"
text="{{ 'common.networkfail' | translate }}"></p-message>
Expand Down
Expand Up @@ -111,7 +111,7 @@ <h2>{{ 'dashboard.recordings.heading' | translate }}</h2>
<div class="form-group field">
<label for="Description" class="label block">{{ 'dashboard.recordings.description' | translate
}}</label>
<textarea pInputTextarea [rows]="5" [cols]="30" autoResize="true" id="Description"
<textarea pInputTextarea [rows]="5" [cols]="30" id="Description"
[(ngModel)]="program.Description" name="Description" #Description="ngModel"
class="mb-2 form-control w-full"></textarea>
</div>
Expand Down
Expand Up @@ -3,6 +3,10 @@ <h2>{{ 'dashboard.recrules.heading' | translate }}</h2>
<p-table [value]="recRules" scrollHeight="flex" [scrollable]="true" styleClass="p-datatable-striped"
[rowHover]="true" responsiveLayout="scroll">
<ng-template pTemplate="caption">
<button pButton pRipple label="{{ 'dashboard.recrules.new_recrule' | translate }}" icon="pi pi-plus"
class="p-button-success mr-2" (click)="newRecRule()"></button>
<button pButton pRipple label="{{ 'dashboard.recrules.new_teplate' | translate }}"
class="p-button-success p-button-outlined mr-2" (click)="newTemplate()" icon="pi pi-plus"></button>
</ng-template>
<ng-template pTemplate="header">
<tr>
Expand Down
Expand Up @@ -71,9 +71,16 @@ export class RecrulesComponent implements OnInit, SchedulerSummary {

}

updateRecRule(recRule: RecRule) {
newRecRule() {
this.updateRecRule();
}

updateRecRule(recRule?: RecRule) {
if (this.inter.sched)
this.inter.sched.open(undefined, undefined, recRule);
}

newTemplate() {
this.updateRecRule( <RecRule>{ Type: 'Recording Template' });
}
}
Expand Up @@ -110,7 +110,7 @@ <h2>{{ 'dashboard.videos.heading' | translate }}</h2>
<div class="form-group field">
<label for="Description" class="label block">{{ 'dashboard.recordings.description' | translate
}}</label>
<textarea pInputTextarea [rows]="5" [cols]="30" autoResize="true" id="Description"
<textarea pInputTextarea [rows]="5" [cols]="30" id="Description"
[(ngModel)]="video.Description" name="Description" #Description="ngModel"
class="mb-2 form-control w-full"></textarea>
</div>
Expand Down
4 changes: 3 additions & 1 deletion mythtv/html/backend/src/app/primeng.module.ts
Expand Up @@ -32,6 +32,7 @@ import { ScrollPanelModule } from 'primeng/scrollpanel';
import { TabMenuModule } from 'primeng/tabmenu';
import { MultiSelectModule } from 'primeng/multiselect';
import { SlideMenuModule } from 'primeng/slidemenu';
import {InputTextareaModule} from 'primeng/inputtextarea';

@NgModule({
exports: [
Expand Down Expand Up @@ -66,7 +67,8 @@ import { SlideMenuModule } from 'primeng/slidemenu';
ScrollPanelModule,
TabMenuModule,
MultiSelectModule,
SlideMenuModule
SlideMenuModule,
InputTextareaModule
]
})

Expand Down
103 changes: 92 additions & 11 deletions mythtv/html/backend/src/app/schedule/schedule.component.html
@@ -1,15 +1,95 @@
<form class="ml-3 mr-3" name="schedform" #schedform="ngForm">
<div *ngIf="recRule">
<p-dialog header="{{ 'dashboard.sched.heading' | translate }}" [(visible)]="displayDlg" [modal]="true"
[style]="{height: '75vw', width: '500px'}" [closable]="false" [closeOnEscape]="false">
[style]="{height: '90vw', width: '700px'}" [closable]="false" [closeOnEscape]="false">
<p> {{ channel?.ChanNum }} {{ channel?.CallSign }}</p>
<p> {{ utility.formatDate(recRule.StartTime) }} {{ utility.formatTime(recRule.StartTime) }} -
{{ utility.formatTime(recRule.EndTime )}}
</p>
<b> {{ recRule.Title }} </b>
<p> {{ recRule.SubTitle }} </p>
<p> <span *ngIf="recRule.Season && recRule.Episode"> (s{{ recRule.Season }}e{{recRule.Episode}})</span>
{{ recRule.Description }} </p>
<div class="form-group field">
<label for="SearchType" class="label block">{{ 'dashboard.sched.srchtype_label' | translate
}}</label>
<p-dropdown [options]="srchTypeList" [(ngModel)]="recRule.SearchType" [editable]="false"
optionLabel="prompt" optionValue="value" [maxlength]="0" [style]="{'minWidth':'400px'}"
name="SearchType" #SearchType="ngModel" optionDisabled="inactive" [disabled]="srchTypeDisabled"
(onChange)="onSearchTypeChange()">
</p-dropdown>
</div>

<div class="form-group field">
<label for="Title" class="label block">{{ 'dashboard.sched.title_label' | translate }}</label>
<textarea pInputTextArea id="Title" [(ngModel)]="recRule.Title" name="Title"
class="text-lg mb-2 form-control w-full"
[disabled]="['Power Search','Manual Search'].indexOf(recRule.SearchType) == -1 && recRule.Type != 'Recording Template' || recRule.Id == defaultTemplate?.Id"
(focusout)="onTitleBlur()" [rows]="titleRows">
</textarea>
</div>

<div class="form-group field" *ngIf="recRule.Type != 'Recording Template'">
<label *ngIf="recRule.SearchType == 'None'" for="SubTitle" class="label block">
{{ 'dashboard.sched.subtitle_label' | translate }}</label>
<label *ngIf="recRule.SearchType == 'Power Search'" for="SubTitle" class="label block">
{{ 'dashboard.sched.add_tables_label' | translate }}</label>
<textarea *ngIf="['None','Power Search'].indexOf(recRule.SearchType)>-1" pInputTextArea id="SubTitle"
[(ngModel)]="recRule.SubTitle" name="SubTitle" class="text-lg mb-2 form-control w-full"
[disabled]="recRule.SearchType!='Power Search'" [rows]="subTitleRows">
</textarea>
</div>

<p> <span *ngIf="recRule.Season && recRule.Episode">S{{ recRule.Season }} E{{recRule.Episode}}</span>
</p>

<div class="form-group field" *ngIf="recRule.Type != 'Recording Template'">
<div [ngSwitch]="recRule.SearchType">
<label *ngSwitchCase="'None'" for="Description" class="label block mb-2">
{{ 'dashboard.sched.description_label' | translate }}</label>
<label *ngSwitchCase="'Power Search'" for="Description" class="label block mb-2">
{{ 'dashboard.sched.sqlwhere_label' | translate }}</label>
<label *ngSwitchCase="'Manual Search'" for="Description" class="label block mb-2">
{{ 'dashboard.sched.description_label' | translate }}</label>
<label *ngSwitchDefault for="Description" class="label block mb-2">
{{ 'dashboard.sched.srchValue_label' | translate }}</label>
</div>
<textarea pInputTextArea id="Description" [(ngModel)]="recRule.Description" name="Description"
class="text-lg mb-2 form-control w-full" (focusout)="onDescriptionBlur()"
[disabled]="['None','Manual Search'].indexOf(recRule.SearchType) > -1" [rows]="descriptionRows">
</textarea>
</div>

<div *ngIf="recRule.SearchType == 'Power Search'">
Examples of SQL Additional Tables and Where Conditions are in the MythTV wiki at<br>
<a href="https://www.mythtv.org/wiki/Power_Search" target="_blank">Power Search</a>
</div>

<!-- Manual Search Settings -->
<div *ngIf="recRule.SearchType == 'Manual Search'">
<p-divider></p-divider>
<div class="form-group field">
<label for="ChanId" class="label block">{{ 'dashboard.sched.channel_label' | translate
}}</label>
<p-dropdown [options]="allChannels" [(ngModel)]="channel" [editable]="false"
optionLabel="Description" [maxlength]="0" [style]="{'minWidth':'400px'}" name="Type"
(onChange)="onChannelChange()">
</p-dropdown>
</div>
<div class="form-group field">
<label for="StartTime" class="label block">{{ 'dashboard.sched.starttime_label' | translate
}}</label>
<p-calendar [(ngModel)]="this.reqDate" [showTime]="true" [stepMinute]="5" [dateFormat]="'yy/mm/dd'"
(onClose)="onDateChange()" (keyup.enter)="onDateChange()" (onBlur)="onDateChange()"
[selectOtherMonths]="true" [showIcon]="true" [showOnFocus]="false" [showButtonBar]="true"
[clearButtonStyleClass]="'hidden'" name="StartTime">
</p-calendar>
</div>

<div class="form-group field">
<label for="Duration" class="label block">{{ 'dashboard.sched.duration_label' | translate
}}</label>
<p-inputNumber [(ngModel)]="reqDuration" name="Duration" id="Duration" [showButtons]="true"
[min]="5" [max]="360" [step]="5" (ngModelChange)="onDurationChange()"></p-inputNumber>
</div>
</div>

<p-divider></p-divider>

<div class="form-group field">
Expand All @@ -28,10 +108,10 @@
</p-dropdown>
</div>

<div class="form-group field" *ngIf="recRule.Type != 'Recording Template'">
<div class="form-group field">
<p-checkbox inputId="Active" [(ngModel)]="recRule.Inactive" name="Active" #Active="ngModel"
class="label mb-2 w-full" [binary]="true" label="{{ 'dashboard.sched.active_label' | translate }}"
[trueValue]="false" [falseValue]="true" >
[trueValue]="false" [falseValue]="true">
</p-checkbox>
</div>

Expand Down Expand Up @@ -99,8 +179,9 @@
<div class="form-group field">
<label for="AutoExtend" class="label block">{{ 'dashboard.sched.autoextend_label' | translate
}}</label>
<p-dropdown [options]="autoExtendList" [(ngModel)]="recRule.AutoExtend" [editable]="false" optionLabel="prompt"
optionValue="value" [maxlength]="0" [style]="{'minWidth':'400px'}" name="AutoExtend" #AutoExtend="ngModel">
<p-dropdown [options]="autoExtendList" [(ngModel)]="recRule.AutoExtend" [editable]="false"
optionLabel="prompt" optionValue="value" [maxlength]="0" [style]="{'minWidth':'400px'}"
name="AutoExtend" #AutoExtend="ngModel">
</p-dropdown>
</div>

Expand Down Expand Up @@ -230,14 +311,14 @@
<p-message *ngIf="successCount > 0 && errorCount == 0 && !schedform.dirty" severity="success"
text="{{ 'common.savesuccess' | translate }}"></p-message>
<p-message *ngIf="errorCount > 0" severity="error"
text="{{ 'common.networkfail' | translate }}"></p-message>
text="{{ 'common.backenderror' | translate }}: {{errortext}}"></p-message>
</div>
<p-button icon="pi pi-times-circle" (onClick)="close()" label="{{ 'common.close' | translate }}"
styleClass="p-button-warning">
</p-button>
<p-button icon="pi pi-check-circle" (onClick)="save();" label="{{ 'common.save' | translate }}"
styleClass="p-button-success"
[disabled]="!schedform.dirty || recRule.Id == 0 && recRule.Type == 'Not Recording' "></p-button>
[disabled]="!schedform.dirty || recRule.Id == 0 && recRule.Type == 'Not Recording' || !recRule.Title"></p-button>
</ng-template>

</p-dialog>
Expand Down

0 comments on commit 3bacbfc

Please sign in to comment.