Skip to content

Commit

Permalink
Merge pull request #2266 from kanselarij-vlaanderen/feature/KAS-4805-…
Browse files Browse the repository at this point in the history
…empty-internal-review

KAS-4805 implement emptying interal review private comment feature
  • Loading branch information
ValenberghsSven authored Jan 7, 2025
2 parents 0957b99 + 608799d commit ed0911d
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 21 deletions.
1 change: 1 addition & 0 deletions app/components/agenda/agenda-header.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<Agenda::AgendaHeader::AgendaActions
@meeting={{@meeting}}
@currentAgenda={{@currentAgenda}}
@reverseSortedAgendas={{@reverseSortedAgendas}}
@didApproveAgendaitems={{@refreshRoute}}
@onStartLoading={{this.setLoadingMessage}}
@onStopLoading={{this.clearLoadingMessage}}
Expand Down
30 changes: 30 additions & 0 deletions app/components/agenda/agenda-header/agenda-actions.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@
{{t "approve-all-agendaitems"}}
</AuButton>
{{/if}}
{{#if this.canEmptyInternalReviews}}
<AuButton
@skin="link"
{{on "click" this.openConfirmEmptyInternalReviews}}
role="menuitem"
>
{{t "empty-internal-review"}}
</AuButton>
{{/if}}
{{#if this.canPublishDecisions}}
<AuHr />
<AuButton
Expand Down Expand Up @@ -348,3 +357,24 @@
</div>
</:body>
</ConfirmationModal>

{{#if this.showConfirmEmptyInternalReviews}}
<Auk::Modal @size="small">
<Auk::Modal::Header
@title={{t "empty-internal-review"}}
@onClose={{this.cancelEmptyInternalReviews}}
/>
<Auk::Modal::Body>
<p class="auk-u-text-prewrap">{{t "empty-internal-review-message"}}</p>
</Auk::Modal::Body>
<Auk::Modal::Footer @onCancel={{this.cancelEmptyInternalReviews}}>
<AuButton
@skin="primary"
@loading={{this.emptyInteralReviewsOfAgendaitemThrottled.isRunning}}
{{on "click" this.emptyInteralReviews}}
>
{{t "empty-internal-review"}}
</AuButton>
</Auk::Modal::Footer>
</Auk::Modal>
{{/if}}
64 changes: 63 additions & 1 deletion app/components/agenda/agenda-header/agenda-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import {
} from 'frontend-kaleidos/utils/zip-agenda-files';
import CONSTANTS from 'frontend-kaleidos/config/constants';
import bind from 'frontend-kaleidos/utils/bind';
import { isPresent } from '@ember/utils';
import { isEmpty, isPresent } from '@ember/utils';
import DownloadFileToast from 'frontend-kaleidos/components/utils/toaster/download-file-toast';

/**
* @argument {Meeting} meeting
* @argument {Agenda} currentAgenda
* @argument {[Agenda]} reverseSortedAgendas: the agendas of the meeting, reverse sorted on serial number
* @argument {function} didApproveAgendaitems
* @argument onStartLoading
* @argument onStopLoading
Expand Down Expand Up @@ -53,6 +54,7 @@ export default class AgendaAgendaHeaderAgendaActions extends Component {
@tracked showDownloadDocuments = false;
@tracked selectedMandatees = [];
@tracked showDownloadDecisions = false;
@tracked showConfirmEmptyInternalReviews = false;

@tracked decisionPublicationActivity;
@tracked documentPublicationActivity;
Expand Down Expand Up @@ -128,6 +130,23 @@ export default class AgendaAgendaHeaderAgendaActions extends Component {
return isPresent(this.args.meeting.agenda.get('id'));
}

get latestAgenda() {
return this.args.reverseSortedAgendas.slice().at(0);
}

get currentAgendaIsLatest() {
return (
this.latestAgenda.id === this.args.currentAgenda.id
);
}

get canEmptyInternalReviews() {
// action will do nothing on designAgenda A, so hide it instead. This method avoids having to yield async relations
const isDesignAgendaA = this.args.currentAgenda.status.get('isDesignAgenda') && this.args.reverseSortedAgendas.length == 1;
// need permission and be on the latest agenda to do the action
return this.currentSession.may('manage-agendaitems') && this.currentAgendaIsLatest && !isDesignAgendaA;
}

@bind
async allAgendaitemsNotOk() {
const agendaitems = await this.args.currentAgenda.agendaitems;
Expand Down Expand Up @@ -352,6 +371,39 @@ export default class AgendaAgendaHeaderAgendaActions extends Component {
this.router.refresh(this.router.currentRouteName);
}

emptyInteralReviews = async() => {
this.showConfirmEmptyInternalReviews = false;
this.args.onStartLoading(this.intl.t('empty-internal-review'));
// getting all valid agendaitems first gets better results than trying submission-internal-review directly via subcase
const agendaStatus = await this.args.currentAgenda.status;
const approvedAgendaitems = await this.store.queryAll('agendaitem', {
'filter[:has:previous-version]': agendaStatus.isDesignAgenda ? true : undefined,
'filter[agenda][:id:]': this.args.currentAgenda.id,
});
const savePromises = approvedAgendaitems.map((agendaitem) => this.emptyInteralReviewsOfAgendaitemThrottled.perform(agendaitem));
await all(savePromises);
// TODO KAS-4886 this can go when we no longer have to save agendaitems
this.args.onStopLoading();
this.args.didApproveAgendaitems(); // just calls a refresh route
};

emptyInteralReviewsOfAgendaitemThrottled = task({ maxConcurrency: 5}, async (agendaitem) => {
const internalReview = await this.store.queryOne('submission-internal-review', {
'filter[subcase][agenda-activities][agendaitems][:id:]': agendaitem.id,
})
if (internalReview?.id && !isEmpty(internalReview.privateComment)) {
internalReview.privateComment = '';
await internalReview.save();
}
// This property was still filled prior to this code, we should empty it to avoid showing this briefly in agenda overview
// TODO KAS-4886 remove when property is removed from model
if (!isEmpty(agendaitem.privateComment)) {
agendaitem.privateComment = '';
await agendaitem.save();
}
return;
});

@action
print() {
window.print();
Expand Down Expand Up @@ -463,4 +515,14 @@ export default class AgendaAgendaHeaderAgendaActions extends Component {
onChangeDownloadOption(selectedDownloadOption) {
this.downloadOption = selectedDownloadOption;
}

openConfirmEmptyInternalReviews = () => {
// TODO KAS-4886 this first line can go when we no longer have to save agendaitems
this.reloadAgendaitemsData.perform(); // Do we need to reload anything?? The interalreview may not be loaded yet, but the model itself cannot be stale
this.showConfirmEmptyInternalReviews = true;
};

cancelEmptyInternalReviews = () => {
this.showConfirmEmptyInternalReviews = false;
};
}
36 changes: 19 additions & 17 deletions app/components/mandatees/mandatees-selector-modal.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@
@onClose={{@onClose}}
/>
<Auk::Modal::Body>
<div class="auk-o-flex--inline auk-o-flex--vertical-center auk-u-mb-2">
<AuCheckbox
data-test-mandatees-selector-open-search
@checked={{this.openSearch}}
@onChange={{this.setOpenSearch}}
>
{{t "open-search-for-mandatee"}}
</AuCheckbox>
{{#let (concat "tooltip-trigger-" (unique-id)) as |tooltipTriggerId|}}
<AuIcon @icon="circle-info" id={{tooltipTriggerId}} class="au-u-muted auk-u-ml" />
<EmberTooltip @targetId={{tooltipTriggerId}} @tooltipClass="auk-tooltip" @side="bottom">
<p>
{{t "open-search-for-mandatee-tooltip"}}
</p>
</EmberTooltip>
{{/let}}
</div>
{{#if (user-may "add-past-mandatees")}}
<div class="auk-o-flex--inline auk-o-flex--vertical-center auk-u-mb-2">
<AuCheckbox
data-test-mandatees-selector-open-search
@checked={{this.openSearch}}
@onChange={{this.setOpenSearch}}
>
{{t "open-search-for-mandatee"}}
</AuCheckbox>
{{#let (concat "tooltip-trigger-" (unique-id)) as |tooltipTriggerId|}}
<AuIcon @icon="circle-info" id={{tooltipTriggerId}} class="au-u-muted auk-u-ml" />
<EmberTooltip @targetId={{tooltipTriggerId}} @tooltipClass="auk-tooltip" @side="bottom">
<p>
{{t "open-search-for-mandatee-tooltip"}}
</p>
</EmberTooltip>
{{/let}}
</div>
{{/if}}
<Utils::LoadableContent
@isLoading={{this.onAdd.isRunning}}
@reserveSpace={{true}}
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/newsletters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default class NewslettersIndexController extends Controller {
const agendas = await meeting.agendas;
return agendas
?.slice()
.sort((a1, a2) => a1.serialNumber.localeCompare(a2.serialNumber))
.sort((a1, a2) => a1.serialnumber.localeCompare(a2.serialnumber))
.reverse()
.at(0);
}
Expand Down
2 changes: 1 addition & 1 deletion app/services/agenda-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export default class AgendaService extends Service {
body: JSON.stringify({
subcase: subcase.uri,
formallyOkStatus: formallyStatusUri,
privateComment: privateComment,
privateComment: null, // TODO KAS-4886 fully remove, private comments were still being set on the agendaitem
})
});
let json;
Expand Down
4 changes: 3 additions & 1 deletion translations/nl-be.json
Original file line number Diff line number Diff line change
Expand Up @@ -1487,5 +1487,7 @@
"generate-press-agenda": "Genereer persagenda",
"login-text" : "Meld u aan",
"show-definitive-cases-only": "Toon enkel dossiers zonder definitieve goedkeuring",
"warning-new-case-has-parliament-flow": "Deze procedurestap kan niet naar dit dossier verplaatst worden aangezien er al een koppeling is met het Vlaams Parlement"
"warning-new-case-has-parliament-flow": "Deze procedurestap kan niet naar dit dossier verplaatst worden aangezien er al een koppeling is met het Vlaams Parlement",
"empty-internal-review": "Interne opmerkingen leegmaken",
"empty-internal-review-message": "Bent u zeker dat u alle interne opmerkingen voor de goedgekeurde agendapunten op deze agenda wil leegmaken?\nDeze actie kan niet ongedaan worden gemaakt.\nDe interne opmerkingen van nieuwe agendapunten blijven ongewijzigd."
}

0 comments on commit ed0911d

Please sign in to comment.