Merge branch 'master' of https://gitlab.com/usi-si-teaching/msde/2022-2023/visual-analytics-atelier/group-projects/group-1
This commit is contained in:
commit
4ed823f7bb
6 changed files with 77 additions and 13 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 |
|
@ -9,7 +9,7 @@
|
||||||
"lint": "eslint . --fix --ignore-path .gitignore"
|
"lint": "eslint . --fix --ignore-path .gitignore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "7.0.96",
|
"@mdi/font": "^7.2.96",
|
||||||
"core-js": "^3.29.0",
|
"core-js": "^3.29.0",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "*",
|
||||||
"vue": "^3.2.0",
|
"vue": "^3.2.0",
|
||||||
|
|
|
@ -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,13 +9,28 @@
|
||||||
<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>
|
|
||||||
|
<div class="d-flex stretch align-center">
|
||||||
|
<div class="flex-0 pa-3">
|
||||||
|
<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-title>{{ company['short name'] }}</v-card-title>
|
||||||
<v-card-subtitle>{{ company['company name'] }}</v-card-subtitle>
|
<v-card-subtitle>{{ company['company name'] }}</v-card-subtitle>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
|
<p class="text--primary">
|
||||||
{{ company.description }}
|
{{ company.description }}
|
||||||
|
</p>
|
||||||
|
<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%">
|
||||||
|
<strong>{{ m.title }}</strong>
|
||||||
|
<span class="text-right">{{ m.value(company) }}{{ m.symbol ?? '' }}</span>
|
||||||
|
</div>
|
||||||
|
<v-progress-linear :color="m.color" :model-value="m.percentage(company)"></v-progress-linear>
|
||||||
|
</div>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
<div class="px-4">
|
<div class="px-4">
|
||||||
|
@ -40,11 +55,44 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getCompanies, Company } from '@/api';
|
import { getCompanies, Company } from '@/api';
|
||||||
import { ref, reactive } from 'vue';
|
import { ref, reactive, computed, watch } from 'vue';
|
||||||
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const companies = reactive<Company[]>([]);
|
const companies = reactive<Company[]>([]);
|
||||||
|
|
||||||
|
interface Metric {
|
||||||
|
title: string,
|
||||||
|
color: string,
|
||||||
|
minValue: number,
|
||||||
|
maxValue: number,
|
||||||
|
value: (c: Company) => number // in [0, 100],
|
||||||
|
symbol?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const metricsData = reactive<Metric[]>([
|
||||||
|
{
|
||||||
|
title: 'Metric 1',
|
||||||
|
color: 'green',
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 100,
|
||||||
|
value: _ => 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Length of ticker',
|
||||||
|
color: 'orange',
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 5,
|
||||||
|
value: c => c.ticker.length,
|
||||||
|
symbol: ' chars'
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const metrics = computed<(Metric & { percentage: (c: Company) => number })[]>(() => metricsData.map(e => ({
|
||||||
|
...e,
|
||||||
|
percentage: (c: Company) => (e.value(c) - e.minValue) * 100 / (e.maxValue - e.minValue)
|
||||||
|
})));
|
||||||
|
|
||||||
|
|
||||||
getCompanies().then(cs => {
|
getCompanies().then(cs => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
companies.push(...cs);
|
companies.push(...cs);
|
||||||
|
|
|
@ -192,10 +192,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
|
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
|
||||||
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
|
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
|
||||||
|
|
||||||
"@mdi/font@7.0.96":
|
"@mdi/font@^7.2.96":
|
||||||
version "7.0.96"
|
version "7.2.96"
|
||||||
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-7.0.96.tgz#9853c222623072f5575b4039c8c195ea929b61fc"
|
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-7.2.96.tgz#af800d9fe3b424f85ad45e9baa755bd003ab4986"
|
||||||
integrity sha512-rzlxTfR64hqY8yiBzDjmANfcd8rv+T5C0Yedv/TWk2QyAQYdc66e0kaN1ipmnYU3RukHRTRcBARHzzm+tIhL7w==
|
integrity sha512-e//lmkmpFUMZKhmCY9zdjRe4zNXfbOIJnn6xveHbaV2kSw5aJ5dLXUxcRt1Gxfi7ZYpFLUWlkG2MGSFAiqAu7w==
|
||||||
|
|
||||||
"@nodelib/fs.scandir@2.1.5":
|
"@nodelib/fs.scandir@2.1.5":
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
|
|
|
@ -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