-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolve "Dashboard pagina, design van Roos" Closes #31, #7, #44, #36, #39, #22, #29, #14, #27, #28, #1, #8, #5, and #3 See merge request ictu/devops/algoritmeregister/algoritmeregister!27
- Loading branch information
Showing
15 changed files
with
928 additions
and
313 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
from enum import Enum | ||
|
||
|
||
class Columns(str, Enum): | ||
all = "*" | ||
|
||
algoritme_organization = "algoritme.organization" | ||
algoritme_name = "algoritme.name" | ||
algoritme_department = "algoritme.department" | ||
algoritme_description_short = "algoritme.description_short" | ||
algoritme_type = "algoritme.type" | ||
algoritme_category = "algoritme.category" | ||
algoritme_website = "algoritme.website" | ||
algoritme_status = "algoritme.status" | ||
algoritme_uuid = "algoritme.uuid" | ||
algoritme_toegevoegd_op = "algoritme.toegevoegd_op" | ||
algoritme_slug = "algoritme.slug" | ||
|
||
inzet_goal = "inzet.goal" | ||
inzet_impact = "inzet.impact" | ||
inzet_proportionality = "inzet.proportionality" | ||
inzet_decision_making_process = "inzet.decision_making_process" | ||
inzet_documentation = "inzet.documentation" | ||
inzet_toegevoegd_op = "inzet.toegevoegd_op" | ||
|
||
juridisch_competent_authority = "juridisch.competent_authority" | ||
juridisch_lawful_basis = "juridisch.lawful_basis" | ||
juridisch_iama = "juridisch.iama" | ||
juridisch_iama_description = "juridisch.iama_description" | ||
juridisch_dpia = "juridisch.dpia" | ||
juridisch_dpia_description = "juridisch.dpia_description" | ||
juridisch_objection_procedure = "juridisch.objection_procedure" | ||
juridisch_toegevoegd_op = "juridisch.toegevoegd_op" | ||
|
||
metadata_schema = "metadata.schema" | ||
metadata_uuid = "metadata.uuid" | ||
metadata_url = "metadata.url" | ||
metadata_contact_email = "metadata.contact_email" | ||
metadata_area = "metadata.area" | ||
metadata_lang = "metadata.lang" | ||
metadata_revision_date = "metadata.revision_date" | ||
metadata_toegevoegd_op = "metadata.toegevoegd_op" | ||
|
||
toepassing_description = "toepassing.description" | ||
toepassing_application_url = "toepassing.application_url" | ||
toepassing_publiccode = "toepassing.publiccode" | ||
toepassing_mprd = "toepassing.mprd" | ||
toepassing_source_data = "toepassing.source_data" | ||
toepassing_methods_and_models = "toepassing.methods_and_models" | ||
toepassing_toegevoegd_op = "toepassing.toegevoegd_op" | ||
|
||
toezicht_monitoring = "toezicht.monitoring" | ||
toezicht_human_intervention = "toezicht.human_intervention" | ||
toezicht_risks = "toezicht.risks" | ||
toezicht_performance_standard = "toezicht.performance_standard" | ||
toezicht_toegevoegd_op = "toezicht.toegevoegd_op" | ||
|
||
|
||
# columns=metadata.contact_email | ||
# columns=metadata.toegevoegd_op | ||
|
||
# columns=toepassing.toegevoegd_op | ||
|
||
# columns=toezicht.human_intervention | ||
# columns=toezicht.toegevoegd_op |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
from fastapi import APIRouter, Query | ||
from fastapi import Depends | ||
from app.middleware.middleware import get_db | ||
from sqlalchemy.orm import Session | ||
from sqlalchemy import text | ||
from app.config.resource import Columns | ||
import logging | ||
|
||
router = APIRouter() | ||
logger = logging.getLogger(__name__) | ||
|
||
|
||
@router.get("/columns/") | ||
async def get_columns(db: Session = Depends(get_db)): | ||
stmt = text( | ||
"""SELECT table_name, column_name, is_nullable | ||
FROM information_schema.columns | ||
WHERE table_schema = 'public' | ||
AND column_name != 'algoritme_id' | ||
AND column_name != 'id' | ||
AND table_name != 'alembic_version' | ||
ORDER BY table_name, ordinal_position | ||
""" | ||
) | ||
return db.execute(stmt).all() | ||
|
||
|
||
@router.get("/db-count/") | ||
async def get_total_count(db: Session = Depends(get_db)) -> int: | ||
stmt = text("SELECT count(id) FROM algoritme") | ||
return int(db.execute(stmt).all()[0][0]) | ||
|
||
|
||
@router.get("/db-count/{column}") | ||
async def get_count_per_type(column: Columns, db: Session = Depends(get_db)): | ||
stmt = text( | ||
f""" | ||
SELECT count(1), {column.value} as descriptor | ||
FROM algoritme | ||
LEFT JOIN inzet ON algoritme.id=inzet.algoritme_id | ||
LEFT JOIN juridisch ON algoritme.id=juridisch.algoritme_id | ||
LEFT JOIN metadata ON algoritme.id=metadata.algoritme_id | ||
LEFT JOIN toepassing ON algoritme.id=toepassing.algoritme_id | ||
LEFT JOIN toezicht ON algoritme.id=toezicht.algoritme_id | ||
GROUP BY {column.value} | ||
ORDER BY count(1) desc | ||
LIMIT 10 | ||
""" | ||
) | ||
return db.execute(stmt).all() | ||
|
||
|
||
@router.get("/completeness/") | ||
async def get_count_with_filled_columns( | ||
columns: list[Columns] | None = Query(default=None), db: Session = Depends(get_db) | ||
): | ||
selection_string = ", ".join(columns) | ||
stmt = text( | ||
f"""SELECT {selection_string} | ||
FROM algoritme | ||
LEFT JOIN inzet ON algoritme.id=inzet.algoritme_id | ||
LEFT JOIN juridisch ON algoritme.id=juridisch.algoritme_id | ||
LEFT JOIN metadata ON algoritme.id=metadata.algoritme_id | ||
LEFT JOIN toepassing ON algoritme.id=toepassing.algoritme_id | ||
LEFT JOIN toezicht ON algoritme.id=toezicht.algoritme_id | ||
""" | ||
) | ||
|
||
table = db.execute(stmt).all() | ||
|
||
def is_filled(cell: any) -> bool: | ||
return [""].count(cell) == 0 | ||
|
||
compliantRows = [] | ||
for row in table: | ||
compliantRow = all([is_filled(cell) for cell in row]) | ||
if compliantRow: | ||
compliantRows.append(row) | ||
return len(compliantRows) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
<template> | ||
<div class="block-cards__card"> | ||
<div class="block-info"> | ||
<div class="rows"> | ||
<h3> | ||
{{ title }} | ||
</h3> | ||
<div class="row"> | ||
<div class="loading-text" v-if="loading">{{ loadingText }}...</div> | ||
<table class="table" v-show="!loading"> | ||
<thead> | ||
<tr> | ||
<th class="u-columnwidth-50p">{{ tableHeader }}:</th> | ||
<th class="u-columnwidth-10p"></th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr v-for="agg in aggregates"> | ||
<td>{{ agg.label }}</td> | ||
<td>{{ agg.value }}</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { useI18n } from 'vue-i18n' | ||
import algoritmeService from '@/services/algoritme' | ||
const { t } = useI18n() | ||
const title = computed(() => t('dashboard.completenessTitle')) | ||
const tableHeader = computed(() => t('dashboard.tableHeader')) | ||
const loadingText = computed(() => t('dashboard.loadingText')) | ||
const props = defineProps<{ | ||
nAlgorithms: number | ||
}>() | ||
const getFullyComplete = async () => { | ||
const result = await algoritmeService.getCountWithFilledColumns('*') | ||
return result.data.value | ||
} | ||
const getMandatoryComplete = async () => { | ||
const notNullableColumns = data.value.filter( | ||
(column: any) => column.is_nullable == 'NO' | ||
) | ||
const columns = notNullableColumns.map( | ||
(c: any) => `${c.table_name}.${c.column_name}` | ||
) | ||
const result = await algoritmeService.getCountWithFilledColumns(columns) | ||
loading = false | ||
return result.data.value | ||
} | ||
const getMandatoryMissing = async () => { | ||
return ( | ||
props.nAlgorithms - | ||
(await getFullyComplete()) - | ||
(await getMandatoryComplete()) | ||
) | ||
} | ||
const aggregates = ref<{ label: string; value: string }[]>([]) | ||
const setAggregates = async () => { | ||
aggregates.value = [ | ||
{ | ||
label: t('dashboard.fullyComplete'), | ||
value: await getFullyComplete(), | ||
}, | ||
{ | ||
label: t('dashboard.mandatoryComplete'), | ||
value: await getMandatoryComplete(), | ||
}, | ||
{ | ||
label: t('dashboard.mandatoryMissing'), | ||
value: await getMandatoryMissing(), | ||
}, | ||
] | ||
} | ||
var loading = true | ||
const { data } = await algoritmeService.getColumns().then((value) => { | ||
setAggregates() | ||
return value | ||
}) | ||
</script> | ||
|
||
<style lang="scss"> | ||
.word-break { | ||
word-break: break-word; | ||
} | ||
.loading-text { | ||
text-align: center; | ||
} | ||
</style> |
Oops, something went wrong.