diff --git a/angular/src/app/app.module.ts b/angular/src/app/app.module.ts index 33e4b115..a3571191 100644 --- a/angular/src/app/app.module.ts +++ b/angular/src/app/app.module.ts @@ -59,7 +59,6 @@ import { StreetviewAssetsComponent } from './components/streetview-assets/street import { PublicMapInfoPanelComponent } from './components/public-map-info-panel/public-map-info-panel.component'; import { LoginComponent } from './components/login/login.component'; import { LogoutComponent } from './components/logout/logout.component'; -import { ModalLinkProjectComponent } from './components/modal-link-project/modal-link-project.component'; import { ModalStreetviewPublishComponent } from './components/modal-streetview-publish/modal-streetview-publish.component'; import { ModalStreetviewLogComponent } from './components/modal-streetview-log/modal-streetview-log.component'; import { ModalStreetviewLinkComponent } from './components/modal-streetview-link/modal-streetview-link.component'; @@ -114,7 +113,6 @@ import { QuestionnaireDetailComponent } from './components/questionnaire-detail/ PublicMapInfoPanelComponent, LoginComponent, LogoutComponent, - ModalLinkProjectComponent, ModalStreetviewPublishComponent, ModalStreetviewLogComponent, ModalStreetviewLinkComponent, @@ -199,7 +197,6 @@ import { QuestionnaireDetailComponent } from './components/questionnaire-detail/ ModalStreetviewUsernameComponent, ModalStreetviewOrganizationComponent, ModalPointCloudInfoComponent, - ModalLinkProjectComponent, ModalQuestionnaireViewerComponent, ], }) diff --git a/angular/src/app/components/modal-create-project/modal-create-project.component.html b/angular/src/app/components/modal-create-project/modal-create-project.component.html index 5c51913e..6ecab766 100644 --- a/angular/src/app/components/modal-create-project/modal-create-project.component.html +++ b/angular/src/app/components/modal-create-project/modal-create-project.component.html @@ -66,6 +66,8 @@

Create a new Map

