diff --git a/_services/osdf/projects.html b/_services/osdf/projects.html index 8157de8ce..f1f667400 100644 --- a/_services/osdf/projects.html +++ b/_services/osdf/projects.html @@ -156,6 +156,63 @@

By Project

+ +
diff --git a/assets/js/components/ProjectDisplay.mjs b/assets/js/components/ProjectDisplay.mjs index bef51f64a..5f780fb81 100644 --- a/assets/js/components/ProjectDisplay.mjs +++ b/assets/js/components/ProjectDisplay.mjs @@ -1,3 +1,4 @@ +import {formatBytes} from "../util.js"; import {PieChart} from "./pie-chart.js"; import {getProjectOverview} from "../adstash.mjs"; import Count from "./Count.mjs"; @@ -83,4 +84,34 @@ class ProjectDisplay{ } } -export default ProjectDisplay; +class OSDFProjectDisplay extends ProjectDisplay { + async update({Name, PIName, FieldOfScience, Organization, Description}) { + this.updateTextValue("project-Name", Name) + this.updateTextValue("project-PIName", PIName) + this.updateTextValue("project-FieldOfScience", FieldOfScience) + this.updateTextValue("project-Organization", Organization) + this.updateTextValue("project-Description", Description) + this.setUrl(Name) + this.clearGraphSlots() + this.parentNode.addEventListener("shown.bs.modal", () => { + this.updateGraphs(Name) + }, {once : true}) + this.display_modal.show() + } + + async updateGraphs(Name){ + const data = await this.getData(Name) + + const objects = Math.round(Object.values(data).reduce((p, v) => p + v.osdfFileTransferCount, 0)); + const bytes = Math.round(Object.values(data).reduce((p, v) => p + v.osdfByteTransferCount, 0)); + Count("project-osdf-objects", objects, 100) + Count("project-osdf-bytes", formatBytes(bytes), 100) + } + + async updateInstitutionPieChart(_) { + throw new Error("updateInstitutionPieChart not implemented for OSDFProjectDisplay") + } +} + +export { OSDFProjectDisplay }; +export default ProjectDisplay; \ No newline at end of file diff --git a/assets/js/osdf-project-page-v6.js b/assets/js/osdf-project-page-v6.js index beb2d7b5c..d0e665fe3 100644 --- a/assets/js/osdf-project-page-v6.js +++ b/assets/js/osdf-project-page-v6.js @@ -13,6 +13,7 @@ import { localeIntToInt, byteStringToBytes } from "./util.js"; import Color from "https://colorjs.io/dist/color.js"; +import {OSDFProjectDisplay} from "./components/ProjectDisplay.mjs"; import {PieChart} from "./components/pie-chart.js"; import Search from "./Search.mjs"; @@ -39,13 +40,14 @@ class ProjectCount { } class Table { - constructor(wrapper, data_function){ + constructor(wrapper, data_function, updateProjectDisplay){ let table = this; this.grid = undefined this.data_function = data_function this.wrapper = wrapper + this.updateProjectDisplay = updateProjectDisplay this.columns = [ { id: 'projectName', @@ -122,6 +124,7 @@ class Table { } } }).render(table.wrapper); + this.grid.on('rowClick', this.row_click); } update = async () => { let table = this @@ -129,6 +132,12 @@ class Table { data: Object.values(await table.data_function()).sort((a, b) => b.osdfFileTransferCount - a.osdfFileTransferCount) }).forceRender(); } + row_click = async (PointerEvent, e) => { + let data = await this.data_function(); + let row_name = e["cells"][0].data + let project = data[row_name] + this.updateProjectDisplay(project) + } } class DataManager { @@ -169,16 +178,37 @@ class DataManager { } } - _getData = async () => { + _fetch = async (url, options = {}) => { + try { + let response = await fetch(url, options) + + if(!response.ok){ + throw new Error(response.statusText) + } + + return response.json() + + } catch(error) { + this.error = "Error fetching usage data, learn more on the OSG status page: status.osg-htc.org" + } + } + _getData = async () => { + let topologyData = await this._fetch("https://topology.opensciencegrid.org/miscproject/json") let usageJson; + try { usageJson = await getProjects() } catch(e) { this.error = "Error fetching usage data, learn more on the status page: status.osg-htc.org" } - this.data = usageJson + this.data = Object.entries(topologyData).reduce((p, [k,v]) => { + if(k in usageJson){ + p[k] = {...v, ...usageJson[k]} + } + return p + }, {}) return this.data } @@ -232,8 +262,11 @@ class ProjectPage{ this.mode = undefined this.dataManager = new DataManager() + let projectDisplayNode = document.getElementById("project-display") + this.projectDisplay = new OSDFProjectDisplay(projectDisplayNode) + this.wrapper = document.getElementById("wrapper") - this.table = new Table(this.wrapper, this.dataManager.getFilteredData) + this.table = new Table(this.wrapper, this.dataManager.getFilteredData, this.projectDisplay.update.bind(this.projectDisplay)) this.dataManager.consumerToggles.push(this.table.update) this.search = new Search(Object.values(await this.dataManager.getData()), this.dataManager.toggleConsumers) @@ -261,12 +294,18 @@ class ProjectPage{ this.filePieChart = new PieChart( "project-file-summary", this.dataManager.reduceByKey.bind(this.dataManager, "projectName", "osdfFileTransferCount"), - "# of Objects Transferred by Project" + "# of Objects Transferred by Project", + ({label, value}) => { + this.table.updateProjectDisplay(this.dataManager.data[label]) + } ) this.bytePieChart = new PieChart( "project-byte-summary", this.dataManager.reduceByKey.bind(this.dataManager, "projectName", "osdfByteTransferCount"), - "# of Bytes Transferred by Project" + "# of Bytes Transferred by Project", + ({label, value}) => { + this.table.updateProjectDisplay(this.dataManager.data[label]) + } ) this.dataManager.consumerToggles.push(this.fosFilePieChart.update)