Merge branch '7-display-company-logo-in-companies-page' into 'master'
Resolve "Display company logo in companies page" Closes #7 See merge request usi-si-teaching/msde/2022-2023/visual-analytics-atelier/group-projects/group-1!7
This commit is contained in:
commit
5bf9ac01e4
4 changed files with 37 additions and 15 deletions
1
company_generic.svg
Normal file
1
company_generic.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48"><path d="M80 976V495l280-119v80l200-81v121h320v480H80Zm60-60h680V556.199H500V464l-200 80v-79l-160 71v380Zm310-100h60V656h-60v160Zm-160 0h60V656h-60v160Zm320 0h60V656h-60v160Zm270-320H700l40-320h100l40 320ZM140 916h680-680Z"/></svg>
|
After Width: | Height: | Size: 317 B |
|
@ -13,7 +13,11 @@ export interface Company {
|
||||||
tags: string[];
|
tags: string[];
|
||||||
ticker: string;
|
ticker: string;
|
||||||
website: string;
|
website: string;
|
||||||
|
logoSrc: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getCompanies = (): Promise<Company[]> =>
|
export const getCompanies = (): Promise<Company[]> =>
|
||||||
fetch(BACKEND_URL + '/companies').then(r => r.json())
|
fetch(BACKEND_URL + '/companies').then(r => r.json()).then(list => list.map((e: Company) => ({
|
||||||
|
...e,
|
||||||
|
logoSrc: `${BACKEND_URL}/companies/logos/${e.ticker}`
|
||||||
|
})));
|
|
@ -9,10 +9,16 @@
|
||||||
<template v-else v-for="company in companies" :key="company.ticker">
|
<template v-else v-for="company in companies" :key="company.ticker">
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<v-card class="ma-1 fill-height">
|
<v-card class="ma-1 fill-height">
|
||||||
<v-card-item>
|
|
||||||
<v-card-title>{{ company['short name'] }}</v-card-title>
|
<div class="d-flex stretch align-center">
|
||||||
<v-card-subtitle>{{ company['company name'] }}</v-card-subtitle>
|
<div class="flex-0 pa-3">
|
||||||
</v-card-item>
|
<img style="max-height: 36px; min-height: 24px;" :src="company.logoSrc"/>
|
||||||
|
</div>
|
||||||
|
<v-card-item style="flex: 1 !important">
|
||||||
|
<v-card-title>{{ company['short name'] }}</v-card-title>
|
||||||
|
<v-card-subtitle>{{ company['company name'] }}</v-card-subtitle>
|
||||||
|
</v-card-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<p class="text--primary">
|
<p class="text--primary">
|
||||||
|
@ -21,9 +27,9 @@
|
||||||
<div class="pt-2 pb-2" v-for="m in metrics" :key="m.title">
|
<div class="pt-2 pb-2" v-for="m in metrics" :key="m.title">
|
||||||
<div class="d-inline-flex justify-space-between" style="width: 100%">
|
<div class="d-inline-flex justify-space-between" style="width: 100%">
|
||||||
<strong>{{ m.title }}</strong>
|
<strong>{{ m.title }}</strong>
|
||||||
<span class="text-right">{{ m.value }}{{ m.symbol ?? '' }}</span>
|
<span class="text-right">{{ m.value(company) }}{{ m.symbol ?? '' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<v-progress-linear :color="m.color" v-model="m.percentage"></v-progress-linear>
|
<v-progress-linear :color="m.color" :model-value="m.percentage(company)"></v-progress-linear>
|
||||||
</div>
|
</div>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
|
@ -59,7 +65,7 @@ interface Metric {
|
||||||
color: string,
|
color: string,
|
||||||
minValue: number,
|
minValue: number,
|
||||||
maxValue: number,
|
maxValue: number,
|
||||||
value: number // in [0, 100],
|
value: (c: Company) => number // in [0, 100],
|
||||||
symbol?: string
|
symbol?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,21 +75,21 @@ const metricsData = reactive<Metric[]>([
|
||||||
color: 'green',
|
color: 'green',
|
||||||
minValue: 0,
|
minValue: 0,
|
||||||
maxValue: 100,
|
maxValue: 100,
|
||||||
value: 20
|
value: _ => 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Metric 2',
|
title: 'Length of ticker',
|
||||||
color: 'orange',
|
color: 'orange',
|
||||||
minValue: 0,
|
minValue: 0,
|
||||||
maxValue: 100,
|
maxValue: 5,
|
||||||
value: 60,
|
value: c => c.ticker.length,
|
||||||
symbol: '%'
|
symbol: ' chars'
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const metrics = computed<(Metric & { percentage: number })[]>(() => metricsData.map(e => ({
|
const metrics = computed<(Metric & { percentage: (c: Company) => number })[]>(() => metricsData.map(e => ({
|
||||||
...e,
|
...e,
|
||||||
percentage: (e.value - e.minValue) * 100 / (e.maxValue - e.minValue)
|
percentage: (c: Company) => (e.value(c) - e.minValue) * 100 / (e.maxValue - e.minValue)
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,17 @@ def companies() -> object:
|
||||||
return jsonify(get_companies(ROOT_DIR))
|
return jsonify(get_companies(ROOT_DIR))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/companies/logos/<ticker>')
|
||||||
|
def get_company_logo(ticker: str):
|
||||||
|
logo_dir: str = os.path.join(ROOT_DIR, 'scraper', 'logos', 'logos')
|
||||||
|
logo_name: str = str(ticker).upper() + '.png'
|
||||||
|
|
||||||
|
if os.path.exists(os.path.join(logo_dir, logo_name)):
|
||||||
|
return send_from_directory(logo_dir, logo_name)
|
||||||
|
|
||||||
|
return send_from_directory(ROOT_DIR, 'company_generic.svg')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
build_frontend()
|
build_frontend()
|
||||||
app.run()
|
app.run()
|
||||||
|
|
Reference in a new issue