- +
diff --git a/angular/src/app/components/modal-create-project/modal-create-project.component.ts b/angular/src/app/components/modal-create-project/modal-create-project.component.ts index 48b4436c..a0aa7885 100644 --- a/angular/src/app/components/modal-create-project/modal-create-project.component.ts +++ b/angular/src/app/components/modal-create-project/modal-create-project.component.ts @@ -67,28 +67,22 @@ export class ModalCreateProjectComponent implements OnInit, AfterContentChecked submit() { this.submitting = true; - const p = new Project(); const pr = new ProjectRequest(); - p.description = this.projCreateForm.get('description').value; - p.name = this.projCreateForm.get('name').value; - p.system_path = this.selectedFiles.length > 0 ? this.selectedFiles[0].path || '/' : this.currentPath || '/'; + pr.description = this.projCreateForm.get('description').value; + pr.name = this.projCreateForm.get('name').value; + pr.system_path = this.selectedFiles.length > 0 ? this.selectedFiles[0].path || '/' : this.currentPath || '/'; - p.system_id = this.selectedSystem.id; - p.system_file = this.projCreateForm.get('fileName').value ? this.projCreateForm.get('fileName').value : p.name; + pr.system_id = this.selectedSystem.id; + pr.system_file = this.projCreateForm.get('fileName').value ? this.projCreateForm.get('fileName').value : pr.name; if (this.selectedSystem.id.includes('project')) { - pr.observable = true; - pr.watch_content = this.projCreateForm.get('watchContent').value; - } else { - pr.observable = this.projCreateForm.get('watchContent').value; - pr.watch_content = pr.observable; + pr.watch_users = true; } + pr.watch_content = this.projCreateForm.get('watchContent').value; this.errorMessage = ''; - pr.project = p; - this.projectsService.create(pr).subscribe( (project) => { this.close(project); diff --git a/angular/src/app/components/modal-link-project/modal-link-project.component.html b/angular/src/app/components/modal-link-project/modal-link-project.component.html deleted file mode 100644 index aec7875c..00000000 --- a/angular/src/app/components/modal-link-project/modal-link-project.component.html +++ /dev/null @@ -1,47 +0,0 @@ - - - -
- - If a name is not given, file will be saved as the map uuid. -
- -
- -
- -
- Saving this map will remove the previous link. -
- -
- - -
diff --git a/angular/src/app/components/modal-link-project/modal-link-project.component.spec.ts b/angular/src/app/components/modal-link-project/modal-link-project.component.spec.ts deleted file mode 100644 index b66d0fa1..00000000 --- a/angular/src/app/components/modal-link-project/modal-link-project.component.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { ModalLinkProjectComponent } from './modal-link-project.component'; - -describe('ModalLinkProjectComponent', () => { - let component: ModalLinkProjectComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ModalLinkProjectComponent], - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(ModalLinkProjectComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/angular/src/app/components/modal-link-project/modal-link-project.component.styl b/angular/src/app/components/modal-link-project/modal-link-project.component.styl deleted file mode 100644 index c8a21fc4..00000000 --- a/angular/src/app/components/modal-link-project/modal-link-project.component.styl +++ /dev/null @@ -1,10 +0,0 @@ -:host - .dimmed - color #ccc - .confirm-checkbox - padding 0px 0px 20px 0px - label - font-size 19px - span - padding-right 10px - diff --git a/angular/src/app/components/modal-link-project/modal-link-project.component.ts b/angular/src/app/components/modal-link-project/modal-link-project.component.ts deleted file mode 100644 index eec00a4f..00000000 --- a/angular/src/app/components/modal-link-project/modal-link-project.component.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { RemoteFile } from 'ng-tapis/models/remote-file'; -import { Project, ProjectRequest } from '../../models/models'; -import { ProjectsService } from '../../services/projects.service'; -import { BsModalRef } from 'ngx-foundation/modal/bs-modal-ref.service'; -import { Subject } from 'rxjs'; -import { TapisFilesService } from '../../services/tapis-files.service'; -import { ChangeDetectorRef } from '@angular/core'; -import { RapidProjectRequest } from '../../models/rapid-project-request'; -import { NotificationsService } from '../../services/notifications.service'; - -@Component({ - selector: 'app-modal-link-project', - templateUrl: './modal-link-project.component.html', - styleUrls: ['./modal-link-project.component.styl'], -}) -export class ModalLinkProjectComponent implements OnInit { - @Input() allowedExtensions: Array = []; - @Input() single: true; - @Input() allowFolders: true; - @Input() onlyFolder: true; - @Input() allowEmptyFiles: true; - - selectedFiles: Array = []; - selectedSystem: any; - fileName = ''; - watchContent = false; - activeProject: Project; - currentPath: string; - projectObserveOptions = [ - { name: 'Sync Members and Files', value: true }, - { name: 'Sync Only Members', value: false }, - ]; - myDataObserveOptions = [ - { name: "Don't Sync", value: false }, - { name: 'Sync Files', value: true }, - ]; - observeOptions = this.myDataObserveOptions; - observeOption = false; - - constructor(private modalRef: BsModalRef, private projectsService: ProjectsService, private cdref: ChangeDetectorRef) {} - - ngOnInit() { - this.projectsService.activeProject.subscribe((next) => { - this.activeProject = next; - this.fileName = next.uuid; - }); - } - - // tslint:disable-next-line - ngAfterContentChecked() { - this.cdref.detectChanges(); - } - - onSelect(items: Array) { - this.selectedFiles = items; - } - - onSystemSelect(system: any) { - this.selectedSystem = system; - this.observeOption = false; - if (system.id.startsWith('project')) { - this.observeOptions = this.projectObserveOptions; - } else { - this.observeOptions = this.myDataObserveOptions; - } - } - - setCurrentPath(path: string) { - this.currentPath = path; - } - - submit() { - const path = this.selectedFiles.length > 0 ? this.selectedFiles[0].path : this.currentPath; - - this.activeProject.system_path = path; - this.activeProject.system_id = this.selectedSystem.id; - this.activeProject.system_file = this.fileName; - - const pr = new ProjectRequest(); - - pr.project = this.activeProject; - - if (this.selectedSystem.id.includes('project')) { - pr.observable = true; - pr.watch_content = this.observeOption; - } else { - pr.observable = this.observeOption; - pr.watch_content = pr.observable ? true : false; - } - - // this.projectsService.updateProject(this.activeProject, pr); - this.projectsService.updateProject(pr); - this.close(); - } - - close() { - this.modalRef.hide(); - } -} diff --git a/angular/src/app/components/users-panel/users-panel.component.ts b/angular/src/app/components/users-panel/users-panel.component.ts index f8610992..da88ecc3 100644 --- a/angular/src/app/components/users-panel/users-panel.component.ts +++ b/angular/src/app/components/users-panel/users-panel.component.ts @@ -4,9 +4,8 @@ import { NotificationsService } from '../../services/notifications.service'; import { ModalService } from '../../services/modal.service'; import { TabsetComponent, BsModalService } from 'ngx-foundation'; import { IProjectUser } from '../../models/project-user'; -import { Project, ProjectRequest } from '../../models/models'; +import { Project, ProjectUpdateRequest } from '../../models/models'; import { EnvService } from '../../services/env.service'; -import { ModalLinkProjectComponent } from '../modal-link-project/modal-link-project.component'; import { AgaveSystemsService } from 'src/app/services/agave-systems.service'; import { combineLatest } from 'rxjs'; import { copyToClipboard } from '../../utils/copyText'; @@ -71,10 +70,6 @@ export class UsersPanelComponent implements OnInit { return publicUrl; } - openExportProjectModal() { - this.bsModalService.show(ModalLinkProjectComponent); - } - copyLinkToClipboard(link: string) { copyToClipboard(link); this.notificationsService.showSuccessToast(`Copied ${link} to the clipboard!`); @@ -131,10 +126,10 @@ export class UsersPanelComponent implements OnInit { this.nameInputError = false; this.activeProject.name = name; - const pr = new ProjectRequest(); - pr.project = this.activeProject; + const pr = new ProjectUpdateRequest(); + pr.name = this.activeProject.name; - this.projectsService.updateProject(pr); + this.projectsService.updateProject(this.activeProject, pr); } else { this.nameInputError = true; } @@ -145,10 +140,10 @@ export class UsersPanelComponent implements OnInit { this.descriptionInputError = false; this.activeProject.description = description; - const pr = new ProjectRequest(); - pr.project = this.activeProject; + const pr = new ProjectUpdateRequest(); + pr.description = this.activeProject.description; - this.projectsService.updateProject(pr); + this.projectsService.updateProject(this.activeProject, pr); } else { this.descriptionInputError = true; } diff --git a/angular/src/app/models/models.ts b/angular/src/app/models/models.ts index cd7ec34c..3ee538fe 100644 --- a/angular/src/app/models/models.ts +++ b/angular/src/app/models/models.ts @@ -2,11 +2,6 @@ import { Feature as GeoJSONFeature, GeoJsonProperties, Geometry, FeatureCollecti // TODO: break these out into their own files -export enum AgaveFileOperations { - Delete, - Update, -} - export interface IFileImportRequest { system_id: string; path: string; @@ -65,13 +60,26 @@ export interface Project { export class Project implements Project {} export interface ProjectRequest { - project: Project; - observable?: boolean; - watch_content?: boolean; + name: string; + description: string; + public: boolean; + system_file: string; + system_id: string; + system_path: string; + watch_content: boolean; + watch_users: boolean; } export class ProjectRequest implements ProjectRequest {} +export interface ProjectUpdateRequest { + name?: string; + description?: string; + public?: boolean; +} + +export class ProjectUpdateRequest implements ProjectUpdateRequest {} + export class AuthToken { token: string; expires: Date; diff --git a/angular/src/app/models/rapid-project-request.ts b/angular/src/app/models/rapid-project-request.ts deleted file mode 100644 index 1b922e19..00000000 --- a/angular/src/app/models/rapid-project-request.ts +++ /dev/null @@ -1,17 +0,0 @@ -class RapidProjectRequest { - system_id: string; - project_id: number; - file_name: string; - watch_content: boolean; - path: string; - - constructor(systemId: string, path: string, watchContent: boolean, projectId?: number, fileName?: string) { - this.system_id = systemId; - this.project_id = projectId ? projectId : undefined; - this.file_name = fileName ? fileName : ''; - this.watch_content = watchContent; - this.path = path; - } -} - -export { RapidProjectRequest }; diff --git a/angular/src/app/services/agave-systems.service.ts b/angular/src/app/services/agave-systems.service.ts index fc74e076..05ee7b69 100644 --- a/angular/src/app/services/agave-systems.service.ts +++ b/angular/src/app/services/agave-systems.service.ts @@ -1,12 +1,12 @@ import { Injectable } from '@angular/core'; -import { System, SystemSummary } from 'ng-tapis'; +import { SystemSummary } from 'ng-tapis'; import { ApiService } from 'ng-tapis'; import { NotificationsService } from './notifications.service'; import { BehaviorSubject, Observable, ReplaySubject, combineLatest } from 'rxjs'; import { map } from 'rxjs/operators'; -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { EnvService } from '../services/env.service'; -import { DesignSafeProjectCollection, Project, AgaveFileOperations } from '../models/models'; +import { DesignSafeProjectCollection, Project } from '../models/models'; export interface AgaveProjectsData { projects: SystemSummary[]; @@ -89,92 +89,4 @@ export class AgaveSystemsService { } return projects; } - - updateProjectMetadata(proj: Project, operation: AgaveFileOperations) { - const DSuuid = proj.system_id.replace('project-', ''); - const uuid = proj.uuid; - const path = proj.system_path; - const name = proj.name; - - this.http.get(this.envService.designSafeUrl + `projects/v2/${DSuuid}/`).subscribe((dsProject) => { - const previousMaps = dsProject.value.hazmapperMaps ? dsProject.value.hazmapperMaps.filter((e) => e.uuid !== uuid) : []; - - const payloadProject = - operation === AgaveFileOperations.Update - ? [ - { - name, - uuid, - path, - deployment: this.envService.env, - }, - ] - : []; - - const payload = { - DSuuid, - hazmapperMaps: [...previousMaps, ...payloadProject], - }; - - const headers = new HttpHeaders().set('X-Requested-With', 'XMLHttpRequest'); - - this.http.post(this.envService.designSafeUrl + `projects/v2/${DSuuid}/`, payload, { headers }).subscribe( - (resp) => { - console.log(resp); - }, - (error) => { - console.log(error); - } - ); - }); - } - - public saveFile(proj: Project) { - const data = JSON.stringify({ - uuid: proj.uuid, - deployment: this.envService.env, - }); - - this.tapis - .filesImport({ - systemId: proj.system_id, - filePath: proj.system_path, - body: { - fileType: 'plain/text', - callbackURL: '', - fileName: `${proj.system_file}.hazmapper`, - urlToIngest: '', - fileToUpload: data, - }, - }) - .subscribe( - (resp) => { - this.notificationsService.showSuccessToast(`Successfully saved file to ${proj.system_id}${proj.system_path}.`); - }, - (error) => { - this.notificationsService.showErrorToast(`Failed to save file to ${proj.system_id}${proj.system_path}.`); - } - ); - } - - public deleteFile(proj: Project) { - this.tapis - .filesDelete({ - systemId: proj.system_id, - filePath: `${proj.system_path}/${proj.system_file}.hazmapper`, - }) - .subscribe( - (resp) => { - this.notificationsService.showSuccessToast( - `Successfully deleted file ${proj.system_id}${proj.system_path}/${proj.system_file}.hazmapper.` - ); - }, - (error) => { - // TODO: Handle this - // 404 happens when redundant delete - // 502/500 I'm not sure why... - console.log(error); - } - ); - } } diff --git a/angular/src/app/services/geo-data.service.ts b/angular/src/app/services/geo-data.service.ts index 508b7943..9699f41a 100644 --- a/angular/src/app/services/geo-data.service.ts +++ b/angular/src/app/services/geo-data.service.ts @@ -279,12 +279,6 @@ export class GeoDataService { .subscribe(); } - addDefaultTileServers(projectId: number): void { - defaultTileServers.forEach((ts) => { - this.addTileServer(projectId, ts, true); - }); - } - importFeatureAsset(projectId: number, featureId: number, payload: IFileImportRequest): void { this.http.post(this.envService.apiUrl + `/projects/${projectId}/features/${featureId}/assets/`, payload).subscribe( (feature) => { diff --git a/angular/src/app/services/projects.service.ts b/angular/src/app/services/projects.service.ts index 9b078238..bb73ef18 100644 --- a/angular/src/app/services/projects.service.ts +++ b/angular/src/app/services/projects.service.ts @@ -1,17 +1,14 @@ import { Injectable } from '@angular/core'; -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { BehaviorSubject, Observable, ReplaySubject, combineLatest } from 'rxjs'; -import { DesignSafeProjectCollection, Project, ProjectRequest, AgaveFileOperations } from '../models/models'; -import { RapidProjectRequest } from '../models/rapid-project-request'; +import { Project, ProjectRequest, ProjectUpdateRequest } from '../models/models'; import { IpanelsDisplay, defaultPanelsDisplay } from '../models/ui'; -import { catchError, map, tap, filter, take } from 'rxjs/operators'; +import { catchError, map, tap } from 'rxjs/operators'; import { IProjectUser } from '../models/project-user'; import { NotificationsService } from './notifications.service'; -import { GeoDataService } from './geo-data.service'; import { EnvService } from '../services/env.service'; import { AuthService } from '../services/authentication.service'; -import { MAIN, LOGIN } from '../constants/routes'; -import { AgaveSystemsService } from '../services/agave-systems.service'; +import { MAIN } from '../constants/routes'; import { Router } from '@angular/router'; export interface ProjectsData { @@ -58,8 +55,6 @@ export class ProjectsService { constructor( private http: HttpClient, private notificationsService: NotificationsService, - private geoDataService: GeoDataService, - private agaveSystemsService: AgaveSystemsService, private router: Router, private authService: AuthService, private envService: EnvService @@ -115,43 +110,12 @@ export class ProjectsService { ); } - // TODO: Utilize project metdata - addUserToProject(proj: Project, uname: string): void { - const payload = { - username: uname, - }; - this.http.post(this.envService.apiUrl + `/projects/${proj.id}/users/`, payload).subscribe((resp) => { - this.getProjectUsers(proj).subscribe(); - }); - } - - // TODO: Utilize project metdata - deleteUserFromProject(proj: Project, uname: string): void { - this.http.delete(this.envService.apiUrl + `/projects/${proj.id}/users/${uname}/`).subscribe( - (resp) => { - this.getProjectUsers(proj).subscribe(); - }, - (error) => { - this.notificationsService.showErrorToast('Unable to delete user'); - } - ); - } - create(data: ProjectRequest): Observable { return this.http.post(this.envService.apiUrl + `/projects/`, data).pipe( tap( (proj) => { - if (data.observable || proj.system_path) { - this.agaveSystemsService.saveFile(proj); - } - - if (proj.system_id && proj.system_id.startsWith('project')) { - this.agaveSystemsService.updateProjectMetadata(proj, AgaveFileOperations.Update); - } - // Spread operator, just pushes the new project into the array this._projects.next([...this._projects.value, proj]); - this.geoDataService.addDefaultTileServers(proj.id); }, (error) => { console.log(error); @@ -203,10 +167,6 @@ export class ProjectsService { } deleteProject(proj: Project): void { - if (proj.system_id && proj.system_id.startsWith('project')) { - this.agaveSystemsService.updateProjectMetadata(proj, AgaveFileOperations.Delete); - } - this._deletingProjects.next([...this._deletingProjects.value, { ...proj, deleting: true }]); this.updateProjectsList(); @@ -214,10 +174,6 @@ export class ProjectsService { this.http.delete(this.envService.apiUrl + `/projects/${proj.id}/`).subscribe( (resp) => { - if (proj.system_path || proj.ds_id) { - this.agaveSystemsService.deleteFile(proj); - } - this._deletingProjects.next(this._deletingProjects.value.filter((p) => p.id !== proj.id)); this.updateProjectsList(); this.getProjects(); @@ -238,8 +194,8 @@ export class ProjectsService { ); } - updateProject(req: ProjectRequest): void { - this.http.put(this.envService.apiUrl + `/projects/${req.project.id}/`, req).subscribe((resp) => { + updateProject(project: Project, projectUpdate: ProjectUpdateRequest): void { + this.http.put(this.envService.apiUrl + `/projects/${project.id}/`, projectUpdate).subscribe((resp) => { this.notificationsService.showSuccessToast('Uploaded file!'); }); } @@ -249,12 +205,10 @@ export class ProjectsService { description = description ? description : this._activeProject.value.description; isPublic = isPublic !== undefined ? isPublic : this._activeProject.value.public; - const payload: ProjectRequest = { - project: { - name, - description, - public: isPublic, - }, + const payload: ProjectUpdateRequest = { + name, + description, + public: isPublic, }; return this.http.put(this.envService.apiUrl + `/projects/${this._activeProject.value.id}/`, payload).pipe(