Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
yaf authored and Jeyffrey committed Dec 16, 2024
1 parent 4cbf727 commit 5b97136
Show file tree
Hide file tree
Showing 4 changed files with 250 additions and 87 deletions.
86 changes: 86 additions & 0 deletions admin/app/components/certifications/header.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import PixButton from '@1024pix/pix-ui/components/pix-button';
import PixTooltip from '@1024pix/pix-ui/components/pix-tooltip';
import { action } from '@ember/object';
import { service } from '@ember/service';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

import ConfirmPopup from '../confirm-popup';

export default class CertificationsHeader extends Component {
@service accessControl;

@tracked isModalDisplayed = false;
@tracked confirmMessage = null;

get canPublish() {
return (
!this.args.juryCertificationSummaries.some(
(certification) => certification.status === 'error' && !certification.isCancelled,
) && this.args.session.isFinalized
);
}

@action
displayConfirmationModal() {
this.confirmMessage = this.args.session.isPublished
? 'Souhaitez-vous dépublier la session ?'
: 'Souhaitez-vous publier la session ?';
this.isModalDisplayed = true;
}

@action
onModalCancel() {
this.isModalDisplayed = false;
}

@action
async toggleSessionPublication() {
if (this.args.session.isPublished) {
await this.args.unpublishSession();
} else {
await this.args.publishSession();
}
this.isModalDisplayed = false;
}

<template>
<header class="certification-list-page__header">
<h2>Certifications</h2>
{{#if this.accessControl.hasAccessToCertificationActionsScope}}
<div class="btn-group" role="group">

{{#if @session.isPublished}}
<PixButton @triggerAction={{this.displayConfirmationModal}}>Dépublier la session</PixButton>
{{else}}

{{#if this.canPublish}}
<PixButton @triggerAction={{this.displayConfirmationModal}}>Publier la session</PixButton>
{{else}}

<PixTooltip @position="left" @isWide={{true}}>
<:triggerElement>
<PixButton @triggerAction={{this.displayConfirmationModal}} @isDisabled={{true}}>
Publier la session
</PixButton>
</:triggerElement>
<:tooltip>
Vous ne pouvez pas publier la session tant qu'elle n'est pas finalisée ou qu'il reste des
certifications en erreur.
</:tooltip>
</PixTooltip>
{{/if}}

{{/if}}
</div>
{{/if}}
</header>

<ConfirmPopup
@message={{this.confirmMessage}}
@confirm={{this.toggleSessionPublication}}
@cancel={{this.onModalCancel}}
@show={{this.isModalDisplayed}}
/>
</template>
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,17 @@ const DEFAULT_PAGE_NUMBER = 1;
export default class ListController extends Controller {
@service pixToast;
@service store;
@service accessControl;

@tracked pageNumber = DEFAULT_PAGE_NUMBER;
@tracked pageSize = 10;

@tracked displayConfirm = false;
@tracked confirmMessage = null;

get canPublish() {
const juryCertificationSummaries = this.model.juryCertificationSummaries;
const { session } = this.model;

return (
!juryCertificationSummaries.some(
(certification) => certification.status === 'error' && !certification.isCancelled,
) && session.isFinalized
);
}

get sortedCertificationJurySummaries() {
return this.model.juryCertificationSummaries
.sortBy('numberOfCertificationIssueReportsWithRequiredAction')
.reverse();
}

@action
displayCertificationStatusUpdateConfirmationModal() {
const sessionIsPublished = this.model.session.isPublished;

if (!this.canPublish && !sessionIsPublished) return;

this.confirmMessage = sessionIsPublished
? 'Souhaitez-vous dépublier la session ?'
: 'Souhaitez-vous publier la session ?';
this.displayConfirm = true;
}

@action
async toggleSessionPublication() {
const isPublished = this.model.session.isPublished;
if (isPublished) {
await this.unpublishSession();
} else {
await this.publishSession();
}
}

async unpublishSession() {
try {
await this.model.session.save({ adapterOptions: { updatePublishedCertifications: true, toPublish: false } });
Expand All @@ -64,9 +28,9 @@ export default class ListController extends Controller {
} finally {
await this.forceRefreshModelFromBackend();
}
this.hideConfirmationModal();
}

@action
async publishSession() {
try {
await this.model.session.save({ adapterOptions: { updatePublishedCertifications: true, toPublish: true } });
Expand All @@ -80,9 +44,9 @@ export default class ListController extends Controller {
if (this.model.session.isPublished) {
this.pixToast.sendSuccessNotification({ message: 'Les certifications ont été correctement publiées.' });
}
this.hideConfirmationModal();
}

@action
notifyError(error) {
if (error.errors && error.errors[0] && error.errors[0].detail) {
this.pixToast.sendErrorNotification({ message: error.errors[0].detail });
Expand All @@ -91,16 +55,8 @@ export default class ListController extends Controller {
}
}

@action
async forceRefreshModelFromBackend() {
await this.store.findRecord('session', this.model.session.id, { reload: true });
}

hideConfirmationModal() {
this.displayConfirm = false;
}

@action
onCancelConfirm() {
this.displayConfirm = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,12 @@
<section>
<div class="certification-list-page">

<header class="certification-list-page__header">
<h2>Certifications</h2>
{{#if this.accessControl.hasAccessToCertificationActionsScope}}
<div class="btn-group" role="group">

{{#if this.model.session.isPublished}}
<PixButton @triggerAction={{this.displayCertificationStatusUpdateConfirmationModal}}>Dépublier la session</PixButton>
{{else}}

{{#if this.canPublish}}
<PixButton @triggerAction={{this.displayCertificationStatusUpdateConfirmationModal}}>Publier la session</PixButton>
{{else}}

<PixTooltip @position="left" @isWide={{true}}>
<:triggerElement>
<PixButton
@triggerAction={{this.displayCertificationStatusUpdateConfirmationModal}}
@isDisabled={{true}}
>
Publier la session
</PixButton>
</:triggerElement>
<:tooltip>
Vous ne pouvez pas publier la session tant qu'elle n'est pas finalisée ou qu'il reste des
certifications en erreur.
</:tooltip>
</PixTooltip>
{{/if}}

{{/if}}
</div>
{{/if}}
</header>
<Certifications::Header
@session={{this.model.session}}
@juryCertificationSummaries={{this.model.juryCertificationSummaries}}
@unpublishSession={{this.unpublishSession}}
@publishSession={{this.publishSession}}
/>

<div>
<Certifications::List
Expand All @@ -46,10 +19,3 @@
</div>
</div>
</section>

<ConfirmPopup
@message={{this.confirmMessage}}
@confirm={{action this.toggleSessionPublication}}
@cancel={{action this.onCancelConfirm}}
@show={{this.displayConfirm}}
/>
155 changes: 155 additions & 0 deletions admin/tests/integration/components/certifications/header-test.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { fireEvent, render } from '@1024pix/ember-testing-library';
import Service from '@ember/service';
import CertificationsHeader from 'pix-admin/components/certifications/header';
import { module, test } from 'qunit';

import setupIntlRenderingTest from '../../../helpers/setup-intl-rendering';

module('Integration | Component | certifications/header', function (hooks) {
setupIntlRenderingTest(hooks);

let store;

hooks.beforeEach(async function () {
store = this.owner.lookup('service:store');
});

module('when user has access to the certification session', function (hooks) {
hooks.beforeEach(function () {
class SessionStub extends Service {
hasAccessToCertificationActionsScope = true;
}
this.owner.register('service:accessControl', SessionStub);
});

test('should display a title', async function (assert) {
// given
const session = store.createRecord('session', { publishedAt: new Date() });

// when
const screen = await render(<template><CertificationsHeader @session={{session}} /></template>);

// then
assert.dom(screen.getByRole('heading', { level: 2, name: 'Certifications' })).exists();
});

module('when session is published', function () {
test('should display an unpublication button', async function (assert) {
// given
const session = store.createRecord('session', { publishedAt: new Date() });

// when
const screen = await render(<template><CertificationsHeader @session={{session}} /></template>);

// then
assert.dom(screen.getByRole('button', { name: 'Dépublier la session' })).exists();
});
});

module('when session is not published', function () {
module('when the session is not finalized', function () {
test('should display a disabled publication button with a tooltip', async function (assert) {
// given
const session = store.createRecord('session', { status: 'created', publishedAt: null });

const juryCertificationSummaries = [];

// when
const screen = await render(
<template>
<CertificationsHeader @session={{session}} @juryCertificationSummaries={{juryCertificationSummaries}} />
</template>,
);

// then
assert.dom(screen.getByRole('button', { name: 'Publier la session' })).isDisabled();

fireEvent.mouseOver(screen.getByRole('button', { name: 'Publier la session' }));
const tooltipText =
"Vous ne pouvez pas publier la session tant qu'elle n'est pas finalisée ou qu'il reste des certifications en erreur.";
assert.dom(screen.getByText(tooltipText)).exists();
});
});

module('when there are no jury certification summaries', function () {
test('should display a disabled publication button', async function (assert) {
// given
const session = store.createRecord('session', { publishedAt: null });

const juryCertificationSummaries = [];

// when
const screen = await render(
<template>
<CertificationsHeader @session={{session}} @juryCertificationSummaries={{juryCertificationSummaries}} />
</template>,
);

// then
assert.dom(screen.getByRole('button', { name: 'Publier la session' })).isDisabled();
});
});

module('when there is only invalid jury certification summaries', function () {
module('when the jury certification summary is cancelled', function () {
test('should display a disabled publication button', async function (assert) {
// given
const session = store.createRecord('session', { publishedAt: null });

const juryCertificationSummaries = [
store.createRecord('jury-certification-summary', { isCancelled: true }),
];

// when
const screen = await render(
<template>
<CertificationsHeader @session={{session}} @juryCertificationSummaries={{juryCertificationSummaries}} />
</template>,
);

// then
assert.dom(screen.getByRole('button', { name: 'Publier la session' })).isDisabled();
});
});

module('when the jury certification summary is on error', function () {
test('should display a disabled publication button', async function (assert) {
// given
const session = store.createRecord('session', { publishedAt: null });

const juryCertificationSummaries = [store.createRecord('jury-certification-summary', { status: 'error' })];

// when
const screen = await render(
<template>
<CertificationsHeader @session={{session}} @juryCertificationSummaries={{juryCertificationSummaries}} />
</template>,
);

// then
assert.dom(screen.getByRole('button', { name: 'Publier la session' })).isDisabled();
});
});
});

module('when there is only valid jury certification summaries', function () {
test('should display an enabled publication button', async function (assert) {
// given
const session = store.createRecord('session', { publishedAt: null, status: 'finalized' });

const juryCertificationSummaries = [store.createRecord('jury-certification-summary', { isCancelled: false })];

// when
const screen = await render(
<template>
<CertificationsHeader @session={{session}} @juryCertificationSummaries={{juryCertificationSummaries}} />
</template>,
);

// then
assert.dom(screen.getByRole('button', { name: 'Publier la session' })).isNotDisabled();
});
});
});
});
});

0 comments on commit 5b97136

Please sign in to comment.