Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Owen/rekenhof #301

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@

# broccoli-debug
/DEBUG/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
151 changes: 151 additions & 0 deletions app/controllers/rekenhof.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { action, set } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import fetch from 'fetch';

export default class RekenhofController extends Controller {
@service('current-session') currentSession;
@tracked apiResults = null;
@tracked filterAangifteplichtig = false;

salaryOptions = [
{ label: 'Niet vergoed', value: 'option1' },
{ label: 'Tussen 1 en 5393 EUR', value: 'option2' },
{ label: 'Tussen 5340 en 11.880 EUR', value: 'option3' },
{ label: 'Tussen 11.881 en 59.399 EUR', value: 'option4' },
{ label: 'Tussen 59.400 en 118.798 EUR', value: 'option5' },
{ label: 'Manuele ingave (wordt afgerond op het dichtste honderdduizendtal)', value: 'manual' }
];

constructor() {
super(...arguments);
this.queryApi(); // Call the queryApi function when the controller is instantiated (when the page is loaded)
}

@action
handleSalaryChange(selected, result) {
// Using set to force reactiveness, otherwise the changes won't be reflected in the UI, not sure why since apiResults is @tracked
set(selected, 'selectedSalary', result);
}

@action
updateManualInput(selected, event) {
selected.manualInputValue = event.target.value;
}




// Queries rekenhof api for relevant data based on logged in bestuurseenheid
@action
async queryApi() {
let uri = this.currentSession.group.uri;
try {
let response = await fetch(`/rekenhof-api/bestuurseenheid-data?bestuurseenheid=${uri}&filterAangifteplichtig=${this.filterAangifteplichtig}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
let contentType = response.headers.get("content-type");
let data;
if (contentType && contentType.includes("application/json")) {
data = await response.json();
} else {
let text = await response.text();
try {
data = JSON.parse(text);
} catch (e) {
console.error("Received non-JSON response:", text);
throw new TypeError("Received non-JSON response");
}
}
this.apiResults = data.results.bindings.map(binding => {
let geslacht = binding.geslacht?.value;
if (geslacht === "http://publications.europa.eu/resource/authority/human-sex/FEMALE") {
geslacht = "Vrouw";
} else if (geslacht === "http://publications.europa.eu/resource/authority/human-sex/MALE") {
geslacht = "Man";
}

const formatDate = (dateString) => {
if (!dateString) return null;

// Handle dates with time part
if (dateString.includes('T')) {
dateString = dateString.split('T')[0];
}

const date = new Date(dateString);
const options = { day: 'numeric', month: 'long', year: 'numeric' };
return date.toLocaleDateString('nl-NL', options);
};

return {
voornaam: binding.voornaam?.value,
achternaam: binding.achternaam?.value,
geboortedatum: formatDate(binding.geboortedatum?.value),
geslacht: geslacht,
rrn: binding.rrn?.value,
bestuursorgaanTijdsspecialisatieLabel: binding.bestuursorgaanTijdsspecialisatieLabel?.value,
rol: binding.rolLabel?.value,
statusLabel: binding.statusLabel?.value,
startdatum: formatDate(binding.startdatum?.value),
einddatum: formatDate(binding.einddatum?.value),
};
});
} catch (error) {
console.error('Error querying API:', error);
this.apiResults = null;
}
}

@action
toggleFilterAangifteplichtig(newCheckedValue) {
this.filterAangifteplichtig = newCheckedValue;
this.queryApi(); // Resend the API call when the toggle is changed
}

@action
exportToCSV() {
console.log('Exporting to CSV');

if (!this.apiResults) {
console.error('apiResults is null or undefined');
return;
}


const rows = [
["Voornaam", "Achternaam", "Geboortedatum", "Geslacht", "RRN", "Bestuursorgaan", "Rol", "Status Label", "Startdatum", "Einddatum", "Vork bruto jaarsalaris na aftrek sociale bijdragen"],
...this.apiResults.map((result, index) => {
const salaryOutput = result.selectedSalary
? (result.selectedSalary.value === 'manual'
? Math.round(result.manualInputValue / 100000) * 100000 // Round to the nearest hundred thousand
: result.selectedSalary.label)
: '';
return [
result.voornaam,
result.achternaam,
result.geboortedatum,
result.geslacht,
result.rrn,
result.bestuursorgaanTijdsspecialisatieLabel,
result.rol,
result.statusLabel,
result.startdatum,
result.einddatum,
salaryOutput
];
})
];

let csvContent = "data:text/csv;charset=utf-8," + rows.map(e => e.join(",")).join("\n");
const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "rekenhof_data.csv");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
4 changes: 4 additions & 0 deletions app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ Router.map(function () {
});
});

this.route('rekenhof', function () {

});

this.route('under-construction');

this.route('error/404', {
Expand Down
9 changes: 9 additions & 0 deletions app/routes/rekenhof.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Route from '@ember/routing/route';

import { service } from '@ember/service';

export default class RekenhofRoute extends Route {
@service session;


}
28 changes: 28 additions & 0 deletions app/styles/_shame.scss
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,31 @@
.ember-power-select-option[aria-disabled=true] {
color: var(--au-gray-400);
}


// Rekenhof page styling

.rekenhof-outerDiv {
margin: 10px;
margin-left: 20px;
margin-right: 20px;
}

#rekenhof-exportbutton {
margin-left: 44vw;
width: 12vw;
padding: 5px;
margin-top: 4px;
}

.rekenhof-au-input {
margin-top: 16px;
width: 100%;
box-sizing: border-box;
}

.rekenhof-toggle-container {
margin-top: 5px;
margin-left: 15px;
margin-bottom: 5px;
}
74 changes: 74 additions & 0 deletions app/templates/rekenhof.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{{page-title "Rekenhof"}}

<div class="au-c-body-container au-c-body-container--scroll rekenhof-outerDiv">
<div class="rekenhof-toggle-container">
<AuCheckbox
@checked={{this.filterAangifteplichtig}}
@onChange={{this.toggleFilterAangifteplichtig}}
>
Toon enkel mandatarissen met minstens één aangifteplichtig mandaat
</AuCheckbox>
</div>

{{#if this.apiResults}}
<AuTable>
<:title>Gevonden mandaten binnen uw Bestuurseenheid</:title>
<:header>
<tr>
<th>Voornaam</th>
<th>Achternaam</th>
<th>Geboortedatum</th>
<th>Geslacht</th>
<th>RRN</th>
<th>Bestuursorgaan</th>
<th>Rol</th>
<th>Status Label</th>
<th>Startdatum</th>
<th>Einddatum</th>
<th>Vork bruto jaarsalaris na aftrek sociale bijdragen</th>
</tr>
</:header>
<:body>
{{#each this.apiResults as |result|}}
<tr>
<td>{{result.voornaam}}</td>
<td>{{result.achternaam}}</td>
<td>{{result.geboortedatum}}</td>
<td>{{result.geslacht}}</td>
<td>{{result.rrn}}</td>
<td>{{result.bestuursorgaanTijdsspecialisatieLabel}}</td>
<td>{{result.rol}}</td>
<td>{{result.statusLabel}}</td>
<td>{{result.startdatum}}</td>
<td>{{result.einddatum}}</td>
<td>
<PowerSelect
@options={{this.salaryOptions}}
@selected={{result.selectedSalary}}
@onChange={{fn this.handleSalaryChange result}}
as |option|>
{{option.label}}
</PowerSelect>
{{#if (eq result.selectedSalary.value "manual")}}
<AuInput
id="manualInput"
class="rekenhof-au-input"
type="number"
@value={{result.manualInputValue}}
@placeholder="Geef een bedrag in"
{{on "input" (fn this.updateManualInput result)}}
/>
{{/if}}
</td>
</tr>
{{/each}}
</:body>
</AuTable>

<div onclick={{fn this.exportToCSV}}>
<AuButton id="rekenhof-exportbutton" @icon="download">
Exporteer naar CSV
</AuButton>
</div>
{{/if}}
</div>
23 changes: 23 additions & 0 deletions e2e/Readme.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
This folder contains a set of automated end to end tests for the /rekenhof route.
The tests are written using the Playwright testing framework.

*EXECUTING THE TESTS*

Running npm install will install the @playwright/test package

You can run the tests with the following command:
npx playwright test --ui (this can be run in the root folder of the application)


In the folder /playwright-report, automatically generated files related to the ui will be created, so make sure this is in the .gitignore




*INFORMATION ABOUT THE TESTS*

The tests include a reusable login function that allows you to specify the location parameter,representing the municipality or entity being tested.
To test different locations, modify the location parameter in the test files as needed.
This function assumes the /mock-login route is being used for login so will require some changes to run in a production environment.


Loading