From b5b831ff7662dcf294b82cd782e124ccc6f69148 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 2 Oct 2023 12:30:17 -0400 Subject: [PATCH 1/6] Add additional fields to list view table Add all currently-available data fields in the `articles`, `patents`, and `other_metrics` keys to the List View table. Closes #121 --- .../src/components/AddRemoveColumnDialog.jsx | 2 +- web/gui-v2/src/components/ListViewTable.jsx | 62 ++++- web/gui-v2/src/static_data/table_columns.js | 226 ++++++++++++++++-- 3 files changed, 262 insertions(+), 28 deletions(-) diff --git a/web/gui-v2/src/components/AddRemoveColumnDialog.jsx b/web/gui-v2/src/components/AddRemoveColumnDialog.jsx index 7255f97e..e5dea698 100644 --- a/web/gui-v2/src/components/AddRemoveColumnDialog.jsx +++ b/web/gui-v2/src/components/AddRemoveColumnDialog.jsx @@ -19,7 +19,7 @@ const styles = { columnDialogContents: css` font-family: GTZirkonLight; padding: 0 0.5rem 0.5rem; - width: 320px; + width: 400px; `, columnDialogTitle: css` font-family: GTZirkonRegular; diff --git a/web/gui-v2/src/components/ListViewTable.jsx b/web/gui-v2/src/components/ListViewTable.jsx index 38abc421..04056107 100644 --- a/web/gui-v2/src/components/ListViewTable.jsx +++ b/web/gui-v2/src/components/ListViewTable.jsx @@ -130,8 +130,38 @@ const DEFAULT_FILTER_VALUES = { country: [], continent: [], stage: [], + + all_pubs: [0, 100], + citations: [0, 100], ai_pubs: [0, 100], + ai_pubs_top_conf: [0, 100], + cv_pubs: [0, 100], + nlp_pubs: [0, 100], + ro_pubs: [0, 100], + ai_patents: [0, 100], + agri_patents: [0, 100], + finance_patents: [0, 100], + business_patents: [0, 100], + comp_in_gov_patents: [0, 100], + doc_mgt_patents: [0, 100], + edu_patents: [0, 100], + energy_mgt_patents: [0, 100], + entertain_patents: [0, 100], + industry_patents: [0, 100], + life_patents: [0, 100], + mil_patents: [0, 100], + nano_patents: [0, 100], + network_patents: [0, 100], + personal_comp_patents: [0, 100], + phys_sci_patents: [0, 100], + security_patents: [0, 100], + semiconductor_patents: [0, 100], + telecom_patents: [0, 100], + transport_patents: [0, 100], + + ai_jobs: [0, 100], + tt1_jobs: [0, 100], }; const initialVal = (key) => { return DEFAULT_FILTER_VALUES[key]?.join(',') ?? ''; @@ -242,10 +272,38 @@ const ListViewTable = ({ continent: useQueryParamString('continent', initialVal('continent')), stage: useQueryParamString('stage', initialVal('stage')), // ... + + all_pubs: useQueryParamString('all_pubs', initialVal('all_pubs')), + citations: useQueryParamString('citations', initialVal('citations')), ai_pubs: useQueryParamString('ai_pubs', initialVal('ai_pubs')), + ai_pubs_top_conf: useQueryParamString('ai_pubs_top_conf', initialVal('ai_pubs_top_conf')), + cv_pubs: useQueryParamString('cv_pubs', initialVal('cv_pubs')), + nlp_pubs: useQueryParamString('nlp_pubs', initialVal('nlp_pubs')), + ro_pubs: useQueryParamString('ro_pubs', initialVal('ro_pubs')), + ai_patents: useQueryParamString('ai_patents', initialVal('ai_patents')), - // ... - // market_list: useQueryParamString('market_list', ''), + agri_patents: useQueryParamString('agri_patents', initialVal('agri_patents')), + finance_patents: useQueryParamString('finance_patents', initialVal('finance_patents')), + business_patents: useQueryParamString('business_patents', initialVal('business_patents')), + comp_in_gov_patents: useQueryParamString('comp_in_gov_patents', initialVal('comp_in_gov_patents')), + doc_mgt_patents: useQueryParamString('doc_mgt_patents', initialVal('doc_mgt_patents')), + edu_patents: useQueryParamString('edu_patents', initialVal('edu_patents')), + energy_mgt_patents: useQueryParamString('energy_mgt_patents', initialVal('energy_mgt_patents')), + entertain_patents: useQueryParamString('entertain_patents', initialVal('entertain_patents')), + industry_patents: useQueryParamString('industry_patents', initialVal('industry_patents')), + life_patents: useQueryParamString('life_patents', initialVal('life_patents')), + mil_patents: useQueryParamString('mil_patents', initialVal('mil_patents')), + nano_patents: useQueryParamString('nano_patents', initialVal('nano_patents')), + network_patents: useQueryParamString('network_patents', initialVal('network_patents')), + personal_comp_patents: useQueryParamString('personal_comp_patents', initialVal('personal_comp_patents')), + phys_sci_patents: useQueryParamString('phys_sci_patents', initialVal('phys_sci_patents')), + security_patents: useQueryParamString('security_patents', initialVal('security_patents')), + semiconductor_patents: useQueryParamString('semiconductor_patents', initialVal('semiconductor_patents')), + telecom_patents: useQueryParamString('telecom_patents', initialVal('telecom_patents')), + transport_patents: useQueryParamString('transport_patents', initialVal('transport_patents')), + + ai_jobs: useQueryParamString('ai_jobs', initialVal('ai_jobs')), + tt1_jobs: useQueryParamString('tt1_jobs', initialVal('tt1_jobs')), }, (key, val) => { if ( DROPDOWN_COLUMNS.includes(key) ) { diff --git a/web/gui-v2/src/static_data/table_columns.js b/web/gui-v2/src/static_data/table_columns.js index c18954fe..5cd658df 100644 --- a/web/gui-v2/src/static_data/table_columns.js +++ b/web/gui-v2/src/static_data/table_columns.js @@ -20,6 +20,36 @@ const styles = { `, }; +/** Default values for slider columns */ +const SLIDER_PRESETS = { + css: styles.slider, + initialCol: false, + sortable: true, + type: 'slider', +}; + +/** + * Helper function to define the `extract` and `format` functions in a consistent + * way across all columns. + * + * @param {string} dataKey + * @param {string} dataSubkey + * @returns {{ + * dataKey: string, + * dataSubkey: string, + * extract: (val: any, row: object) => any, + * format: (val: any, row: object) => ReactNode, + * }} + */ +const generateDataFns = (dataKey, dataSubkey) => { + return { + dataKey, + dataSubkey, + extract: (_val, row) => row[dataKey][dataSubkey].total, + format: (_val, row) => , + } +}; + export default [ { title: "Company", @@ -33,38 +63,184 @@ export default [ { title: "Country", key: "country", initialCol: true, type: 'dropdown' }, { title: "Region", key: "continent", initialCol: true, type: 'dropdown' }, { title: "Stage", key: "stage", initialCol: true, type: 'dropdown' }, + + { + title: "All publications", + key: "all_pubs", + ...generateDataFns("articles", "all_publications"), + ...SLIDER_PRESETS, + }, + { + title: "Citation counts", + key: "citations", + ...generateDataFns("articles", "citation_counts"), + ...SLIDER_PRESETS, + }, { title: "AI publications", key: "ai_pubs", - dataKey: "articles", - dataSubkey: "ai_publications", - css: styles.sliderColumn, + ...generateDataFns("articles", "ai_publications"), + ...SLIDER_PRESETS, initialCol: true, - extract: (_val, row) => row.articles.ai_publications.total, - format: (_val, row) => , - sortable: true, - type: 'slider', + }, + { + title: "AI publications in top conferences", + key: "ai_pubs_top_conf", + ...generateDataFns("articles", "ai_pubs_top_conf"), + ...SLIDER_PRESETS, }, { title: "AI patents", key: "ai_patents", - dataKey: "patents", - dataSubkey: "ai_patents", - css: styles.sliderColumn, + ...generateDataFns("patents", "ai_patents"), + ...SLIDER_PRESETS, initialCol: true, - extract: (_val, row) => row.patents.ai_patents.total, - format: (_val, row) => , - sortable: true, - type: 'slider', - }, - // { title: "AI publication intensity", key: "ai_pubs_int", initialCol: false, type: 'slider' }, - // { title: "NLP publications", key: "nlp_pubs", initialCol: true }, - // { title: "NLP patents", key: "nlp_patents", initialCol: true }, - // { title: "CV publications", key: "cv_pubs", initialCol: false }, - // { title: "CV patents", key: "cv_patents", initialCol: false }, - // { title: "Robotics publications", key: "ro_pubs", initialCol: false }, - // { title: "Robotics patents", key: "ro_patents", initialCol: false }, - // { title: "tt1 jobs (??)", key: "tt1_jobs", initialCol: false }, - // { title: "AI jobs", key: "ai_jobs", initialCol: false }, - // { title: "Stock ticker", key: "market_list", type: "stock" }, + }, + { + title: "CV publications", + key: "cv_pubs", + ...generateDataFns("articles", "cv_pubs"), + ...SLIDER_PRESETS, + }, + { + title: "NLP publications", + key: "nlp_pubs", + ...generateDataFns("articles", "nlp_pubs"), + ...SLIDER_PRESETS, + }, + { + title: "Robotics publications", + key: "ro_pubs", + ...generateDataFns("articles", "robotics_pubs"), + ...SLIDER_PRESETS, + }, + + { + title: "Agricultural patents", + key: "agri_patents", + ...generateDataFns("patents", "Agricultural"), + ...SLIDER_PRESETS, + }, + { + title: "Banking and finance patents", + key: "finance_patents", + ...generateDataFns("patents", "Banking_and_Finance"), + ...SLIDER_PRESETS, + }, + { + title: "Business patents", + key: "business_patents", + ...generateDataFns("patents", "Business"), + ...SLIDER_PRESETS, + }, + { + title: "Computing in government patents", + key: "comp_in_gov_patents", + ...generateDataFns("patents", "Computing_in_Government"), + ...SLIDER_PRESETS, + }, + { + title: "Document management and publishing patents", + key: "doc_mgt_patents", + ...generateDataFns("patents", "Document_Mgt_and_Publishing"), + ...SLIDER_PRESETS, + }, + { + title: "Education patents", + key: "edu_patents", + ...generateDataFns("patents", "Education"), + ...SLIDER_PRESETS, + }, + { + title: "Energy patents", + key: "energy_mgt_patents", + ...generateDataFns("patents", "Energy_Management"), + ...SLIDER_PRESETS, + }, + { + title: "Entertainment patents", + key: "entertain_patents", + ...generateDataFns("patents", "Entertainment"), + ...SLIDER_PRESETS, + }, + { + title: "Industrial and manufacturing patents", + key: "industry_patents", + ...generateDataFns("patents", "Industrial_and_Manufacturing"), + ...SLIDER_PRESETS, + }, + { + title: "Life sciences patents", + key: "life_patents", + ...generateDataFns("patents", "Life_Sciences"), + ...SLIDER_PRESETS, + }, + { + title: "Military patents", + key: "mil_patents", + ...generateDataFns("patents", "Military"), + ...SLIDER_PRESETS, + }, + { + title: "Nanotechnology patents", + key: "nano_patents", + ...generateDataFns("patents", "Nanotechnology"), + ...SLIDER_PRESETS, + }, + { + title: "Networks patents", + key: "network_patents", + ...generateDataFns("patents", "Networks__eg_social_IOT_etc"), + ...SLIDER_PRESETS, + }, + { + title: "Personal devices and computing patents", + key: "personal_comp_patents", + ...generateDataFns("patents", "Personal_Devices_and_Computing"), + ...SLIDER_PRESETS, + }, + { + title: "Physical sciences and engineering patents", + key: "phys_sci_patents", + ...generateDataFns("patents", "Physical_Sciences_and_Engineering"), + ...SLIDER_PRESETS, + }, + { + title: "Security patents", + key: "security_patents", + ...generateDataFns("patents", "Security__eg_cybersecurity"), + ...SLIDER_PRESETS, + }, + { + title: "Semiconductor patents", + key: "semiconductor_patents", + ...generateDataFns("patents", "Semiconductors"), + ...SLIDER_PRESETS, + }, + { + title: "Telecommunications patents", + key: "telecom_patents", + ...generateDataFns("patents", "Telecommunications"), + ...SLIDER_PRESETS, + }, + { + title: "Transportation patents", + key: "transport_patents", + ...generateDataFns("patents", "Transportation"), + ...SLIDER_PRESETS, + }, + + { + title: "AI jobs", + key: "ai_jobs", + ...generateDataFns("other_metrics", "ai_jobs"), + ...SLIDER_PRESETS, + initialCol: true, + }, + { + title: "Tech Tier 1 jobs", + key: "tt1_jobs", + ...generateDataFns("other_metrics", "tt1_jobs"), + ...SLIDER_PRESETS, + }, ]; From f34ad1df4c2b4a478f5803cdeb966e611a0322e2 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 5 Oct 2023 11:49:03 -0400 Subject: [PATCH 2/6] Handle null values and reduce boilerplate code Treat null values as zero for sorting purposes; display as "n/a". Reduce boilerplate code for default values. --- web/gui-v2/src/components/CellStat.jsx | 6 ++-- web/gui-v2/src/components/ListViewTable.jsx | 33 ++------------------- web/gui-v2/src/static_data/table_columns.js | 5 +++- 3 files changed, 10 insertions(+), 34 deletions(-) diff --git a/web/gui-v2/src/components/CellStat.jsx b/web/gui-v2/src/components/CellStat.jsx index 7dd08c50..60e73072 100644 --- a/web/gui-v2/src/components/CellStat.jsx +++ b/web/gui-v2/src/components/CellStat.jsx @@ -23,9 +23,11 @@ const styles = { const CellStat = ({data, colKey}) => { return (
-
{commas(data.total)}
+
+ { data?.total === null ? 'n/a' : commas(data.total) } +
- { data?.total === 0 ? '---' : <>#{data.rank} } + { (data?.total === 0 || data?.total === null) ? '---' : <>#{data.rank} }
); diff --git a/web/gui-v2/src/components/ListViewTable.jsx b/web/gui-v2/src/components/ListViewTable.jsx index 04056107..7b61efa5 100644 --- a/web/gui-v2/src/components/ListViewTable.jsx +++ b/web/gui-v2/src/components/ListViewTable.jsx @@ -111,6 +111,7 @@ const styles = { const DATAKEYS_WITH_SUBKEYS = [ "articles", "patents", + "other_metrics", ]; const DEFAULT_COLUMNS = columnDefinitions @@ -131,37 +132,7 @@ const DEFAULT_FILTER_VALUES = { continent: [], stage: [], - all_pubs: [0, 100], - citations: [0, 100], - ai_pubs: [0, 100], - ai_pubs_top_conf: [0, 100], - cv_pubs: [0, 100], - nlp_pubs: [0, 100], - ro_pubs: [0, 100], - - ai_patents: [0, 100], - agri_patents: [0, 100], - finance_patents: [0, 100], - business_patents: [0, 100], - comp_in_gov_patents: [0, 100], - doc_mgt_patents: [0, 100], - edu_patents: [0, 100], - energy_mgt_patents: [0, 100], - entertain_patents: [0, 100], - industry_patents: [0, 100], - life_patents: [0, 100], - mil_patents: [0, 100], - nano_patents: [0, 100], - network_patents: [0, 100], - personal_comp_patents: [0, 100], - phys_sci_patents: [0, 100], - security_patents: [0, 100], - semiconductor_patents: [0, 100], - telecom_patents: [0, 100], - transport_patents: [0, 100], - - ai_jobs: [0, 100], - tt1_jobs: [0, 100], + ...SLIDER_COLUMNS.reduce((obj, e) => { obj[e] = [0, 100]; return obj; }, {}), }; const initialVal = (key) => { return DEFAULT_FILTER_VALUES[key]?.join(',') ?? ''; diff --git a/web/gui-v2/src/static_data/table_columns.js b/web/gui-v2/src/static_data/table_columns.js index 5cd658df..0369466d 100644 --- a/web/gui-v2/src/static_data/table_columns.js +++ b/web/gui-v2/src/static_data/table_columns.js @@ -45,7 +45,10 @@ const generateDataFns = (dataKey, dataSubkey) => { return { dataKey, dataSubkey, - extract: (_val, row) => row[dataKey][dataSubkey].total, + extract: (_val, row) => { + const res = row[dataKey][dataSubkey].total; + return res === null ? 0 : res; + }, format: (_val, row) => , } }; From ff83781c962d244504adc4ab7ea57714a1e4eafc Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 5 Oct 2023 11:53:59 -0400 Subject: [PATCH 3/6] Reduce more boilerplate There's an issue with filter states "bouncing" - tracked in #131 --- web/gui-v2/src/components/ListViewTable.jsx | 64 ++++----------------- 1 file changed, 10 insertions(+), 54 deletions(-) diff --git a/web/gui-v2/src/components/ListViewTable.jsx b/web/gui-v2/src/components/ListViewTable.jsx index 7b61efa5..c28b3471 100644 --- a/web/gui-v2/src/components/ListViewTable.jsx +++ b/web/gui-v2/src/components/ListViewTable.jsx @@ -126,12 +126,13 @@ const SLIDER_COLUMNS = columnDefinitions .filter(colDef => colDef.type === "slider") .map(colDef => colDef.key); -const DEFAULT_FILTER_VALUES = { - name: [], - country: [], - continent: [], - stage: [], +const ALL_COLUMNS = [ + ...DROPDOWN_COLUMNS, + ...SLIDER_COLUMNS, +]; +const DEFAULT_FILTER_VALUES = { + ...DROPDOWN_COLUMNS.reduce((obj, e) => { obj[e] = []; return obj; }, {}), ...SLIDER_COLUMNS.reduce((obj, e) => { obj[e] = [0, 100]; return obj; }, {}), }; const initialVal = (key) => { @@ -150,7 +151,6 @@ const AGGREGATE_SUM_COLUMNS = [ 'ai_patents', ]; - // Determine whether a given row matches the filters and/or selected group const filterRow = (row, filters, selectedGroupMembers) => { const filterKeys = Object.keys(filters); @@ -195,10 +195,6 @@ const filterRow = (row, filters, selectedGroupMembers) => { if ( rowVal < min || ( max < 100 && max < rowVal) ) { return false; } - } else if ( colDef.type === "stock" ) { - // TODO: Figure out how we're filtering the `market_list` column - // -- Actually - are we even wanting this column, or did I just make - // it as a placeholder? } else { console.error(`Invalid column type for key '${colDef.key}': column.type should be either "dropdown" or "slider" but is instead "${colDef.type}"`); } @@ -237,45 +233,10 @@ const ListViewTable = ({ // Store filters via the URL parameters, making the values (and setters) // accessible via an object. const filters = useMultiState( - { - name: useQueryParamString('name', initialVal('name')), - country: useQueryParamString('country', initialVal('country')), - continent: useQueryParamString('continent', initialVal('continent')), - stage: useQueryParamString('stage', initialVal('stage')), - // ... - - all_pubs: useQueryParamString('all_pubs', initialVal('all_pubs')), - citations: useQueryParamString('citations', initialVal('citations')), - ai_pubs: useQueryParamString('ai_pubs', initialVal('ai_pubs')), - ai_pubs_top_conf: useQueryParamString('ai_pubs_top_conf', initialVal('ai_pubs_top_conf')), - cv_pubs: useQueryParamString('cv_pubs', initialVal('cv_pubs')), - nlp_pubs: useQueryParamString('nlp_pubs', initialVal('nlp_pubs')), - ro_pubs: useQueryParamString('ro_pubs', initialVal('ro_pubs')), - - ai_patents: useQueryParamString('ai_patents', initialVal('ai_patents')), - agri_patents: useQueryParamString('agri_patents', initialVal('agri_patents')), - finance_patents: useQueryParamString('finance_patents', initialVal('finance_patents')), - business_patents: useQueryParamString('business_patents', initialVal('business_patents')), - comp_in_gov_patents: useQueryParamString('comp_in_gov_patents', initialVal('comp_in_gov_patents')), - doc_mgt_patents: useQueryParamString('doc_mgt_patents', initialVal('doc_mgt_patents')), - edu_patents: useQueryParamString('edu_patents', initialVal('edu_patents')), - energy_mgt_patents: useQueryParamString('energy_mgt_patents', initialVal('energy_mgt_patents')), - entertain_patents: useQueryParamString('entertain_patents', initialVal('entertain_patents')), - industry_patents: useQueryParamString('industry_patents', initialVal('industry_patents')), - life_patents: useQueryParamString('life_patents', initialVal('life_patents')), - mil_patents: useQueryParamString('mil_patents', initialVal('mil_patents')), - nano_patents: useQueryParamString('nano_patents', initialVal('nano_patents')), - network_patents: useQueryParamString('network_patents', initialVal('network_patents')), - personal_comp_patents: useQueryParamString('personal_comp_patents', initialVal('personal_comp_patents')), - phys_sci_patents: useQueryParamString('phys_sci_patents', initialVal('phys_sci_patents')), - security_patents: useQueryParamString('security_patents', initialVal('security_patents')), - semiconductor_patents: useQueryParamString('semiconductor_patents', initialVal('semiconductor_patents')), - telecom_patents: useQueryParamString('telecom_patents', initialVal('telecom_patents')), - transport_patents: useQueryParamString('transport_patents', initialVal('transport_patents')), - - ai_jobs: useQueryParamString('ai_jobs', initialVal('ai_jobs')), - tt1_jobs: useQueryParamString('tt1_jobs', initialVal('tt1_jobs')), - }, + ALL_COLUMNS.reduce((obj, e) => { + obj[e] = useQueryParamString(e, initialVal(e)); + return obj; + }, {}), (key, val) => { if ( DROPDOWN_COLUMNS.includes(key) ) { let result = val.split(',').filter(e => e !== ""); @@ -451,11 +412,6 @@ const ListViewTable = ({ /> ); break; - case 'stock': - display_name = ( - colDef.title - ); - break; default: display_name = colDef.title; } From 11a906a7aa74cff8c4b5048da666eafcf3eb1737 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 5 Oct 2023 14:47:11 -0400 Subject: [PATCH 4/6] Fix 'bouncing' states Fix the "party parrot filters" issue with filters on page refresh Closes #131 --- web/gui-v2/src/components/HeaderSlider.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/gui-v2/src/components/HeaderSlider.jsx b/web/gui-v2/src/components/HeaderSlider.jsx index ac159289..8583eebb 100644 --- a/web/gui-v2/src/components/HeaderSlider.jsx +++ b/web/gui-v2/src/components/HeaderSlider.jsx @@ -37,9 +37,10 @@ const HeaderSlider = ({ ); // Debounce handler for propagating internal changes to the outside + const externalHandler = (newVal) => onChange(newVal); const handleExternalChange = useMemo(() => { - return debounce(onChange, 300); - }, [onChange]); + return debounce(externalHandler, 300); + }, []); // Trigger external state change useEffect( From c94e929adcebb47532d6345802896084fca3695a Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 5 Oct 2023 16:06:30 -0400 Subject: [PATCH 5/6] Simpify column definitions and increase minimum column width Simplify the column definitions for slider columns to reduce necessary boilerplate. Set a minimum width for slider columns (and ensured that it is actually applied) to reduce crowding in some of the smaller columns (like AI/TT1 jobs). --- web/gui-v2/src/static_data/table_columns.js | 110 ++++++++------------ 1 file changed, 41 insertions(+), 69 deletions(-) diff --git a/web/gui-v2/src/static_data/table_columns.js b/web/gui-v2/src/static_data/table_columns.js index 0369466d..a354c609 100644 --- a/web/gui-v2/src/static_data/table_columns.js +++ b/web/gui-v2/src/static_data/table_columns.js @@ -12,6 +12,7 @@ const styles = { } `, sliderColumn: css` + min-width: 100px; width: 120px; .MuiButtonBase-root { @@ -20,29 +21,26 @@ const styles = { `, }; -/** Default values for slider columns */ -const SLIDER_PRESETS = { - css: styles.slider, - initialCol: false, - sortable: true, - type: 'slider', -}; - /** - * Helper function to define the `extract` and `format` functions in a consistent - * way across all columns. + * Helper function to define the `extract` and `format` functions of slider + * fields in a consistent way across all columns. * * @param {string} dataKey * @param {string} dataSubkey * @returns {{ + * css: SerializedStyles, * dataKey: string, * dataSubkey: string, * extract: (val: any, row: object) => any, * format: (val: any, row: object) => ReactNode, + * initialCol: boolean, + * sortable: boolean, + * type: 'dropdown'|'slider', * }} */ -const generateDataFns = (dataKey, dataSubkey) => { +const generateSliderColDef = (dataKey, dataSubkey) => { return { + css: styles.sliderColumn, dataKey, dataSubkey, extract: (_val, row) => { @@ -50,6 +48,9 @@ const generateDataFns = (dataKey, dataSubkey) => { return res === null ? 0 : res; }, format: (_val, row) => , + initialCol: false, + sortable: true, + type: 'slider', } }; @@ -70,180 +71,151 @@ export default [ { title: "All publications", key: "all_pubs", - ...generateDataFns("articles", "all_publications"), - ...SLIDER_PRESETS, + ...generateSliderColDef("articles", "all_publications"), }, { title: "Citation counts", key: "citations", - ...generateDataFns("articles", "citation_counts"), - ...SLIDER_PRESETS, + ...generateSliderColDef("articles", "citation_counts"), }, { title: "AI publications", key: "ai_pubs", - ...generateDataFns("articles", "ai_publications"), - ...SLIDER_PRESETS, + ...generateSliderColDef("articles", "ai_publications"), initialCol: true, }, { title: "AI publications in top conferences", key: "ai_pubs_top_conf", - ...generateDataFns("articles", "ai_pubs_top_conf"), - ...SLIDER_PRESETS, + ...generateSliderColDef("articles", "ai_pubs_top_conf"), }, { title: "AI patents", key: "ai_patents", - ...generateDataFns("patents", "ai_patents"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "ai_patents"), initialCol: true, }, { title: "CV publications", key: "cv_pubs", - ...generateDataFns("articles", "cv_pubs"), - ...SLIDER_PRESETS, + ...generateSliderColDef("articles", "cv_pubs"), }, { title: "NLP publications", key: "nlp_pubs", - ...generateDataFns("articles", "nlp_pubs"), - ...SLIDER_PRESETS, + ...generateSliderColDef("articles", "nlp_pubs"), }, { title: "Robotics publications", key: "ro_pubs", - ...generateDataFns("articles", "robotics_pubs"), - ...SLIDER_PRESETS, + ...generateSliderColDef("articles", "robotics_pubs"), }, { title: "Agricultural patents", key: "agri_patents", - ...generateDataFns("patents", "Agricultural"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Agricultural"), }, { title: "Banking and finance patents", key: "finance_patents", - ...generateDataFns("patents", "Banking_and_Finance"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Banking_and_Finance"), }, { title: "Business patents", key: "business_patents", - ...generateDataFns("patents", "Business"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Business"), }, { title: "Computing in government patents", key: "comp_in_gov_patents", - ...generateDataFns("patents", "Computing_in_Government"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Computing_in_Government"), }, { title: "Document management and publishing patents", key: "doc_mgt_patents", - ...generateDataFns("patents", "Document_Mgt_and_Publishing"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Document_Mgt_and_Publishing"), }, { title: "Education patents", key: "edu_patents", - ...generateDataFns("patents", "Education"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Education"), }, { title: "Energy patents", key: "energy_mgt_patents", - ...generateDataFns("patents", "Energy_Management"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Energy_Management"), }, { title: "Entertainment patents", key: "entertain_patents", - ...generateDataFns("patents", "Entertainment"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Entertainment"), }, { title: "Industrial and manufacturing patents", key: "industry_patents", - ...generateDataFns("patents", "Industrial_and_Manufacturing"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Industrial_and_Manufacturing"), }, { title: "Life sciences patents", key: "life_patents", - ...generateDataFns("patents", "Life_Sciences"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Life_Sciences"), }, { title: "Military patents", key: "mil_patents", - ...generateDataFns("patents", "Military"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Military"), }, { title: "Nanotechnology patents", key: "nano_patents", - ...generateDataFns("patents", "Nanotechnology"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Nanotechnology"), }, { title: "Networks patents", key: "network_patents", - ...generateDataFns("patents", "Networks__eg_social_IOT_etc"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Networks__eg_social_IOT_etc"), }, { title: "Personal devices and computing patents", key: "personal_comp_patents", - ...generateDataFns("patents", "Personal_Devices_and_Computing"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Personal_Devices_and_Computing"), }, { title: "Physical sciences and engineering patents", key: "phys_sci_patents", - ...generateDataFns("patents", "Physical_Sciences_and_Engineering"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Physical_Sciences_and_Engineering"), }, { title: "Security patents", key: "security_patents", - ...generateDataFns("patents", "Security__eg_cybersecurity"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Security__eg_cybersecurity"), }, { title: "Semiconductor patents", key: "semiconductor_patents", - ...generateDataFns("patents", "Semiconductors"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Semiconductors"), }, { title: "Telecommunications patents", key: "telecom_patents", - ...generateDataFns("patents", "Telecommunications"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Telecommunications"), }, { title: "Transportation patents", key: "transport_patents", - ...generateDataFns("patents", "Transportation"), - ...SLIDER_PRESETS, + ...generateSliderColDef("patents", "Transportation"), }, { title: "AI jobs", key: "ai_jobs", - ...generateDataFns("other_metrics", "ai_jobs"), - ...SLIDER_PRESETS, + ...generateSliderColDef("other_metrics", "ai_jobs"), initialCol: true, }, { title: "Tech Tier 1 jobs", key: "tt1_jobs", - ...generateDataFns("other_metrics", "tt1_jobs"), - ...SLIDER_PRESETS, + ...generateSliderColDef("other_metrics", "tt1_jobs"), }, ]; From 135a19767bd63e287279ae801b483d562609deb6 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 12 Oct 2023 22:12:55 -0400 Subject: [PATCH 6/6] Adjusted cell stat padding to accomodate 4-digit ranks Adjusted the layout of `` to ensure that there is always enough space for a 4-digit ranking (plus "#"). --- web/gui-v2/src/components/CellStat.jsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/web/gui-v2/src/components/CellStat.jsx b/web/gui-v2/src/components/CellStat.jsx index 60e73072..6b4b708a 100644 --- a/web/gui-v2/src/components/CellStat.jsx +++ b/web/gui-v2/src/components/CellStat.jsx @@ -6,7 +6,13 @@ import { commas } from '../util'; const styles = { cell: css` display: grid; - grid-template-columns: 60% 40%; + gap: 0.5rem; + /* + * 3.2em was chosen because it was a touch above the size needed to safely + * display a 4-digit company ranking. If we ever get above 10,000 companies + * and things start looking funky, just increase this accordingly. + */ + grid-template-columns: 1fr 3.2em; justify-content: center; & > div { @@ -15,7 +21,6 @@ const styles = { .rank { color: #a0a0a0; - margin-left: 0.5rem; } `, };