Skip to content

Commit

Permalink
Merge pull request #722 from lblod/feat/download-meeting-part
Browse files Browse the repository at this point in the history
Feat/download meeting part
  • Loading branch information
abeforgit authored Oct 8, 2024
2 parents efe418d + 88c33c4 commit dbb8187
Show file tree
Hide file tree
Showing 12 changed files with 476 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/tender-olives-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'frontend-gelinkt-notuleren': minor
---

Users can now download certain meeting parts as HTML
132 changes: 132 additions & 0 deletions app/components/download-meeting-part.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import Component from '@glimmer/component';
import { service } from '@ember/service';
import AuIcon from '@appuniversum/ember-appuniversum/components/au-icon';
import AuLoader from '@appuniversum/ember-appuniversum/components/au-loader';
import AuButton from '@appuniversum/ember-appuniversum/components/au-button';
import { on } from '@ember/modifier';
import t from 'ember-intl/helpers/t';
import { task } from 'ember-concurrency';
import perform from 'ember-concurrency/helpers/perform';
import { stripHtmlForPublish } from '@lblod/ember-rdfa-editor/utils/strip-html-for-publish';

const PREFIXES = [
'eli: http://data.europa.eu/eli/ontology#',
'prov: http://www.w3.org/ns/prov#',
'mandaat: http://data.vlaanderen.be/ns/mandaat#',
'besluit: http://data.vlaanderen.be/ns/besluit#',
'ext: http://mu.semte.ch/vocabularies/ext/',
'person: http://www.w3.org/ns/person#',
'persoon: http://data.vlaanderen.be/ns/persoon#',
'dateplugin: http://say.data.gift/manipulators/insertion/',
'besluittype: https://data.vlaanderen.be/id/concept/BesluitType/',
'dct: http://purl.org/dc/terms/',
'mobiliteit: https://data.vlaanderen.be/ns/mobiliteit#',
'lblodmow: http://data.lblod.info/vocabularies/mobiliteit/',
];

