Skip to content

Commit

Permalink
[Training] enhances registration
Browse files Browse the repository at this point in the history
  • Loading branch information
Elorfin committed Apr 17, 2023
1 parent 6f10d94 commit 6f0ee2a
Show file tree
Hide file tree
Showing 142 changed files with 4,306 additions and 2,304 deletions.
4 changes: 2 additions & 2 deletions VERSION.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
13.7.0
13.8.0
882ae08e7824ac27c201482ea148afe13bb3f6a7
13.7
13.8
6 changes: 6 additions & 0 deletions changelogs/changelog-13.8.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Trainings:
- Add a custom registration form (as for the user profile or the database resource) on the courses.
- Add a "Statistics" view to see the answers given to the registration
- Possibility to choose the roles to be assigned to the participants (tutors and learners) of the courses.
- Added a Participants view at course level to view registrations in all sessions of the course.
- Other small improvements and fixes to the Training tool
6 changes: 6 additions & 0 deletions changelogs/changelog-13.8.fr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Formations:
- Ajout d'un formulaire d'inscription personnalisé (comme pour le profil utilisateur ou la ressource Base de données) sur les formations.
- Ajout d'une vue "Statistiques" pour visualiser les réponses données au formulaire d'inscription.
- Possibilité de choisir les rôles à affecter aux participants (tuteurs et apprenants) des formations.
- Ajout d'une vue Participants au niveau de la formation pour visualiser les inscriptions dans toutes les sessions de la formation.
- Autres petites améliorations et correctifs sur l'outil Formation
23 changes: 16 additions & 7 deletions src/main/app/API/Crud.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,31 @@ public function __construct(
*
* @return object|null
*/
public function get(string $class, $id, string $idProp = 'id')
public function get(string $class, $id, string $idProp = 'id', ?array $options = [])
{
$object = null;

if ('id' === $idProp) {
if (!is_numeric($id) && property_exists($class, 'uuid')) {
return $this->om->getRepository($class)->findOneBy(['uuid' => $id]);
$object = $this->om->getRepository($class)->findOneBy(['uuid' => $id]);
} else {
$object = $this->om->getRepository($class)->findOneBy(['id' => $id]);
}
} else {
$identifiers = $this->schema->getIdentifiers($class);
if (!in_array($idProp, $identifiers)) {
throw new \LogicException(sprintf('You can only get entities with an identifier property (identifiers: %s).', implode(', ', $identifiers)));
}

return $this->om->getRepository($class)->findOneBy(['id' => $id]);
$object = $this->om->getRepository($class)->findOneBy([$idProp => $id]);
}

$identifiers = $this->schema->getIdentifiers($class);
if (!in_array($idProp, $identifiers)) {
throw new \LogicException(sprintf('You can only get entities with an identifier property (identifiers: %s).', implode(', ', $identifiers)));
if ($object && !in_array(static::NO_PERMISSIONS, $options)) {
// creates the entity if allowed
$this->checkPermission('OPEN', $object, [], true);
}

return $this->om->getRepository($class)->findOneBy([$idProp => $id]);
return $object;
}

public function find(string $class, $data)
Expand Down
4 changes: 1 addition & 3 deletions src/main/app/Entity/Meta/Name.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ trait Name
{
/**
* @ORM\Column(name="entity_name")
*
* @var string
*/
protected $name;
protected ?string $name = null;

public function getName(): ?string
{
Expand Down
14 changes: 0 additions & 14 deletions src/main/app/Entity/Parameters/AbstractParameters.php

This file was deleted.

10 changes: 6 additions & 4 deletions src/main/app/Resources/modules/content/components/sections.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ const Section = props =>

{typeof props.icon !== 'string' && props.icon}

{props.title}
{props.subtitle &&
<small>{props.subtitle}</small>
}
<span role="presentation">
{props.title}
{props.subtitle &&
<small>{props.subtitle}</small>
}
</span>

{(props.status || 0 !== props.actions.length) &&
<div className="panel-actions">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const ContentTitle = props =>

{props.children}

<span className={classes(
<span role="presentation" className={classes(
props.align && `text-${props.align}`
)}>
{props.title}
Expand Down
10 changes: 8 additions & 2 deletions src/main/app/Resources/modules/content/details/prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {DataProperty} from '#/main/app/data/types/prop-types'
const DataDetailsProperty = {
propTypes: merge({}, DataProperty.propTypes, {
hideLabel: T.bool,
displayed: T.bool
displayed: T.oneOfType([
T.bool,
T.func // a function that receives the whole details data and returns a bool
])
}),
defaultProps: merge({}, DataProperty.defaultProps, {
hideLabel: false,
Expand All @@ -21,7 +24,10 @@ const DataDetailsSection = {
title: T.string.isRequired,
className: T.string,
primary: T.bool,
displayed: T.bool,
displayed: T.oneOfType([
T.bool,
T.func // a function that receives the whole details data and returns a bool
]),
defaultOpened: T.bool,
fields: T.arrayOf(T.shape(
DataDetailsProperty.propTypes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,13 @@ const FormData = (props) => {
<FormSections
level={hLevel}
displayLevel={hDisplay}
defaultOpened={openedSection ? (openedSection.id || toKey(openedSection.title)) : undefined}
defaultOpened={openedSection ? getSectionId(openedSection, props.id) : undefined}
>
{otherSections.map(section => (
<FormSection
id={`${getSectionId(section, props.id)}-section`}
id={getSectionId(section, props.id)}
className={section.className}
key={section.id || toKey(section.title)}
key={getSectionId(section, props.id)}
icon={section.icon}
title={section.title}
subtitle={section.subtitle}
Expand All @@ -182,7 +182,7 @@ const FormData = (props) => {
actions={section.actions}
>
<FormFieldset
id={getSectionId(section, props.id)}
id={`${getSectionId(section, props.id)}-fieldset`}
fill={true}
className="panel-body"
mode={props.mode}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {Alert} from '#/main/app/alert/components/alert'
import {DataInput} from '#/main/app/data/components/input'
import {DataDisplay} from '#/main/app/data/components/display'
import {toKey} from '#/main/core/scaffolding/text'
import {ContentHtml} from '#/main/app/content/components/html'

/**
* ATTENTION : as it's only be used in the FormData component, the `fields` are not defaulted by the component.
Expand Down Expand Up @@ -127,7 +128,9 @@ class FormFieldset extends Component {
const helps = Array.isArray(this.props.help) ? this.props.help : [this.props.help]

return helps.map(help =>
<Alert key={toKey(help)} type="info">{help}</Alert>
<Alert key={toKey(help)} type="info">
<ContentHtml>{help}</ContentHtml>
</Alert>
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {Fragment} from 'react'
import {PropTypes as T} from 'prop-types'
import get from 'lodash/get'
import merge from 'lodash/merge'
import omit from 'lodash/omit'

Expand All @@ -15,7 +16,9 @@ import {FormData} from '#/main/app/content/form/containers/data'
const SectionParameters = props =>
<FormSection
{...omit(props, ['name', 'dataPart', 'index', 'fields', 'remove'])}
title={props.title || trans('profile_facet_section')}
icon={props.icon ? `fa fa-fw fa-${props.icon}` : undefined}
title={props.title || trans('facet_section')}
subtitle={props.description}
className="embedded-form-section"
actions={[
{
Expand All @@ -26,8 +29,8 @@ const SectionParameters = props =>
callback: props.remove,
dangerous: true,
confirm: {
title: trans('profile_remove_section'),
message: trans('profile_remove_section_question')
title: trans('facet_remove_section'),
message: trans('facet_remove_section_question')
}
}
]}
Expand All @@ -39,27 +42,56 @@ const SectionParameters = props =>
dataPart={`${props.dataPart}[${props.index}]`}
definition={[
{
icon: 'fa fa-fw fa-cog',
id: 'general',
title: trans('general'),
primary: true,
fields: [
{
name: 'title',
type: 'string',
label: trans('title'),
required: true
label: trans('title')
}, {
name: 'meta.description',
type: 'string',
label: trans('description')
}, {
name: 'fields',
type: 'fields',
label: trans('fields_list'),
required: true,
options: {
placeholder: trans('profile_section_no_field'),
placeholder: trans('facet_section_no_field'),
fields: props.fields,
min: 1
}
}
]
}, {
id: 'help',
icon: 'fa fa-fw fa-circle-question',
title: trans('help'),
fields: [
{
name: 'help',
type: 'html',
label: trans('message')
}
]
}, {
id: 'display',
icon: 'fa fa-fw fa-desktop',
title: trans('display_parameters'),
fields: [
{
name: 'display.icon',
type: 'icon',
label: trans('icon')
}, {
name: 'display.order',
type: 'number',
label: trans('order')
}
]
}
]}
/>
Expand All @@ -71,6 +103,7 @@ SectionParameters.propTypes = {
dataPart: T.string.isRequired,
icon: T.string,
title: T.string,
description: T.string,
fields: T.array,
remove: T.func.isRequired
}
Expand All @@ -85,7 +118,9 @@ const FormParameters = (props) =>
index={sectionIndex}
name={props.name}
dataPart={props.dataPart}
icon={get(section, 'display.icon')}
title={section.title}
description={get(section, 'meta.description')}
fields={props.fields}
remove={() => {
const updatedSections = merge([], props.sections)
Expand All @@ -112,15 +147,15 @@ const FormParameters = (props) =>
{0 === props.sections.length &&
<ContentPlaceholder
size="lg"
icon="fa fa-face-frown"
title={trans('profile_facet_no_section')}
title={trans('facet_no_section')}
help={trans('facet_no_section_help')}
/>
}

<Button
type={CALLBACK_BUTTON}
className="btn btn-block btn-emphasis component-container"
label={trans('profile_facet_section_add')}
label={trans('facet_section_add')}
callback={() => props.update(props.name, props.dataPart, [].concat(props.sections, [{
id: makeId(),
title: '',
Expand Down
22 changes: 22 additions & 0 deletions src/main/app/Resources/modules/content/form/parameters/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ function formatSections(sections, allFields, dataPath = null, hasConfidentialRig
function formatSection(section, allFields, dataPath = null, hasConfidentialRights = false, hasLockedRights = false) {
const sectionDefinition = cloneDeep(section)

sectionDefinition.icon = get(section, 'display.icon') ? `fa fa-fw fa-${get(section, 'display.icon')}` : undefined
sectionDefinition.subtitle = get(section, 'meta.description')
sectionDefinition.fields = sectionDefinition.fields
.filter(field => !get(field, 'restrictions.metadata') || hasConfidentialRights)
.map(f => formatField(f, allFields, dataPath, hasLockedRights))
Expand Down Expand Up @@ -46,6 +48,25 @@ function formatField(fieldDef, allFields, dataPath = null, hasLockedRights = fal
return field
}

function formatListField(fieldDef, allFields, dataPath = null) {
const field = {
name: dataPath ? `${dataPath}.${fieldDef.id}` : fieldDef.id,
type: fieldDef.type,
label: fieldDef.label,
help: fieldDef.help,
options: fieldDef.options ? cloneDeep(fieldDef.options) : {}
}

if (fieldDef.type === 'choice') {
field.options.choices = fieldDef.options.choices ?
fieldDef.options.choices.reduce((acc, choice) => Object.assign(acc, {
[choice.value]: choice.value
}), {}) : {}
}

return field
}

function isFieldDisplayed(fieldDef, allFields, data) {
if (!isEmpty(get(fieldDef, 'display.condition'))) {
const parentField = allFields.find(f => f.id === fieldDef.display.condition.field)
Expand Down Expand Up @@ -78,5 +99,6 @@ function isFieldDisplayed(fieldDef, allFields, data) {
export {
formatSections,
formatField,
formatListField,
isFieldDisplayed
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, {createElement} from 'react'
import {PropTypes as T} from 'prop-types'
import get from 'lodash/get'
import merge from 'lodash/merge'
Expand Down Expand Up @@ -39,7 +39,7 @@ const DataCellContent = props => {
cellRendering = props.column.placeholder
} else if (get(props.definition, 'components.table', null)) {
// use custom component defined in the type definition
cellRendering = React.createElement(props.definition.components.table, merge({}, props.column.options || {}, {
cellRendering = createElement(props.definition.components.table, merge({}, props.column.options || {}, {
id: toKey(props.column.name + '-' + props.rowData.id),
label: props.column.label,
data: cellData
Expand Down
Loading

0 comments on commit 6f0ee2a

Please sign in to comment.