Skip to content

Commit

Permalink
feat(admin): add internalName property for target profile administration
Browse files Browse the repository at this point in the history
  • Loading branch information
Guillaume committed Mar 6, 2025
1 parent f1e388c commit 7996272
Show file tree
Hide file tree
Showing 29 changed files with 135 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ export default class OrganizationTargetProfilesSectionComponent extends Componen
<thead>
<tr>
<th class="table__column table__column--id">ID</th>
<th>Nom du profil cible</th>
<th>Nom interne du profil cible</th>
{{#if this.accessControl.hasAccessToOrganizationActionsScope}}
<th>Actions</th>
{{/if}}
Expand All @@ -179,7 +179,7 @@ export default class OrganizationTargetProfilesSectionComponent extends Componen
<td class="table__column table__column--id">{{summary.id}}</td>
<td headers="target-profile-name">
<LinkTo @route="authenticated.target-profiles.target-profile" @model={{summary.id}}>
{{summary.name}}
{{summary.internalName}}
</LinkTo>
</td>
{{#if this.accessControl.hasAccessToOrganizationActionsScope}}
Expand Down
17 changes: 15 additions & 2 deletions admin/app/components/target-profiles/edit-target-profile-form.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { optionsCategoryList } from '../../models/target-profile';
import Card from '../card';
import TubesSelection from '../common/tubes-selection';

export default class CreateTargetProfileForm extends Component {
export default class EditTargetProfileForm extends Component {
@tracked submitting = false;
selectedTubes = [];

Expand Down Expand Up @@ -65,7 +65,19 @@ export default class CreateTargetProfileForm extends Component {
{{t "common.forms.mandatory-fields" htmlSafe=true}}
</p>
<section class="admin-form__content admin-form__content--with-counters">

<Card class="admin-form__card" @title="Information sur le profil cible">
<PixInput
@id="targetProfileInternalName"
required={{true}}
@requiredLabel={{t "common.forms.mandatory"}}
aria-required={{true}}
@value={{@targetProfile.internalName}}
{{on "change" (fn this.handleInputValue "internalName")}}
>
<:label>Nom interne :</:label>
</PixInput>

<PixInput
@id="targetProfileName"
required={{true}}
Expand All @@ -74,7 +86,7 @@ export default class CreateTargetProfileForm extends Component {
@value={{@targetProfile.name}}
{{on "change" (fn this.handleInputValue "name")}}
>
<:label>Nom :</:label>
<:label>Nom externe :</:label>
</PixInput>

<PixSelect
Expand Down Expand Up @@ -161,6 +173,7 @@ export default class CreateTargetProfileForm extends Component {
</PixTextarea>
</Card>
</section>

<section class="admin-form__actions">
<PixButton @variant="secondary" @size="large" @triggerAction={{@onCancel}}>
{{t "common.actions.cancel"}}
Expand Down
15 changes: 8 additions & 7 deletions admin/app/components/target-profiles/list-summary-items.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class TargetProfileListSummaryItems extends Component {
@tracked selectedValues = [];

get isClearFiltersButtonDisabled() {
return !this.args.id && !this.args.name && this.args.categories?.length === 0;
return !this.args.id && !this.args.internalName && this.args.categories?.length === 0;
}

get categoryOptions() {
Expand Down Expand Up @@ -52,13 +52,14 @@ export default class TargetProfileListSummaryItems extends Component {

<PixInput
type="text"
value={{@name}}
placeholder={{t "pages.target-profiles.filters.search-by-name.placeholder"}}
oninput={{fn @triggerFiltering "name"}}
value={{@internalName}}
placeholder={{t "pages.target-profiles.filters.search-by-internal-name.placeholder"}}
oninput={{fn @triggerFiltering "internalName"}}
@screenReaderOnly={{true}}
>
<:label>{{t "pages.target-profiles.filters.search-by-name.name"}}</:label>
<:label>{{t "pages.target-profiles.filters.search-by-internal-name.name"}}</:label>
</PixInput>

<PixMultiSelect
@id="categories"
@screenReaderOnly={{true}}
Expand All @@ -79,7 +80,7 @@ export default class TargetProfileListSummaryItems extends Component {
<thead>
<tr>
<th class="table__column table__column--id">{{t "common.fields.id"}}</th>
<th>{{t "common.fields.name"}}</th>
<th>{{t "common.fields.internalName"}}</th>
<th>{{t "common.fields.target-profile.category.name"}}</th>
<th class="col-date">{{t "common.fields.createdAt"}}</th>
<th class="col-status">{{t "common.fields.status"}}</th>
Expand All @@ -93,7 +94,7 @@ export default class TargetProfileListSummaryItems extends Component {
<td class="table__column table__column--id">{{summary.id}}</td>
<td>
<LinkTo @route="authenticated.target-profiles.target-profile" @model={{summary.id}}>
{{summary.name}}
{{summary.internalName}}
</LinkTo>
</td>
<td class="table__column table__column--id">{{t summary.translationKeyCategory}}</td>
Expand Down
6 changes: 4 additions & 2 deletions admin/app/components/target-profiles/target-profile.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -178,19 +178,21 @@ export default class TargetProfile extends Component {
<div>
<LinkTo @route="authenticated.target-profiles.list">Tous les profils cibles</LinkTo>
<span class="wire">&nbsp;>&nbsp;</span>
<h1>{{@model.name}}</h1>
<h1>{{@model.internalName}}</h1>
</div>
</header>

<main class="page-body">
<section class="page-section target-profile-section">
<div class="page-section__header">
<h2 class="page-section__title target-profile__title">{{@model.name}}</h2>
<h2 class="page-section__title target-profile__title">{{@model.internalName}}</h2>
<Category @category={{@model.category}} />
</div>
<div class="target-profile-section__container">
<ul>
<li><span class="bold">ID&#x20;:&#x20;</span>{{@model.id}}</li>
<li><span class="bold">Nom interne&#x20;:&#x20;</span>{{@model.internalName}}</li>
<li><span class="bold">Nom externe&#x20;:&#x20;</span>{{@model.name}}</li>
<li><span class="bold">Organisation de référence&#x20;:&#x20;</span><LinkTo
@route="authenticated.organizations.get"
@model={{@model.ownerOrganizationId}}
Expand Down
6 changes: 3 additions & 3 deletions admin/app/controllers/authenticated/target-profiles/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import config from 'pix-admin/config/environment';
const DEFAULT_PAGE_NUMBER = 1;

export default class ListController extends Controller {
queryParams = ['pageNumber', 'pageSize', 'id', 'name', 'categories'];
queryParams = ['pageNumber', 'pageSize', 'id', 'internalName', 'categories'];
DEBOUNCE_MS = config.pagination.debounce;

@tracked pageNumber = DEFAULT_PAGE_NUMBER;
@tracked pageSize = 10;
@tracked id = null;
@tracked name = null;
@tracked internalName = null;
@tracked categories = [];

updateFilters(filters) {
Expand All @@ -31,7 +31,7 @@ export default class ListController extends Controller {
@action
onResetFilter() {
this.id = null;
this.name = null;
this.internalName = null;
this.categories = [];
}
}
15 changes: 15 additions & 0 deletions admin/app/models/target-profile-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ const Validations = buildValidations({
}),
],
},
internalName: {
validators: [
validator('presence', {
presence: true,
ignoreBlank: true,
message: 'Le nom interne ne peut pas être vide',
}),
validator('length', {
min: 1,
max: 255,
message: 'La longueur du nom ne doit pas excéder 255 caractères',
}),
],
},
description: {
validators: [
validator('length', {
Expand Down Expand Up @@ -43,6 +57,7 @@ const Validations = buildValidations({

export default class TargetProfileForm extends Model.extend(Validations) {
@attr('string') name;
@attr('string') internalName;
@attr('string') description;
@attr('string') comment;
@attr('string') category;
Expand Down
2 changes: 1 addition & 1 deletion admin/app/models/target-profile-summary.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Model, { attr } from '@ember-data/model';

import { categories } from '../helpers/target-profile-categories';
export default class TargetProfileSummary extends Model {
@attr() name;
@attr() internalName;
@attr() outdated;
@attr() category;
@attr() createdAt;
Expand Down
1 change: 1 addition & 0 deletions admin/app/models/target-profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default class TargetProfile extends Model {
@service session;

@attr('nullable-string') name;
@attr('nullable-string') internalName;
@attr('date') createdAt;
@attr('nullable-string') imageUrl;
@attr('boolean') outdated;
Expand Down
6 changes: 3 additions & 3 deletions admin/app/routes/authenticated/target-profiles/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default class ListRoute extends Route {
pageNumber: { refreshModel: true },
pageSize: { refreshModel: true },
id: { refreshModel: true },
name: { refreshModel: true },
internalName: { refreshModel: true },
categories: { refreshModel: true },
};

Expand All @@ -25,7 +25,7 @@ export default class ListRoute extends Route {
targetProfileSummaries = await this.store.query('target-profile-summary', {
filter: {
id: params.id ? params.id.trim() : '',
name: params.name ? params.name.trim() : '',
internalName: params.internalName ? params.internalName.trim() : '',
categories: params.categories ?? [],
},
page: {
Expand All @@ -47,7 +47,7 @@ export default class ListRoute extends Route {
controller.pageNumber = 1;
controller.pageSize = 10;
controller.id = null;
controller.name = null;
controller.internalName = null;
controller.categories = [];
}
}
Expand Down
2 changes: 2 additions & 0 deletions admin/app/serializers/target-profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default class TargetProfileSerializer extends ApplicationSerializer {
description: attributes.description,
'image-url': attributes['image-url'],
name: attributes.name,
'internal-name': attributes['internal-name'],
'owner-organization-id': attributes['owner-organization-id'],
},
},
Expand All @@ -25,6 +26,7 @@ export default class TargetProfileSerializer extends ApplicationSerializer {
}

const isUpdateMode = options?.update;

if (isUpdateMode) {
delete json.data.attributes['owner-organization-id'];
}
Expand Down
2 changes: 1 addition & 1 deletion admin/app/templates/authenticated/target-profiles/list.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<TargetProfiles::ListSummaryItems
@summaries={{@model}}
@id={{this.id}}
@name={{this.name}}
@internalName={{this.internalName}}
@categories={{this.categories}}
@triggerFiltering={{this.triggerFiltering}}
@onResetFilter={{this.onResetFilter}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@
</PixTableColumn>
<PixTableColumn @context={{context}} class="table__column--wide">
<:header>
Nom du profil cible
Nom interne du profil cible
</:header>
<:cell>
<LinkTo @route="authenticated.target-profiles.target-profile" @model={{row.id}}>
{{row.name}}
{{row.internalName}}
</LinkTo>
</:cell>
</PixTableColumn>
Expand Down
4 changes: 4 additions & 0 deletions admin/mirage/factories/target-profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export default Factory.extend({
return 'Mon Super Profil Cible Trop Biengggg';
},

internalName() {
return 'Mon Super Profil Cible interne Trop Biengggg';
},

createdAt() {
return new Date('2020-01-01');
},
Expand Down
3 changes: 2 additions & 1 deletion admin/mirage/handlers/target-profiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function attachTargetProfiles(schema, request) {
const params = JSON.parse(request.requestBody);
const targetProfilesToAttach = params['target-profile-ids'];
targetProfilesToAttach.forEach((targetProfileId) => {
schema.targetProfileSummaries.create({ name: `Profil ${targetProfileId}` });
schema.targetProfileSummaries.create({ internalName: `Profil ${targetProfileId}` });
});
return new Response(204);
}
Expand Down Expand Up @@ -36,6 +36,7 @@ function copyTargetProfile(schema, request) {
const { id } = schema.create('target-profile', {
...targetProfile.attrs,
name: '[Copie] ' + targetProfile.attrs.name,
internalName: '[Copie] ' + targetProfile.attrs.internalName,
});

return id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module('Acceptance | Organizations | Target profiles management', function (hook
test('should display organization target profiles', async function (assert) {
// given
const ownerOrganizationId = this.server.create('organization').id;
this.server.create('target-profile-summary', { name: 'Profil cible du ghetto' });
this.server.create('target-profile-summary', { internalName: 'Profil cible du ghetto' });

// when
const screen = await visit(`/organizations/${ownerOrganizationId}/target-profiles`);
Expand All @@ -36,6 +36,7 @@ module('Acceptance | Organizations | Target profiles management', function (hook

await fillByLabel('ID du ou des profil(s) cible(s)', '66');
await clickByName('Valider');

// then
assert.dom(await screen.findByLabelText('Profil cible')).includesText('66');
assert.dom(await within(parentInput).findByDisplayValue('')).hasAria('label', 'ID du ou des profil(s) cible(s)');
Expand All @@ -45,7 +46,7 @@ module('Acceptance | Organizations | Target profiles management', function (hook
// given
await authenticateAdminMemberWithRole({ isCertif: true })(server);
const ownerOrganizationId = this.server.create('organization').id;
this.server.create('target-profile-summary', { name: 'Profil cible du ghetto', ownerOrganizationId });
this.server.create('target-profile-summary', { internalName: 'Profil cible du ghetto', ownerOrganizationId });

// when
const screen = await visit(`/organizations/${ownerOrganizationId}/target-profiles`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ module('Acceptance | Target Profiles | List', function (hooks) {

test('it should list target profile summaries', async function (assert) {
// given
server.create('target-profile-summary', { id: 1, name: 'COUCOU', outdated: true });
server.create('target-profile-summary', { id: 2, name: 'CAVA', outdated: false });
server.create('target-profile-summary', { id: 1, internalName: 'COUCOU', outdated: true });
server.create('target-profile-summary', { id: 2, internalName: 'CAVA', outdated: false });

// when
const screen = await visit('/target-profiles/list');
Expand All @@ -67,7 +67,7 @@ module('Acceptance | Target Profiles | List', function (hooks) {
name: 'Profil Cible',
areas: [area],
});
server.create('target-profile-summary', { id: 1, name: 'Profil Cible', outdated: true });
server.create('target-profile-summary', { id: 1, internalName: 'Profil Cible', outdated: true });
const screen = await visit('/target-profiles/list');

// when
Expand Down Expand Up @@ -97,10 +97,12 @@ module('Acceptance | Target Profiles | List', function (hooks) {

test('it should display the current filter when target profiles are filtered by name', async function (assert) {
// when
const screen = await visit('/target-profiles/list?name=sav');
const screen = await visit('/target-profiles/list?internalName=sav');

// then
assert.dom(screen.getByRole('textbox', { name: 'Filtrer les profils cible par un nom' })).hasValue('sav');
assert
.dom(screen.getByRole('textbox', { name: 'Filtrer les profils cible par le nom interne' }))
.hasValue('sav');
});

test('it should display the current filter when target profiles are filtered by id', async function (assert) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module('Acceptance | Target Profile copy', function (hooks) {
server.create('target-profile', {
id: 1,
name: 'nom initial',
internalName: 'nom initial interne',
description: 'description initiale',
comment: 'commentaire initial',
category: 'OTHER',
Expand All @@ -36,9 +37,12 @@ module('Acceptance | Target Profile copy', function (hooks) {
// then
await screen.findByRole('button', { name: 'Valider' });
await clickByName('Valider');
await screen.findByRole('heading', { name: '[Copie] nom initial', level: 1 });
assert.dom(screen.getByRole('heading', { name: '[Copie] nom initial', level: 1 })).exists();
assert.dom(screen.getByRole('heading', { name: '[Copie] nom initial', level: 2 })).exists();

await screen.findByRole('heading', { name: '[Copie] nom initial interne', level: 1 });

assert.dom(screen.getByRole('heading', { name: '[Copie] nom initial interne', level: 1 })).exists();
assert.dom(screen.getByRole('heading', { name: '[Copie] nom initial interne', level: 2 })).exists();

await clickByName('1 · areaUn');
await clickByName('1.1 competenceUn');
assert.dom(screen.getByText('@tubeNiveauDeux : Mon tube de niveau deux')).exists();
Expand Down
Loading

0 comments on commit 7996272

Please sign in to comment.