diff --git a/src/main/ngapp/src/app/app-routing.module.ts b/src/main/ngapp/src/app/app-routing.module.ts
index c795f4118..cfbe550d0 100644
--- a/src/main/ngapp/src/app/app-routing.module.ts
+++ b/src/main/ngapp/src/app/app-routing.module.ts
@@ -29,6 +29,7 @@ import {
} from "./components/admin/admin-web-of-registries/admin-web-of-registries.component";
import {AdminSampleRequestsComponent} from "./components/admin/admin-sample-requests/admin-sample-requests.component";
import {AdminPublicGroupsComponent} from "./components/admin/admin-public-groups/admin-public-groups.component";
+import {AdminCustomFieldsComponent} from "./components/admin/admin-custom-fields/admin-custom-fields.component";
const routes: Routes = [
{path: '', redirectTo: '/collection/personal', pathMatch: 'full'},
@@ -80,7 +81,8 @@ const routes: Routes = [
{path: 'users', component: AdminUsersComponent},
{path: 'web', component: AdminWebOfRegistriesComponent},
{path: 'samples', component: AdminSampleRequestsComponent},
- {path: 'groups', component: AdminPublicGroupsComponent}
+ {path: 'groups', component: AdminPublicGroupsComponent},
+ {path: 'fields', component: AdminCustomFieldsComponent}
]
}, // todo resolver
{path: 'create/:type', component: CreateNewEntryComponent},
diff --git a/src/main/ngapp/src/app/app.module.ts b/src/main/ngapp/src/app/app.module.ts
index 2a5e64ee7..8e8b05a6d 100644
--- a/src/main/ngapp/src/app/app.module.ts
+++ b/src/main/ngapp/src/app/app.module.ts
@@ -53,6 +53,10 @@ import {
} from './components/admin/admin-web-of-registries/admin-web-of-registries.component';
import {AdminSampleRequestsComponent} from './components/admin/admin-sample-requests/admin-sample-requests.component';
import {AdminPublicGroupsComponent} from './components/admin/admin-public-groups/admin-public-groups.component';
+import {AdminCustomFieldsComponent} from './components/admin/admin-custom-fields/admin-custom-fields.component';
+import {
+ EditCustomFieldModalComponent
+} from './components/modal/edit-custom-field-modal/edit-custom-field-modal.component';
// register Handsontable's modules
registerAllModules();
@@ -102,6 +106,8 @@ registerAllModules();
AdminWebOfRegistriesComponent,
AdminSampleRequestsComponent,
AdminPublicGroupsComponent,
+ AdminCustomFieldsComponent,
+ EditCustomFieldModalComponent,
],
imports: [
BrowserModule,
diff --git a/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.css b/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.html b/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.html
new file mode 100644
index 000000000..6ab789010
--- /dev/null
+++ b/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.html
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+ Plasmid
+
+
+
+ Strain
+
+
+
+ Part
+
+
+
+ Seed
+
+
+
+ Protein
+
+
+
+
+
+
+
+
+
+
+
+ Label |
+ Field Type |
+ Entry Type |
+ Required |
+ Value(s) |
+ |
+
+
+
+ {{field.label}} |
+ {{optionsText(field.fieldType)}} |
+ {{field.entryType}} |
+
+ |
+
+ {{option.name}}
+ |
+
+
+ Permanently remove field?
+
+
+
+ |
+
+
+
+
+
+
+ No custom fields available for parts of type {{selection | capitalize}}
+
+
+
+
+
+
diff --git a/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.spec.ts b/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.spec.ts
new file mode 100644
index 000000000..1d3b3cec7
--- /dev/null
+++ b/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.spec.ts
@@ -0,0 +1,21 @@
+import {ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {AdminCustomFieldsComponent} from './admin-custom-fields.component';
+
+describe('AdminCustomFieldsComponent', () => {
+ let component: AdminCustomFieldsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [AdminCustomFieldsComponent]
+ });
+ fixture = TestBed.createComponent(AdminCustomFieldsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.ts b/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.ts
new file mode 100644
index 000000000..ef0c853a9
--- /dev/null
+++ b/src/main/ngapp/src/app/components/admin/admin-custom-fields/admin-custom-fields.component.ts
@@ -0,0 +1,81 @@
+import {Component} from '@angular/core';
+import {HttpService} from "../../../services/http.service";
+import {NgbModal, NgbModalOptions} from "@ng-bootstrap/ng-bootstrap";
+import {EditCustomFieldModalComponent} from "../../modal/edit-custom-field-modal/edit-custom-field-modal.component";
+
+@Component({
+ selector: 'app-admin-custom-fields',
+ templateUrl: './admin-custom-fields.component.html',
+ styleUrls: ['./admin-custom-fields.component.css']
+})
+export class AdminCustomFieldsComponent {
+
+ selection = 'plasmid';
+ loading: boolean;
+ partCustomFields: any;
+
+ constructor(private http: HttpService, private modalService: NgbModal) {
+ this.retrievePartFields();
+ }
+
+ options = [
+ {name: "Built in field", value: 'EXISTING'},
+ {name: 'Text', value: 'TEXT_INPUT'},
+ {name: 'Options', value: 'MULTI_CHOICE'},
+ {name: 'Options with Text', value: 'MULTI_CHOICE_PLUS'}];
+
+ optionsText(value: string): string {
+ for (let i = 0; i < this.options.length; i += 1) {
+ if (value === this.options[i].value) {
+ return this.options[i].name;
+ }
+ }
+ return value;
+ }
+
+ retrievePartFields(): void {
+ this.partCustomFields = undefined;
+ this.loading = true;
+ this.http.get("rest/fields/" + this.selection).subscribe({
+ next: (result: any) => {
+ this.partCustomFields = result.data;
+ }
+ });
+ };
+
+ selectedTab(selection: string): void {
+ if (this.selection === selection)
+ return;
+
+ this.selection = selection;
+ this.retrievePartFields();
+ };
+
+ deleteCustomField(customField: any): void {
+ this.http.delete("rest/fields/" + customField.entryType + "/" + customField.id)
+ .subscribe({
+ next: (result: any) => {
+ const index = this.partCustomFields.indexOf(customField);
+ if (index !== -1)
+ this.partCustomFields.splice(index, 1);
+ }
+ });
+ };
+
+ addNewCustomEntryField() {
+ const options: NgbModalOptions = {backdrop: 'static', size: 'md'};
+ const modalInstance = this.modalService.open(EditCustomFieldModalComponent, options);
+ modalInstance.componentInstance.entryType = this.selection;
+
+ modalInstance.result.then((result) => {
+ if (!result)
+ return;
+
+ if (!this.partCustomFields)
+ this.partCustomFields = [];
+ this.partCustomFields.push(result);
+ });
+ };
+}
+
+
diff --git a/src/main/ngapp/src/app/components/admin/admin-public-groups/admin-public-groups.component.html b/src/main/ngapp/src/app/components/admin/admin-public-groups/admin-public-groups.component.html
index f2dcf87fe..1c6be20bc 100644
--- a/src/main/ngapp/src/app/components/admin/admin-public-groups/admin-public-groups.component.html
+++ b/src/main/ngapp/src/app/components/admin/admin-public-groups/admin-public-groups.component.html
@@ -1 +1,88 @@
-admin-public-groups works!
+
+
+
+
+
+
+ No public groups available
+
+
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+
+
+
+ |
+ {{group.label}}
+
+ {{group.description || 'No description provided'}}
+ |
+
+ {{group.memberCount | number}}
+
+ |
+
+ {{group.ownerEmail}}
+ {{group.creationTime | date:'MMM d, yyyy'}}
+ |
+
+
+
+
+
+
+
+
+ Delete?
+
+
+
+ |
+
+
+
+
+
+
+ First
+
+ Prev
+
+
+ Next
+ Last
+
+
+
+
+
+
+
+ {{pageNumber | number}} - {{pageCount | number}} of {{paging.available}}
+
+
+
+
diff --git a/src/main/ngapp/src/app/components/admin/admin-public-groups/admin-public-groups.component.ts b/src/main/ngapp/src/app/components/admin/admin-public-groups/admin-public-groups.component.ts
index 807390d28..0e846cac0 100644
--- a/src/main/ngapp/src/app/components/admin/admin-public-groups/admin-public-groups.component.ts
+++ b/src/main/ngapp/src/app/components/admin/admin-public-groups/admin-public-groups.component.ts
@@ -1,4 +1,8 @@
import {Component} from '@angular/core';
+import {HttpService} from "../../../services/http.service";
+import {Group} from "../../../models/group";
+import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
+import {Paging} from "../../../models/paging";
@Component({
selector: 'app-admin-public-groups',
@@ -7,4 +11,65 @@ import {Component} from '@angular/core';
})
export class AdminPublicGroupsComponent {
+ groups = undefined;
+ group: Group;
+ loadingPage: boolean;
+ paging: Paging;
+ pageNumber: number;
+ pageCount: number;
+
+ adminGroupsPagingParams = {
+ offset: 0,
+ limit: 10,
+ available: 0,
+ currentPage: 1,
+ maxSize: 5,
+ type: 'PUBLIC'
+ };
+
+ constructor(private http: HttpService, private modalService: NgbModal) {
+ this.groupListPageChanged();
+ this.paging = new Paging();
+ }
+
+ groupListPageChanged(): void {
+ this.http.get("rest/groups", this.adminGroupsPagingParams).subscribe({
+ next: (result: any) => {
+ this.groups = result.data;
+ this.adminGroupsPagingParams.available = result.resultCount;
+ }
+ })
+ };
+
+ pageChange(page: number): void {
+ this.paging.offset = ((page - 1) * this.paging.limit);
+ }
+
+
+ openCreatePublicGroupModal(group: Group): void {
+ //
+ // const modalInstance = this.modalService.open();
+ // modalInstance.result.then(function (result) {
+ // if (!result)
+ // return;
+ //
+ // var msg = "Group successfully ";
+ // if (group && group.id)
+ // msg += "updated";
+ // else
+ // msg += "created";
+ // // Util.setFeedback(msg, "success");
+ // this.groupListPageChanged();
+ // })
+ };
+
+ deletePublicGroup(group: Group): void {
+ this.http.delete("rest/groups/" + group.id).subscribe({
+ next: () => {
+ const i = this.groups.indexOf(group);
+ if (i !== -1)
+ this.groups.splice(i, 1);
+ }
+ });
+ }
}
diff --git a/src/main/ngapp/src/app/components/admin/admin/admin.component.html b/src/main/ngapp/src/app/components/admin/admin/admin.component.html
index e12924572..0a0d53632 100644
--- a/src/main/ngapp/src/app/components/admin/admin/admin.component.html
+++ b/src/main/ngapp/src/app/components/admin/admin/admin.component.html
@@ -47,13 +47,13 @@
- Public Groups
+
Public Groups
- Custom Fields
+
Custom Fields
diff --git a/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.css b/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.html b/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.html
new file mode 100644
index 000000000..852d6c3ea
--- /dev/null
+++ b/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.html
@@ -0,0 +1,87 @@
+
+
+
+
+
Select type
+
+
+
+
+ Select built in field
+
+
+
+
+
Enter a unique label for field
+
+
+
+
+
+
Enter values for options
+
+
+
+
+
+
+
+
+
+
+
+
+
Is this field required
+
+ No
+
+
+
+ Yes
+
+
+
+
+
+
+
+ {{field.label}} *
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.spec.ts b/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.spec.ts
new file mode 100644
index 000000000..53022b7c6
--- /dev/null
+++ b/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.spec.ts
@@ -0,0 +1,21 @@
+import {ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {EditCustomFieldModalComponent} from './edit-custom-field-modal.component';
+
+describe('EditCustomFieldModalComponent', () => {
+ let component: EditCustomFieldModalComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [EditCustomFieldModalComponent]
+ });
+ fixture = TestBed.createComponent(EditCustomFieldModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.ts b/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.ts
new file mode 100644
index 000000000..3216dff29
--- /dev/null
+++ b/src/main/ngapp/src/app/components/modal/edit-custom-field-modal/edit-custom-field-modal.component.ts
@@ -0,0 +1,88 @@
+import {Component, Input} from '@angular/core';
+import {HttpService} from "../../../services/http.service";
+import {EntryService} from "../../../services/entry.service";
+import {NgbActiveModal} from "@ng-bootstrap/ng-bootstrap";
+
+@Component({
+ selector: 'app-edit-custom-field-modal',
+ templateUrl: './edit-custom-field-modal.component.html',
+ styleUrls: ['./edit-custom-field-modal.component.css']
+})
+export class EditCustomFieldModalComponent {
+
+ @Input() entryType: string;
+
+ field: any;
+ options = [
+ {name: "Built in field", value: 'EXISTING'},
+ {name: 'Text', value: 'TEXT_INPUT'},
+ {name: 'Options', value: 'MULTI_CHOICE'},
+ {name: 'Options with Text', value: 'MULTI_CHOICE_PLUS'}];
+ existingOptions: any;
+
+ constructor(public activeModal: NgbActiveModal, private http: HttpService, private entryService: EntryService) {
+ this.field = {required: false, options: [], entryType: this.entryType.toUpperCase()};
+ // this.existingOptions = this.entryService.getFieldsForType(entryType);
+ }
+
+
+ // adds option
+ addOption(afterIndex) {
+ this.field.options.push({});
+ };
+
+ removeOption(index) {
+ this.field.options.splice(index, 1);
+ };
+
+ change() {
+ switch (this.field.fieldType.value) {
+ case "MULTI_CHOICE":
+ this.field.options = [{}];
+ break;
+
+ case "MULTI_CHOICE_PLUS":
+ this.field.options = [{}];
+ break;
+ }
+ };
+
+ existingFieldSelected() {
+ this.field.required = this.field.existingFieldObject.required;
+ this.field.label = this.field.existingFieldObject.label;
+ this.field.options = [{name: "schema", value: this.field.existingFieldObject.schema}]
+ this.field.existingField = this.field.existingFieldObject.label.toUpperCase();
+ };
+
+ createCustomLink() {
+ this.field.fieldType = this.field.fieldType.value;
+ this.http.post("rest/fields/" + this.entryType, this.field).subscribe({
+ next: (result: any) => {
+ this.activeModal.close(result);
+ }
+ })
+ };
+
+ // determines whether the "create" button in the form should be enabled or disabled based on information
+ // entered by user
+ disableCreateButton() {
+ if (!this.field.label)
+ return true;
+
+ if (!this.field.fieldType)
+ return true;
+
+ switch (this.field.fieldType.value) {
+ case "MULTI_CHOICE":
+ case "MULTI_CHOICE_PLUS":
+ for (let i = 0; i < this.field.options.length; i += 1) {
+ if (!this.field.options[i].value)
+ return true;
+ }
+ break;
+ }
+
+ return false;
+ }
+
+}
diff --git a/src/main/ngapp/src/app/models/group.ts b/src/main/ngapp/src/app/models/group.ts
new file mode 100644
index 000000000..35759490a
--- /dev/null
+++ b/src/main/ngapp/src/app/models/group.ts
@@ -0,0 +1,13 @@
+export class Group {
+ id: number;
+ uuid: string;
+ label: string;
+ description: string;
+ memberCount: number;
+ type: string;
+ creationTime: number;
+ ownerEmail: string;
+
+ confirmDeleteGroup: boolean;
+
+}