export default class DownloadMeetingComponent extends Component {
@service publish;
@service intl;

downloadMeeting = task(async () => {
let route = `/prepublish/${this.args.documentType}`;
let html;
switch (this.args.documentType) {
case 'agendapunt': {
html = await this.downloadAgendapoint(
this.args.meeting.id,
this.args.behandeling.id,
);
break;
}
case 'besluit': {
html = await this.downloadBesluit(this.args.behandeling);
break;
}
case 'agenda': {
html = await this.downloadAgenda(
this.args.meeting.id,
this.args.agendaType,
);
break;
}
default: {
const json = await this.publish.fetchJobTask.perform(
`${route}/${this.args.meeting.id}`,
);
html = json.data.attributes.content;
break;
}
}
const file = new Blob([html], { type: 'text/html' });
const linkElement = document.createElement('a');
linkElement.href = URL.createObjectURL(file);
linkElement.download = `${this.args.documentType}.html`;
linkElement.click();
});
get buttonText() {
return this.intl.t(`download.document-download.${this.args.documentType}`);
}
async downloadAgenda(meetingId, agendaType) {
const response = await fetch(
`/prepublish/agenda/${agendaType}/${meetingId}`,
);
const json = await response.json();
return json.data.attributes.content;
}
async downloadAgendapoint(meetingId, behandelingId) {
const response = await fetch(`/extract-previews`, {
method: 'POST',
headers: {
'Content-Type': 'application/vnd.api+json',
},
body: JSON.stringify({
data: {
type: 'extract-previews',
relationships: {
treatment: {
data: {
id: behandelingId,
},
},
},
},
}),
});
const json = await response.json();
return json.data.attributes.html;
}
async downloadBesluit(behandeling) {
const documentContainer = await behandeling.get('documentContainer');
const currentVersion = await documentContainer.currentVersion;
const content = currentVersion.content;
const enrichedContent = `
<div prefix="${PREFIXES.join(' ')}">
${stripHtmlForPublish(content)}
</div>
`;
return enrichedContent;
}
<template>
{{#if this.downloadMeeting.last.isSuccessful}}
<span
class='download-meeting-part-downloaded au-u-flex--inline au-u-flex--vertical-center'
>
<AuIcon @icon='circle-check' />
{{t 'download-meeting-part.downloaded'}}
</span>
{{else if this.downloadMeeting.isRunning}}
<AuLoader @inline='true'>
{{t 'download-meeting-part.downloading'}}
</AuLoader>
{{else}}
<AuButton
@skin='link'
@icon={{@icon}}
{{on 'click' (perform this.downloadMeeting)}}
>
{{this.buttonText}}
</AuButton>
{{/if}}
</template>
}
21 changes: 20 additions & 1 deletion app/components/meeting-form.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,30 @@
</Group>
<Group class='au-u-flex--vertical-center'>
{{#unless this.readOnly}}
<DeleteMeeting @meeting={{@zitting}} />
{{#if this.isInaugurationMeeting}}
<InaugurationMeeting::Synchronization @meeting={{this.zitting}} />
{{/if}}
{{/unless}}
<AuDropdown
@skin='secondary'
@title={{t 'meeting-form.actions.dropdown-title'}}
@alignment='left'
@icon='chevron-down'
role='menu'
>
<AuLink
@skin='primary'
@route='meetings.download'
@icon='copy-paste'
@model={{@zitting}}
role='menuitem'
>
{{t 'meeting-form.actions.download-treatments'}}
</AuLink>
{{#unless this.readOnly}}
<DeleteMeeting @meeting={{@zitting}} />
{{/unless}}
</AuDropdown>
{{#if this.isComplete}}
<AuButton @skin='secondary' {{on 'click' this.goToPublish}}>
{{t 'meeting-form.publish-button'}}
Expand Down
80 changes: 80 additions & 0 deletions app/controllers/meetings/download.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import Controller from '@ember/controller';
import { articlesBasedOnClassifcationMap } from '../../utils/classification-utils';
import { restartableTask, task } from 'ember-concurrency';
import { trackedTask } from 'reactiveweb/ember-concurrency';
import InstallatieVergaderingModel from 'frontend-gelinkt-notuleren/models/installatievergadering';
import { service } from '@ember/service';

export default class MeetingsDownloadController extends Controller {
@service publish;
get zitting() {
return this.model;
}
get agendapoints() {
return this.zitting.agendapunten;
}
get meetingDateForTitle() {
if (this.zitting?.gestartOpTijdstip) {
return this.zitting.gestartOpTijdstip;
} else return this.zitting.geplandeStart;
}
get headerArticleTranslationString() {
return (
this.meetingDetailsData.value?.headerArticleTranslationString ??
'meeting-form.meeting-heading-article-ungendered'
);
}

downloadMeeting = task(async () => {
const json = await this.publish.fetchJobTask.perform(
`/prepublish/notulen/${this.zitting.id}`,
);
const html = json.data.attributes.content;
this.downloadHtml(html, 'notulen');
});

downloadAgenda = task(async () => {
const response = await fetch(
`/prepublish/agenda/bdf68a65-ce15-42c8-ae1b-19eeb39e20d0/${this.zitting.id}`,
);
const json = await response.json();
const html = json.data.attributes.content;
this.downloadHtml(html, 'agenda');
});

downloadDecisionlist = task(async () => {
const json = await this.publish.fetchJobTask.perform(
`/prepublish/besluitenlijst/${this.zitting.id}`,
);
const html = json.data.attributes.content;
this.downloadHtml(html, 'besluitenlijst');
});

downloadHtml(html, documentName) {
const file = new Blob([html], { type: 'text/html' });
const linkElement = document.createElement('a');
linkElement.href = URL.createObjectURL(file);
linkElement.download = `${documentName}.html`;
linkElement.click();
}

meetingDetailsTask = restartableTask(async () => {
const bestuursorgaan = await this.zitting.bestuursorgaan;
const specialisedBestuursorgaan =
await bestuursorgaan.isTijdsspecialisatieVan;
const classification = await specialisedBestuursorgaan.classificatie;
const headerArticleTranslationString =
articlesBasedOnClassifcationMap[classification.uri];
return {
bestuursorgaan,
headerArticleTranslationString,
};
});
meetingDetailsData = trackedTask(this, this.meetingDetailsTask, () => [
this.zitting.bestuursorgaan,
]);

get isInaugurationMeeting() {
return this.zitting instanceof InstallatieVergaderingModel;
}
}
1 change: 1 addition & 0 deletions app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Router.map(function () {
this.route('detail', { path: '/:publishing_log_id' });
});
});
this.route('download', { path: '/:id/download' });
});

this.route('irg-archive', function () {
Expand Down
13 changes: 13 additions & 0 deletions app/routes/meetings/download.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Route from '@ember/routing/route';
import { service } from '@ember/service';

export default class MeetingsDownloadRoute extends Route {
@service store;
async model(params) {
const zitting = await this.store.findRecord('zitting', params.id, {
include: 'bestuursorgaan,agendapunten.behandeling',
});
zitting.agendapunten = (await zitting.agendapunten).sortBy('position');
return zitting;
}
}
11 changes: 11 additions & 0 deletions app/styles/_shame.scss
Original file line number Diff line number Diff line change
Expand Up @@ -771,3 +771,14 @@ div[typeof='besluitpublicatie:Documentonderdeel'] {
#ember-basic-dropdown-wormhole {
z-index: 20000;
}

.au-c-data-table-with-borders {
border-left: 0.1rem solid var(--au-gray-300);
border-right: 0.1rem solid var(--au-gray-300);
}
.download-meeting-part-downloaded {
color: var(--au-green-700);
.au-c-icon {
margin-right: 0.5rem;
}
}
Loading

0 comments on commit dbb8187

Please sign in to comment.