diff --git a/angular/src/app/_helpers/fakeBackendInterceptor.ts b/angular/src/app/_helpers/fakeBackendInterceptor.ts index 0cd8118d9..de07fc16f 100644 --- a/angular/src/app/_helpers/fakeBackendInterceptor.ts +++ b/angular/src/app/_helpers/fakeBackendInterceptor.ts @@ -6,10 +6,17 @@ import { userInfo } from 'os'; @Injectable() export class FakeBackendInterceptor implements HttpInterceptor { - + _storage: Storage = null; constructor(private http: HttpClient) { } intercept(request: HttpRequest, next: HttpHandler): Observable> { + //Read local storage, if exist, set the flag so the alert will not display again + //Otherwise, set storage and display alert + if(!localStorage.getItem("fakebackend")) { + localStorage.setItem("fakebackend", "true"); + alert("You are using fake backend!"); + } + // array in local storage for registered users // const sampleData: any = require('../../assets/science-theme/BiometricsScienceTheme.json'); @@ -44,8 +51,6 @@ export class FakeBackendInterceptor implements HttpInterceptor { // wrap in delayed observable to simulate server api call return of(null).pipe(mergeMap(() => { - alert("You are using fake backend!"); - console.log("request.url", request.url); // RPA diff --git a/angular/src/app/landing/contact/contact.component.html b/angular/src/app/landing/contact/contact.component.html index abbb60203..dc7c9eeca 100644 --- a/angular/src/app/landing/contact/contact.component.html +++ b/angular/src/app/landing/contact/contact.component.html @@ -14,7 +14,7 @@ href="{{record.contactPoint.hasEmail}}" target="_top"> {{record.contactPoint.fn}} {{record.contactPoint.fn}} - .. + . diff --git a/angular/src/app/landing/facilitators/facilitators.component.html b/angular/src/app/landing/facilitators/facilitators.component.html index b523099eb..647f54119 100644 --- a/angular/src/app/landing/facilitators/facilitators.component.html +++ b/angular/src/app/landing/facilitators/facilitators.component.html @@ -4,7 +4,7 @@
- + {{facilitator.fn.trim()}},.
- - +
+ + +
@@ -44,14 +46,14 @@ + (filterObj)="updateFilterObj($event, '@type')">
+ (filterObj)="updateFilterObj($event, 'components.@type')">
@@ -66,7 +68,7 @@
{{author}}
@@ -84,7 +86,7 @@
{{keyword}}
diff --git a/angular/src/app/landing/filters/filters.component.ts b/angular/src/app/landing/filters/filters.component.ts index b19c1e585..e1144810d 100644 --- a/angular/src/app/landing/filters/filters.component.ts +++ b/angular/src/app/landing/filters/filters.component.ts @@ -72,7 +72,7 @@ export class FiltersComponent implements OnInit { clearAllCheckbox: boolean = false; collectionThemesWithCount: FilterTreeNode[] = []; - filterStrings = {}; + filterObjs = {}; // Object that hold all themes: Forensics, NIST, ... allCollections: any = {}; @@ -144,7 +144,7 @@ export class FiltersComponent implements OnInit { @Input() collection: string = Collections.FORENSICS; @Input() taxonomyURI: any = {}; @Output() filterMode = new EventEmitter(); // normal or collapsed - @Output() filterString = new EventEmitter(); + @Output() filterObjsOut = new EventEmitter(); constructor( public taxonomyListService: TaxonomyListService, @@ -157,7 +157,7 @@ export class FiltersComponent implements OnInit { } ngOnInit(): void { - this.collectionService.loadAllCollections(); + // this.collectionService.loadAllCollections(); this.collectionOrder = this.collectionService.getCollectionOrder(); this.msgs = []; @@ -180,97 +180,76 @@ export class FiltersComponent implements OnInit { * Update the filter string object based on the input filter string * @param $event filter string returned from app-taxonomy */ - updateFilterString(event, collection: string) { - let _filterString = event; - if(!event) _filterString = ""; + updateFilterObj(event, collection: string) { + let _filterObj = event; + if(!event) _filterObj = null; - this.filterStrings[collection] = _filterString; + this.filterObjs[collection] = _filterObj; - this.filterResults(); - } - - /** - * Replace reserved chars with char name to avoid problems - * when parsing filter string in the result list component. - * For example, replace "&" with "aaamp". result list component - * restore "aaamp" back to "&". - * @param strng input string - */ - escapeReservedChars(inputStrng: string) { - let outputString: string; - if(!inputStrng || inputStrng.trim() == "") - return ""; - else - return inputStrng.replace(new RegExp("&", "g"), "aaamp") + this.createFilterObj(); } /** * Form the filter string and refresh the result page */ - filterResults() { - let lFilterString: string = ""; - this.selectedThemes = []; - this.selectedComponents = []; - this.selectedResourceType = []; - let componentSelected: boolean = false; - let resourceTypesSelected: boolean = false; - let compType = ''; - let resourceType = ''; + createFilterObj() { + let lFilterObjs: any[] = []; // Resource type - if(this.filterStrings["@type"]) { - if(lFilterString != '') lFilterString += "&"; - lFilterString += this.escapeReservedChars(this.filterStrings["@type"]); - lFilterString = this.removeEndingComma(lFilterString); + if(this.filterObjs["@type"] && this.filterObjs["@type"].value.length>0) { + lFilterObjs.push(this.filterObjs["@type"]); } // Collections for(let col of this.collectionOrder) { - if(this.filterStrings[col]) { - if(lFilterString != '') lFilterString += "&"; - lFilterString += this.escapeReservedChars(this.filterStrings[col]); - lFilterString = this.removeEndingComma(lFilterString); + if(this.filterObjs[col] && this.filterObjs[col].value && this.filterObjs[col].value.length>0) { + lFilterObjs.push(this.filterObjs[col]); } } // Record has - if(this.filterStrings["components.@type"]) { - if(lFilterString != '') lFilterString += "&"; - lFilterString += this.escapeReservedChars(this.filterStrings["components.@type"]); - lFilterString = this.removeEndingComma(lFilterString); + if(this.filterObjs["components.@type"] && this.filterObjs["components.@type"].value.length>0) { + lFilterObjs.push(this.filterObjs["components.@type"]); } // Authors and contributors if (this.selectedAuthor.length > 0) { - if(lFilterString != '') lFilterString += "&"; - - lFilterString += "contactPoint.fn="; - + let authors: string[] = []; + for (let author of this.selectedAuthor) { - lFilterString += author + ","; + authors.push(author); } - } - lFilterString = this.removeEndingComma(lFilterString); + lFilterObjs.push({ + "type": "contactPoint.fn", + "value": authors + }) + } // Keywords if (this.selectedKeywords.length > 0) { - if(lFilterString != '') lFilterString += "&"; + let keywords: string[] = []; - lFilterString += "keyword="; for (let keyword of this.selectedKeywords) { - lFilterString += this.escapeReservedChars(this.suggestedKeywordsLkup[keyword]) + ","; + keywords.push(this.suggestedKeywordsLkup[keyword]); } + + lFilterObjs.push({ + "type": "keyword", + "value": keywords + }) } - lFilterString = this.removeEndingComma(lFilterString); - if(!lFilterString) lFilterString = "NoFilter"; + if(!lFilterObjs || lFilterObjs.length == 0) { + lFilterObjs.push({ + "type": "NoFilter", + "value": "" + }) + } - // console.log('lFilterString', lFilterString); - this.filterString.emit(lFilterString); + this.filterObjsOut.emit(lFilterObjs); } - /** * If search value changed, clear the filters and refresh the search result. * @param changes - changed detected @@ -506,7 +485,6 @@ export class FiltersComponent implements OnInit { } } - this.resourceTypeTree = [{ label: 'Type of Resource', "expanded": false, @@ -702,11 +680,7 @@ export class FiltersComponent implements OnInit { this.searchService.setClearAll(false); }, 0) - this.filterStrings = {}; - this.filterStrings[Collections.DEFAULT] = ""; - this.filterStrings[Collections.FORENSICS] = ""; - this.filterStrings[Collections.SEMICONDUCTORS] = ""; - + this.filterObjs = {}; this.suggestedThemes = []; this.suggestedKeywords = []; this.suggestedAuthors = []; @@ -748,7 +722,6 @@ export class FiltersComponent implements OnInit { setTimeout(() => { this.clearAllCheckbox = false; }, 0) - // this.filterResults() } /** diff --git a/angular/src/app/landing/landingpage.component.html b/angular/src/app/landing/landingpage.component.html index 80405fc92..65f7afe4a 100644 --- a/angular/src/app/landing/landingpage.component.html +++ b/angular/src/app/landing/landingpage.component.html @@ -8,9 +8,9 @@
-
+
-
+
@@ -19,12 +19,15 @@
-
+
diff --git a/angular/src/app/landing/landingpage.component.scss b/angular/src/app/landing/landingpage.component.scss index d231fd5fe..089e60527 100644 --- a/angular/src/app/landing/landingpage.component.scss +++ b/angular/src/app/landing/landingpage.component.scss @@ -52,10 +52,18 @@ z-index: 10; } +.stickyPopupMenu { + position: absolute; + right: 1em; + width: 2.3em; + height: 2.3em; + z-index: 10; +} + .sticky-menu-popup { float: right; - position: sticky; - margin-top: 4em; + // position: sticky; + margin-top: 10px; right: 2em; width: 10em; height: 2.3em; diff --git a/angular/src/app/landing/landingpage.component.ts b/angular/src/app/landing/landingpage.component.ts index 8a9031ad3..267f1ba1f 100644 --- a/angular/src/app/landing/landingpage.component.ts +++ b/angular/src/app/landing/landingpage.component.ts @@ -102,6 +102,8 @@ export class LandingPageComponent implements OnInit, AfterViewInit { collectionObj: any; buttonTop: number = 20; + stickPopupMenuDiv: any; + stickPopupMenuTop: number = 176; showStickMenu: boolean = false; @@ -115,6 +117,8 @@ export class LandingPageComponent implements OnInit, AfterViewInit { @ViewChild(LandingBodyComponent) landingBodyComponent: LandingBodyComponent; + @ViewChild('stickyPopupMenu') stickyPopupMenu: ElementRef; + // @ViewChild(MetricsinfoComponent) // metricsinfoComponent: MetricsinfoComponent; @@ -122,6 +126,17 @@ export class LandingPageComponent implements OnInit, AfterViewInit { @ViewChild('stickyMenu') menuElement: ElementRef; @ViewChild('test') test: ElementRef; + @HostListener('window:scroll', ['$event']) + onScroll(event: Event) { + // Get the current scroll position + const scrollY = window.scrollY; + // Do something based on the scroll position + let dif = 176 - scrollY; + if (dif < 20) { + this.stickPopupMenuTop = scrollY + 20; + } + } + /** * create the component. * @param route the requested URL path to be fulfilled with this view @@ -186,6 +201,12 @@ export class LandingPageComponent implements OnInit, AfterViewInit { * the Angular rendering infrastructure. */ ngOnInit() { + //Clean up fabebackend in local storage so an alert will display if fake back end is used. + //If fake back end is used, the alert will show up only once. + if(localStorage.getItem("fakebackend")) { + localStorage.removeItem("fakebackend"); + } + this.recordLevelMetrics = new RecordLevelMetrics(); var showError: boolean = true; let metadataError = ""; @@ -303,6 +324,25 @@ export class LandingPageComponent implements OnInit, AfterViewInit { }); } + /** + * apply housekeeping after view has been initialized + */ + ngAfterViewInit() { + if(this.inBrowser) { + this.stickPopupMenuDiv = this.stickyPopupMenu.nativeElement.getBoundingClientRect(); + //Set the position of the sticky menu (or menu button) + setTimeout(() => { + this.setMenuPosition(); + }, 0); + } + + if (this.md && this.inBrowser) { + this.useFragment(); + + window.history.replaceState({}, '', '/od/id/' + this.reqId); + } + } + getCollection() { if(this.pdrid.includes("pdr0-0001")) this.collection = Collections.FORENSICS; @@ -391,11 +431,11 @@ export class LandingPageComponent implements OnInit, AfterViewInit { /** * Detect window scroll */ - @HostListener("window:scroll", []) - onWindowScroll() { - if(this.mobileMode) - this.buttonTop = window.pageYOffset > 200? 10 : 200 - window.pageYOffset; - } + // @HostListener("window:scroll", []) + // onWindowScroll() { + // if(this.mobileMode) + // this.buttonTop = window.pageYOffset > 200? 10 : 200 - window.pageYOffset; + // } /** * When storage changed, if it's dataCartStatus and action is "set download completed", @@ -462,24 +502,6 @@ export class LandingPageComponent implements OnInit, AfterViewInit { return ""; } - /** - * apply housekeeping after view has been initialized - */ - ngAfterViewInit() { - if(this.inBrowser) { - //Set the position of the sticky menu (or menu button) - setTimeout(() => { - this.setMenuPosition(); - }, 0); - } - - if (this.md && this.inBrowser) { - this.useFragment(); - - window.history.replaceState({}, '', '/od/id/' + this.reqId); - } - } - /** * Set the position of the sticky menu (or menu button) */ diff --git a/angular/src/app/landing/resultlist/resultlist.component.html b/angular/src/app/landing/resultlist/resultlist.component.html index 216351824..3dab3105d 100644 --- a/angular/src/app/landing/resultlist/resultlist.component.html +++ b/angular/src/app/landing/resultlist/resultlist.component.html @@ -36,7 +36,7 @@
diff --git a/angular/src/app/landing/resultlist/resultlist.component.ts b/angular/src/app/landing/resultlist/resultlist.component.ts index 5b6d639df..812af691a 100644 --- a/angular/src/app/landing/resultlist/resultlist.component.ts +++ b/angular/src/app/landing/resultlist/resultlist.component.ts @@ -79,7 +79,7 @@ export class ResultlistComponent implements OnInit { @Input() searchTaxonomyKey: string; @Input() mobWidth: number = 1920; @Input() resultWidth: string = '400px'; - @Input() filterString: string = ''; + @Input() filterObjs: any[] = []; @Input() collection: string = Collections.FORENSICS; @Input() taxonomyURI: any = {}; @@ -91,7 +91,7 @@ export class ResultlistComponent implements OnInit { this.searchService.watchClearAll((clearAll: boolean) => { if(clearAll) { this.searchPhases = ""; - this.filterResults(); + this.filterResultsNew(); } }); } @@ -123,8 +123,8 @@ export class ResultlistComponent implements OnInit { } ngOnChanges(changes: SimpleChanges): void { - if(changes.filterString != null && changes.filterString != undefined) { - this.filterResults(); + if(changes.filterObjs != null && changes.filterObjs != undefined) { + this.filterResultsNew(); } } @@ -166,7 +166,7 @@ export class ResultlistComponent implements OnInit { item.active = true; } - this.filterResults(); + this.filterResultsNew(); this.sortByDate(); this.showResultList = true; @@ -383,27 +383,23 @@ export class ResultlistComponent implements OnInit { /** * Apply filters from left side panel and the search word(s) from the search text box */ - filterResults() { + filterResultsNew() { if(this.searchResults == undefined) return; let filters: string[]; - - // Reset the search result - this.resetResult(this.filterString=="NoFilter"); + this.resetResult(this.filterObjs[0].type == "NoFilter"); // Handle filters - if(this.filterString != "noFilter" && this.filterString != ""){ - filters = this.filterString.split("&"); - filters.forEach((filter) => { - switch(filter.split("=")[0]){ + if(this.filterObjs && this.filterObjs.length > 0){ + this.filterObjs.forEach((filter) => { + switch(filter.type){ case "@type": this.searchResults.forEach((object) => { if(!object.active){ // object.active = false; object["@type"].forEach((oType) => { - let types = filter.split("=")[1].split(","); - types.forEach(type => { + filter.value.forEach(type => { if(oType.toLowerCase().includes(this.restoreReservedChars(type).toLowerCase())) object.active = true; }); @@ -413,14 +409,13 @@ export class ResultlistComponent implements OnInit { break; case "topic.tag": - let topics = filter.split("=")[1].split(","); for(let resultItem of this.searchResults) { if(!resultItem.active){ // resultItem.active = false; for(let oTopic of resultItem["topic"]) { - for(let topic of topics) { + for(let topic of filter.value) { let collection = topic.split("----")[0]; let topicValue = this.restoreReservedChars(topic.split("----")[1]); @@ -447,8 +442,7 @@ export class ResultlistComponent implements OnInit { object["components"].forEach((component) => { component["@type"].forEach((cType) => { - let types = filter.split("=")[1].split(","); - types.forEach(type => { + filter.value.forEach(type => { if(cType.toLowerCase().includes(this.restoreReservedChars(type).toLowerCase())) object.active = true; }); @@ -465,8 +459,8 @@ export class ResultlistComponent implements OnInit { this.searchResults.forEach((object) => { if(!object.active){ // object.active = false; - - if(object["contactPoint"]["fn"].includes(filter.split("=")[1])) + if(filter.value.find((str) => str === object["contactPoint"]["fn"])) + // if(object["contactPoint"]["fn"].includes(filter.value[0])) object.active = true; } }); @@ -481,8 +475,8 @@ export class ResultlistComponent implements OnInit { object["keyword"].forEach((keyword) => { //Loop through each search keyword from keyword filter - filter.split("=")[1].split(",").forEach(kw => { - if(keyword.toLowerCase().includes(this.restoreReservedChars(kw))){ + filter.value.forEach(kw => { + if(keyword.toLowerCase().includes(kw)){ object.active = true; } }) @@ -497,6 +491,7 @@ export class ResultlistComponent implements OnInit { }) } + // Handle search text box first this.filterResultByPhase(this.searchPhases); diff --git a/angular/src/app/landing/searchresult/searchresult.component.html b/angular/src/app/landing/searchresult/searchresult.component.html index c47f12331..4b4d5dcf4 100644 --- a/angular/src/app/landing/searchresult/searchresult.component.html +++ b/angular/src/app/landing/searchresult/searchresult.component.html @@ -5,8 +5,17 @@
- - +
@@ -16,7 +25,15 @@
- +
\ No newline at end of file diff --git a/angular/src/app/landing/searchresult/searchresult.component.ts b/angular/src/app/landing/searchresult/searchresult.component.ts index 8bf854fcf..08023c0c2 100644 --- a/angular/src/app/landing/searchresult/searchresult.component.ts +++ b/angular/src/app/landing/searchresult/searchresult.component.ts @@ -28,7 +28,7 @@ export class SearchresultComponent implements OnInit { searchTaxonomyKey: string; page: number = 1; filterToggler: string = 'expanded'; - filterString: string = ""; + filterObjs: any[] = []; mouse: any = {x:0, y:0}; mouseDragging: boolean = false; prevMouseX: number = 0; @@ -138,11 +138,11 @@ export class SearchresultComponent implements OnInit { } /** - * Update the filter string - * @param filterString + * Update the filter object + * @param filterObjs */ - updateFilterString(filterString: string) { - this.filterString = filterString; + updateFilterObjs(filterObjs: any[]) { + this.filterObjs = filterObjs; } /** diff --git a/angular/src/app/landing/taxonomy/taxonomy.component.html b/angular/src/app/landing/taxonomy/taxonomy.component.html index 7bad9e9a7..3d44f8a7b 100644 --- a/angular/src/app/landing/taxonomy/taxonomy.component.html +++ b/angular/src/app/landing/taxonomy/taxonomy.component.html @@ -14,8 +14,8 @@
+ (onNodeUnselect)="createFilterObj()" + (onNodeSelect)="createFilterObj()">
{{node.label.split("---")[0]}}  diff --git a/angular/src/app/landing/taxonomy/taxonomy.component.ts b/angular/src/app/landing/taxonomy/taxonomy.component.ts index 6c8f836fb..d702c5b8d 100644 --- a/angular/src/app/landing/taxonomy/taxonomy.component.ts +++ b/angular/src/app/landing/taxonomy/taxonomy.component.ts @@ -47,7 +47,7 @@ export class TaxonomyComponent implements OnInit { @Input() isCollection: boolean = false; @Input() collectionNodeExpanded: boolean = false; @Input() clearAllCheckbox: boolean = false; - @Output() filterString: EventEmitter = new EventEmitter(); + @Output() filterObj: EventEmitter = new EventEmitter(); constructor() { @@ -92,12 +92,12 @@ export class TaxonomyComponent implements OnInit { if(this.collectionThemesTree && this.collectionThemesTree.length > 0) this.preselectNodes(this.collectionThemesTree[0].children); - this.filterResults(); + this.createFilterObj(); } uncheckAll() { this.collectionSelectedThemesNode = []; - this.filterResults(); + this.createFilterObj(); } preselectNodes(allNodes: TreeNode[]): void { @@ -140,41 +140,39 @@ export class TaxonomyComponent implements OnInit { /** * Form the filter string and refresh the result page */ - filterResults() { + createFilterObj() { this.allChecked = this.isAllChecked; - let lFilterString: string = ""; + let lFilterObj: any = { + value: [] + }; + let themeSelected: boolean = false; // let themeType = ''; + if(this.isCollection) { + lFilterObj.type = "topic.tag"; + }else{ + lFilterObj.type = this.collection; + } // Collection Research topics - if (this.collectionSelectedThemesNode.length > 0) { - for (let theme of this.collectionSelectedThemesNode) { - if (theme != 'undefined' && typeof theme.data !== 'undefined' && theme.data[0] !== 'undefined') { - themeSelected = true; - for(let i = 0; i < theme.data.length; i++ ){ - if(this.isCollection) { - // themeType += theme.data[i] + ','; - lFilterString += this.collection + "----" + theme.data[i].trim() + ","; - }else{ - lFilterString += theme.data[i].trim().replace(/\s/g, "") + ","; - } + if (this.collectionSelectedThemesNode.length > 0) { + for (let theme of this.collectionSelectedThemesNode) { + if (theme != 'undefined' && typeof theme.data !== 'undefined' && theme.data[0] !== 'undefined') { + themeSelected = true; + for(let i = 0; i < theme.data.length; i++ ){ + if(this.isCollection) { + // themeType += theme.data[i] + ','; + lFilterObj.value.push(this.collection + "----" + theme.data[i].trim()); + }else{ + lFilterObj.value.push(theme.data[i].trim().replace(/\s/g, "")); } } } } + } - lFilterString = this.removeEndingComma(lFilterString); - if(!lFilterString) lFilterString = ""; - else { - if(this.isCollection) { - lFilterString = "topic.tag=" + lFilterString; - }else{ - lFilterString = this.collection + "=" + lFilterString; - } - } - - this.filterString.emit(lFilterString); + this.filterObj.emit(lFilterObj); } /** diff --git a/angular/src/app/shared/collection-service/collection.service.ts b/angular/src/app/shared/collection-service/collection.service.ts index 32155dbe7..3883c1512 100644 --- a/angular/src/app/shared/collection-service/collection.service.ts +++ b/angular/src/app/shared/collection-service/collection.service.ts @@ -13,7 +13,7 @@ export class CollectionService { // list of collections for landing page display (topics) collectionForDisplay: string[] = []; - allCollections: any = {}; + allCollections: any = null; colorSchemes: any = {}; colorSchemeSub = new BehaviorSubject([] as ColorScheme[]); @@ -66,9 +66,12 @@ export class CollectionService { * @returns collection object list that contains nist and collection data */ loadAllCollections() { - for(let col of this.collectionOrder) { - this.allCollections[col] = this.loadCollection(col); - this.colorSchemes[col] = this.allCollections[col].color; + if(!this.allCollections) { + this.allCollections = {}; + for(let col of this.collectionOrder) { + this.allCollections[col] = this.loadCollection(col); + this.colorSchemes[col] = this.allCollections[col].color; + } } return this.allCollections;