--- /dev/null
+<eg-string #successString i18n-text text="{{tableName}} Update Succeeded"></eg-string>
+<eg-string #createString i18n-text text="{{tableName}} Was Created Successfully"></eg-string>
+<eg-string #deleteFailedString i18n-text text="Deletion of {{tableName}} failed or was not allowed"></eg-string>
+<eg-string #deleteSuccessString i18n-text text="Deletion of {{tableName}} was successful"></eg-string>
+<eg-string #deleteLinkedTermWarningString i18n-text text="Warning: One or more courses are linked to this Term. Are you sure you want to delete {{termToDelete}}?"></eg-string>
+
+<ng-container>
+<div class="row">
+ <div class="col-lg-6">
+ <eg-org-family-select
+ [limitPerms]="['MANAGE_RESERVES']"
+ [selectedOrgId]="defaultOuId"
+ [(ngModel)]="searchOrgs"
+ (ngModelChange)="grid.reload()">
+ </eg-org-family-select>
+ </div>
+</div>
+<hr/>
+
+<div class="w-100 mt-2 mb-2">
+ <eg-grid #grid idlClass={{idlClass}}
+ [dataSource]="grid_source"
+ [sortable]="true">
+ <eg-grid-toolbar-button
+ label="Create {{tableName}}" (onClick)="createNew()" i18n-label>
+ </eg-grid-toolbar-button>
+ <eg-grid-toolbar-action label="Edit Selected" i18n-label (onClick)="editSelected($event)">
+ </eg-grid-toolbar-action>
+ <eg-grid-toolbar-action label="Delete Selected" i18n-label (onClick)="deleteSelected($event)">
+ </eg-grid-toolbar-action>
+ <eg-grid-column label="ID" path="id" [index]=true [hidden]="true" i18n-label></eg-grid-column>
+ <eg-grid-column label="Name" name="name" i18n-label></eg-grid-column>
+ </eg-grid>
+</div>
+</ng-container>
+
+<eg-fm-record-editor #editDialog
+ idlClass="acmt"
+ fieldOrder="name,owning_lib,start_date,end_date"
+ [preloadLinkedValues]="true"
+ hiddenFields="id,is_archived">
+</eg-fm-record-editor>
+
+<eg-confirm-dialog dialogBody="{{deleteLinkedTermWarningString.text}}" #deleteLinkedTermWarning></eg-confirm-dialog>
\ No newline at end of file
--- /dev/null
+import {Component, Input, ViewChild, OnInit, AfterViewInit} from '@angular/core';
+import {Router} from '@angular/router';
+import {IdlObject, IdlService} from '@eg/core/idl.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+import {CourseService} from '@eg/staff/share/course.service';
+import {GridComponent} from '@eg/share/grid/grid.component';
+import {Pager} from '@eg/share/util/pager';
+import {GridDataSource, GridColumn} from '@eg/share/grid/grid';
+import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
+import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
+import {StringComponent} from '@eg/share/string/string.component';
+import {ToastService} from '@eg/share/toast/toast.service';
+import {LocaleService} from '@eg/core/locale.service';
+import {AuthService} from '@eg/core/auth.service';
+import {OrgService} from '@eg/core/org.service';
+import {OrgFamily} from '@eg/share/org-family-select/org-family-select.component';
+
+@Component({
+ selector: 'eg-course-term-grid',
+ templateUrl: './course-term-grid.component.html'
+})
+
+export class TermListComponent implements OnInit, AfterViewInit {
+
+ @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
+ @ViewChild('deleteLinkedTermWarning', { static: true }) deleteLinkedTermWarning: ConfirmDialogComponent;
+ @ViewChild('grid') grid: GridComponent;
+ @ViewChild('successString', { static: true }) successString: StringComponent;
+ @ViewChild('createString') createString: StringComponent;
+ @ViewChild('createErrString') createErrString: StringComponent;
+ @ViewChild('updateFailedString') updateFailedString: StringComponent;
+ @ViewChild('deleteFailedString', { static: true }) deleteFailedString: StringComponent;
+ @ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent;
+ @ViewChild('deleteLinkedTermWarningString', { static: true }) deleteLinkedTermWarningString: StringComponent;
+
+ @Input() sortField: string;
+ @Input() idlClass = 'acmt';
+ @Input() dialog_size: 'sm' | 'lg' = 'lg';
+ @Input() tableName = 'Term';
+ grid_source: GridDataSource = new GridDataSource();
+ currentMaterials: any[] = [];
+ search_value = '';
+ defaultOuId: number;
+ searchOrgs: OrgFamily;
+ defaultTerm: IdlObject;
+ termToDelete: String;
+
+
+ constructor(
+ private courseSvc: CourseService,
+ private locale: LocaleService,
+ private auth: AuthService,
+ private idl: IdlService,
+ private org: OrgService,
+ private pcrud: PcrudService,
+ private router: Router,
+ private toast: ToastService
+ ) {}
+
+ ngOnInit() {
+ this.getSource();
+ this.defaultTerm = this.idl.create('acmt');
+ this.defaultOuId = this.auth.user().ws_ou() || this.org.root().id();
+ this.defaultTerm.owning_lib(this.defaultOuId);
+ this.searchOrgs = {primaryOrgId: this.defaultOuId};
+ }
+
+ ngAfterViewInit() {
+ this.grid.onRowActivate.subscribe((term: IdlObject) => {
+ const idToEdit = term.id();
+ this.editSelected([term]);
+ });
+
+ }
+
+ /**
+ * Gets the data, specified by the class, that is available.
+ */
+ getSource() {
+ this.grid_source.getRows = (pager: Pager, sort: any[]) => {
+ const orderBy: any = {};
+ if (sort.length) {
+ // Sort specified from grid
+ orderBy[this.idlClass] = sort[0].name + ' ' + sort[0].dir;
+ } else if (this.sortField) {
+ // Default sort field
+ orderBy[this.idlClass] = this.sortField;
+ }
+ const search: any = new Array();
+ const orgFilter: any = {};
+ orgFilter['owning_lib'] =
+ this.searchOrgs.orgIds || [this.defaultOuId];
+ search.push(orgFilter);
+ const searchOps = {
+ offset: pager.offset,
+ limit: pager.limit,
+ order_by: orderBy
+ };
+ return this.pcrud.search(this.idlClass, search, searchOps, {fleshSelectors: true});
+ };
+ }
+
+ createNew() {
+ this.editDialog.mode = 'create';
+ const course_module_term = this.idl.create('acmt');
+ course_module_term.owning_lib(this.auth.user().ws_ou());
+ this.editDialog.recordId = null;
+ this.editDialog.record = course_module_term;
+ this.editDialog.open({size: this.dialog_size}).subscribe(
+ ok => {
+ this.createString.current()
+ .then(str => this.toast.success(str));
+ this.grid.reload();
+ },
+ rejection => {
+ if (!rejection.dismissed) {
+ this.createErrString.current()
+ .then(str => this.toast.danger(str));
+ }
+ }
+ );
+ }
+
+ editSelected(fields: IdlObject[]) {
+ this.editDialog.mode = 'update';
+ // Edit each IDL thing one at a time
+ const course_ids = [];
+ fields.forEach(field => {
+ this.editDialog.record = field;
+ this.editDialog.open({size: this.dialog_size}).subscribe(
+ ok => {
+ this.createString.current()
+ .then(str => this.toast.success(str));
+ this.grid.reload();
+ },
+ rejection => {
+ if (!rejection.dismissed) {
+ this.createErrString.current()
+ .then(str => this.toast.danger(str));
+ }
+ }
+ );
+ });
+ }
+
+ deleteSelected(fields: IdlObject[]) {
+ console.log(this.deleteLinkedTermWarningString);
+ fields.forEach(field => {
+ let termHasLinkedCourses = false;
+ this.courseSvc.getTermMaps(field.id()).subscribe(map => {
+ if (map) {
+ termHasLinkedCourses = true;
+ }
+ }, err => {
+ console.error(err);
+ }, () => {
+ if (termHasLinkedCourses) {
+ this.termToDelete = field.name();
+ this.deleteLinkedTermWarning.open().toPromise().then(yes => {
+ if (!yes) return;
+ this.doDelete(field);
+ });
+ } else {
+ this.doDelete(field);
+ }
+ });
+ });
+
+ }
+
+ doDelete(idlThing: IdlObject) {
+ idlThing.isdeleted(true);
+ this.pcrud.autoApply(idlThing).subscribe(
+ val => {
+ console.debug('deleted: ' + val);
+ this.deleteSuccessString.current()
+ .then(str => this.toast.success(str));
+ },
+ err => {
+ this.deleteFailedString.current()
+ .then(str => this.toast.danger(str));
+ },
+ () => this.grid.reload()
+ );
+ }
+}