diff --git a/CHANGELOG.md b/CHANGELOG.md
index 940d7e05c..233c1f51b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,7 +11,14 @@ and this project adheres to
## Unreleased
-
+* [main] Add editableByUser field to locationType entity, adapt the admin template and add this condition in the location-type endpoint (see https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/297)
+* [main] Add mainLocation field to User entity and add it in user form type
+* rewrite page which allow to select activity
+* [main] Add mainLocation field to User entity and add it in user form type
+* [course list in person context] show full username/label for ref
+* [accompanying period work] remove the possibility to generate document from an accompanying period work
+* vuejs: add validation on required fields for AddPerson, Address and Location components
+* vuejs: treat 422 validation errors in locations and AddPerson components
## Test releases
diff --git a/src/Bundle/ChillActivityBundle/Resources/public/chill/chillactivity.scss b/src/Bundle/ChillActivityBundle/Resources/public/chill/chillactivity.scss
index 275f67950..8b88f0e78 100644
--- a/src/Bundle/ChillActivityBundle/Resources/public/chill/chillactivity.scss
+++ b/src/Bundle/ChillActivityBundle/Resources/public/chill/chillactivity.scss
@@ -9,8 +9,9 @@ div.new-activity-select-type {
display: flex;
flex-direction: row;
flex-wrap: wrap;
- justify-content: center;
+ justify-content: flex-start;
gap: 12px;
+ margin-bottom: 30px;
div.bloc {
width: 200px;
@@ -27,26 +28,26 @@ div.new-activity-select-type {
// precise dashboard specific details
p.date-label {
- display: inline-block;
- margin: 0 0.5em 0 0;
- font-weight: 700;
- font-size: 18pt;
+ display: inline-block;
+ margin: 0 0.5em 0 0;
+ font-weight: 700;
+ font-size: 18pt;
}
div.dashboard,
h2.badge-title {
- ul.list-content {
- font-size: 70%;
- list-style-type: none;
- padding-left: 0;
- margin: 0;
- li {
- margin-bottom: 0.2em;
- // exception: change bg color for action badges above dashboard
- .bg-light {
- background-color: $chill-light-gray !important;
- }
- }
- }
+ ul.list-content {
+ font-size: 70%;
+ list-style-type: none;
+ padding-left: 0;
+ margin: 0;
+ li {
+ margin-bottom: 0.2em;
+ // exception: change bg color for action badges above dashboard
+ .bg-light {
+ background-color: $chill-light-gray !important;
+ }
+ }
+ }
}
//// ACTIVITY SHOW AND FORM PAGES
diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/App.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/App.vue
index 2fb9d022d..4809a5fae 100644
--- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/App.vue
+++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/App.vue
@@ -11,7 +11,7 @@ import Location from './components/Location.vue';
export default {
name: "App",
- props: ['hasSocialIssues', 'hasLocation', 'hasPerson'],
+ props: ['hasSocialIssues', 'hasLocation', 'hasPerson'],
components: {
ConcernedGroups,
SocialIssuesAcc,
diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue
index b8249ccc5..91c5db839 100644
--- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue
+++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue
@@ -24,7 +24,7 @@
v-model="location"
>
-
+
diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location/NewLocation.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location/NewLocation.vue
index 35bf9a065..c9a1c233c 100644
--- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location/NewLocation.vue
+++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location/NewLocation.vue
@@ -18,15 +18,6 @@
@@ -81,7 +78,8 @@
import Modal from 'ChillMainAssets/vuejs/_components/Modal.vue';
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
import { mapState } from "vuex";
-import { getLocationTypes, postLocation } from "../../api";
+import { getLocationTypes } from "../../api";
+import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
export default {
name: "NewLocation",
@@ -89,7 +87,7 @@ export default {
Modal,
AddAddress,
},
- props: ['locations'],
+ props: ['availableLocations'],
data() {
return {
errors: [],
@@ -223,7 +221,6 @@ export default {
},
saveNewLocation() {
if (this.checkForm()) {
- console.log('saveNewLocation', this.selected);
let body = {
type: 'location',
name: this.selected.name,
@@ -242,23 +239,28 @@ export default {
}
});
}
- postLocation(body)
- .then(
- location => new Promise(resolve => {
- this.locations.push(location);
- this.$store.dispatch('updateLocation', location);
- resolve();
- this.modal.showModal = false;
- })
- ).catch(
- err => {
- this.errors.push(err.message);
+
+ makeFetch('POST', '/api/1.0/main/location.json', body)
+ .then(response => {
+ this.$store.dispatch('addAvailableLocationGroup', {
+ locationGroup: 'Localisations nouvellement créées',
+ locations: [response]
+ });
+ this.$store.dispatch('updateLocation', response);
+ this.modal.showModal = false;
+ })
+ .catch((error) => {
+ if (error.name === 'ValidationException') {
+ for (let v of error.violations) {
+ this.errors.push(v);
+ }
+ } else {
+ this.errors.push('An error occurred');
}
- );
+ })
};
},
submitNewAddress(payload) {
- console.log('submitNewAddress', payload);
this.selected.addressId = payload.addressId;
this.addAddress.context.addressId = payload.addressId;
this.addAddress.context.edit = true;
diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/index.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/index.js
index 66657df47..b7a5c791b 100644
--- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/index.js
+++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/index.js
@@ -12,7 +12,11 @@ const hasLocation = document.querySelector('#location') !== null;
const hasPerson = document.querySelector('#add-persons') !== null;
const app = createApp({
- template: ` `,
+ template: ` `,
data() {
return {
hasSocialIssues,
diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js
index 4bf70b006..f94381fc2 100644
--- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js
+++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js
@@ -240,6 +240,9 @@ const store = createStore({
});
commit("updateActionsSelected", payload);
},
+ addAvailableLocationGroup({ commit }, payload) {
+ commit("addAvailableLocationGroup", payload);
+ },
addPersonsInvolved({ commit }, payload) {
//console.log('### action addPersonsInvolved', payload.result.type);
switch (payload.result.type) {
diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/selectType.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/selectType.html.twig
index 4120d8285..90237bbcc 100644
--- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/selectType.html.twig
+++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/selectType.html.twig
@@ -25,7 +25,7 @@
'activityData': activityData
}) }}">
-
+
{{ activityType.name|localize_translatable_string }}
diff --git a/src/Bundle/ChillMainBundle/Controller/LocationTypeApiController.php b/src/Bundle/ChillMainBundle/Controller/LocationTypeApiController.php
index 1c7fbdb89..ce1b5e825 100644
--- a/src/Bundle/ChillMainBundle/Controller/LocationTypeApiController.php
+++ b/src/Bundle/ChillMainBundle/Controller/LocationTypeApiController.php
@@ -24,6 +24,7 @@ class LocationTypeApiController extends ApiController
$query->andWhere(
$query->expr()->andX(
$query->expr()->eq('e.availableForUsers', "'TRUE'"),
+ $query->expr()->eq('e.editableByUsers', "'TRUE'"),
$query->expr()->eq('e.active', "'TRUE'"),
)
);
diff --git a/src/Bundle/ChillMainBundle/Entity/LocationType.php b/src/Bundle/ChillMainBundle/Entity/LocationType.php
index 9081304c8..2fd4dbfea 100644
--- a/src/Bundle/ChillMainBundle/Entity/LocationType.php
+++ b/src/Bundle/ChillMainBundle/Entity/LocationType.php
@@ -67,6 +67,12 @@ class LocationType
*/
private ?string $defaultFor = null;
+ /**
+ * @ORM\Column(type="boolean")
+ * @Serializer\Groups({"read"})
+ */
+ private bool $editableByUsers = true;
+
/**
* @ORM\Id
* @ORM\GeneratedValue
@@ -107,6 +113,11 @@ class LocationType
return $this->defaultFor;
}
+ public function getEditableByUsers(): ?bool
+ {
+ return $this->editableByUsers;
+ }
+
public function getId(): ?int
{
return $this->id;
@@ -152,6 +163,13 @@ class LocationType
return $this;
}
+ public function setEditableByUsers(bool $editableByUsers): self
+ {
+ $this->editableByUsers = $editableByUsers;
+
+ return $this;
+ }
+
public function setTitle(array $title): self
{
$this->title = $title;
diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php
index 0c3194fba..76fd7196d 100644
--- a/src/Bundle/ChillMainBundle/Entity/User.php
+++ b/src/Bundle/ChillMainBundle/Entity/User.php
@@ -97,6 +97,11 @@ class User implements AdvancedUserInterface
*/
private ?Center $mainCenter = null;
+ /**
+ * @ORM\ManyToOne(targetEntity=Location::class)
+ */
+ private ?Location $mainLocation = null;
+
/**
* @ORM\ManyToOne(targetEntity=Scope::class)
*/
@@ -228,6 +233,11 @@ class User implements AdvancedUserInterface
return $this->mainCenter;
}
+ public function getMainLocation(): ?Location
+ {
+ return $this->mainLocation;
+ }
+
public function getMainScope(): ?Scope
{
return $this->mainScope;
@@ -405,6 +415,13 @@ class User implements AdvancedUserInterface
return $this;
}
+ public function setMainLocation(?Location $mainLocation): User
+ {
+ $this->mainLocation = $mainLocation;
+
+ return $this;
+ }
+
public function setMainScope(?Scope $mainScope): User
{
$this->mainScope = $mainScope;
diff --git a/src/Bundle/ChillMainBundle/Form/LocationTypeType.php b/src/Bundle/ChillMainBundle/Form/LocationTypeType.php
index aa096b3e6..2ecaa56c8 100644
--- a/src/Bundle/ChillMainBundle/Form/LocationTypeType.php
+++ b/src/Bundle/ChillMainBundle/Form/LocationTypeType.php
@@ -39,6 +39,17 @@ final class LocationTypeType extends AbstractType
'expanded' => true,
]
)
+ ->add(
+ 'editableByUsers',
+ ChoiceType::class,
+ [
+ 'choices' => [
+ 'Yes' => true,
+ 'No' => false,
+ ],
+ 'expanded' => true,
+ ]
+ )
->add(
'addressRequired',
ChoiceType::class,
diff --git a/src/Bundle/ChillMainBundle/Form/UserType.php b/src/Bundle/ChillMainBundle/Form/UserType.php
index 58f053ac1..6662d0bab 100644
--- a/src/Bundle/ChillMainBundle/Form/UserType.php
+++ b/src/Bundle/ChillMainBundle/Form/UserType.php
@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\MainBundle\Form;
use Chill\MainBundle\Entity\Center;
+use Chill\MainBundle\Entity\Location;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\UserJob;
use Chill\MainBundle\Templating\TranslatableStringHelper;
@@ -75,6 +76,22 @@ class UserType extends AbstractType
'choice_label' => function (UserJob $c) {
return $this->translatableStringHelper->localize($c->getLabel());
},
+ ])
+ ->add('mainLocation', EntityType::class, [
+ 'label' => 'Main location',
+ 'required' => false,
+ 'placeholder' => 'choose a location',
+ 'class' => Location::class,
+ 'choice_label' => function (Location $l) {
+ return $this->translatableStringHelper->localize($l->getLocationType()->getTitle()) . ' - ' . $l->getName();
+ },
+ 'query_builder' => static function (EntityRepository $er) {
+ $qb = $er->createQueryBuilder('l');
+ $qb->orderBy('l.locationType');
+ $qb->where('l.availableForUsers = TRUE');
+
+ return $qb;
+ },
]);
if ($options['is_creation']) {
diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss
index 1d2a52d89..4829f9634 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss
+++ b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss
@@ -423,3 +423,8 @@ span.item-key {
background-color: #0000000a;
//text-decoration: dotted underline;
}
+
+// increase toast message z-index (above all modals)
+div.v-toast {
+ z-index: 10000!important;
+}
\ No newline at end of file
diff --git a/src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.js b/src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.js
index 96a95ad93..5ad119858 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.js
+++ b/src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.js
@@ -85,7 +85,9 @@ const fetchScopes = () => {
const ValidationException = (response) => {
const error = {};
error.name = 'ValidationException';
- error.violations = response.violations.map((violation) => `${violation.title}`);
+ error.violations = response.violations.map((violation) => `${violation.title}: ${violation.propertyPath}`);
+ error.titles = response.violations.map((violation) => violation.title);
+ error.propertyPaths = response.violations.map((violation) => violation.propertyPath);
return error;
}
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue
index ecc7b7e38..1f62269de 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue
@@ -98,6 +98,8 @@
v-bind:defaultz="this.defaultz"
v-bind:entity="this.entity"
v-bind:flag="this.flag"
+ v-bind:errors="this.errors"
+ v-bind:checkErrors="this.checkErrors"
@getCities="getCities"
@getReferenceAddresses="getReferenceAddresses">
@@ -123,6 +125,8 @@
v-bind:defaultz="this.defaultz"
v-bind:entity="this.entity"
v-bind:flag="this.flag"
+ v-bind:errors="this.errors"
+ v-bind:checkErrors="this.checkErrors"
v-bind:insideModal="false"
@getCities="getCities"
@getReferenceAddresses="getReferenceAddresses">
@@ -256,8 +260,10 @@ export default {
editPane: false,
datePane: false,
loading: false,
- success: false
+ success: false,
+ dirty: false
},
+ errors: [],
defaultz: {
button: {
text: { create: 'add_an_address_title', edit: 'edit_address' },
@@ -529,6 +535,23 @@ export default {
});
},
+ checkErrors() {
+ this.errors = [];
+ if (this.flag.dirty) {
+ if (this.entity.selected.country === null) {
+ this.errors.push("Un pays doit être sélectionné.");
+ }
+ if (Object.keys(this.entity.selected.city).length === 0) {
+ this.errors.push("Une ville doit être sélectionnée.");
+ }
+ if (!this.entity.selected.isNoAddress) {
+ if (this.entity.selected.address.street === null || this.entity.selected.address.streetNumber === null) {
+ this.errors.push("Une adresse doit être sélectionnée.");
+ }
+ }
+ }
+ },
+
/*
* Make form ready for new changes
*/
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue
index 6d9c32524..12e45d0b7 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue
@@ -12,6 +12,7 @@
@search-change="listenInputSearch"
ref="addressSelector"
@select="selectAddress"
+ @remove="remove"
name="field"
track-by="id"
label="value"
@@ -56,7 +57,7 @@ import { searchReferenceAddresses, fetchReferenceAddresses } from '../../api.js'
export default {
name: 'AddressSelection',
components: { VueMultiselect },
- props: ['entity', 'context', 'updateMapCenter'],
+ props: ['entity', 'context', 'updateMapCenter', 'flag', 'checkErrors'],
data() {
return {
value: this.context.edit ? this.entity.address.addressReference : null,
@@ -109,6 +110,13 @@ export default {
this.entity.selected.address.streetNumber = value.streetNumber;
this.entity.selected.writeNew.address = false;
this.updateMapCenter(value.point);
+ this.flag.dirty = true;
+ this.checkErrors();
+ },
+ remove() {
+ this.flag.dirty = true;
+ this.entity.selected.address = {};
+ this.checkErrors();
},
listenInputSearch(query) {
//console.log('listenInputSearch', query, this.isAddressSelectorOpen);
@@ -149,6 +157,8 @@ export default {
this.entity.selected.address.street = addr.street;
this.entity.selected.address.streetNumber = addr.number;
this.entity.selected.writeNew.address = true;
+ this.flag.dirty = true;
+ this.checkErrors();
}
},
splitAddress(address) {
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue
index 5191b3a31..4883957bb 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue
@@ -7,6 +7,7 @@
@search-change="listenInputSearch"
ref="citySelector"
@select="selectCity"
+ @remove="remove"
name="field"
track-by="id"
label="value"
@@ -55,12 +56,12 @@ import { searchCities, fetchCities } from '../../api.js';
export default {
name: 'CitySelection',
components: { VueMultiselect },
- props: ['entity', 'context', 'focusOnAddress', 'updateMapCenter'],
+ props: ['entity', 'context', 'focusOnAddress', 'updateMapCenter', 'flag', 'checkErrors'],
emits: ['getReferenceAddresses'],
data() {
return {
value: this.context.edit ? this.entity.address.postcode : null,
- isLoading: false
+ isLoading: false,
}
},
computed: {
@@ -123,6 +124,13 @@ export default {
if (value.center) {
this.updateMapCenter(value.center);
}
+ this.flag.dirty = true;
+ this.checkErrors();
+ },
+ remove() {
+ this.flag.dirty = true;
+ this.entity.selected.city = {};
+ this.checkErrors();
},
listenInputSearch(query) {
if (query.length > 2) {
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CountrySelection.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CountrySelection.vue
index c1b1d1b55..09ba8421d 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CountrySelection.vue
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CountrySelection.vue
@@ -12,7 +12,9 @@
:select-label="$t('multiselect.select_label')"
:deselect-label="$t('multiselect.deselect_label')"
:selected-label="$t('multiselect.selected_label')"
- @select="selectCountry">
+ @select="selectCountry"
+ @remove="remove"
+ >
@@ -23,7 +25,7 @@ import VueMultiselect from 'vue-multiselect';
export default {
name: 'CountrySelection',
components: { VueMultiselect },
- props: ['context', 'entity'],
+ props: ['context', 'entity', 'flag', 'checkErrors'],
emits: ['getCities'],
data() {
return {
@@ -34,14 +36,13 @@ export default {
},
computed: {
sortedCountries() {
- //console.log('sorted countries');
const countries = this.entity.loaded.countries;
let sortedCountries = [];
sortedCountries.push(...countries.filter(c => c.countryCode === 'FR'))
sortedCountries.push(...countries.filter(c => c.countryCode === 'BE'))
sortedCountries.push(...countries.filter(c => c.countryCode !== 'FR').filter(c => c.countryCode !== 'BE'))
return sortedCountries;
- }
+ },
},
mounted() {
this.init();
@@ -50,6 +51,7 @@ export default {
init() {
if (this.value !== undefined) {
this.selectCountry(this.value);
+ this.flag.dirty = false;
}
},
selectCountryByCode(countryCode) {
@@ -62,7 +64,13 @@ export default {
//console.log('select country', value);
this.entity.selected.country = value;
this.$emit('getCities', value);
- }
+ this.checkErrors();
+ },
+ remove() {
+ this.flag.dirty = true;
+ this.entity.selected.country = null;
+ this.checkErrors();
+ },
}
};
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/EditPane.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/EditPane.vue
index af1263b43..486d28e73 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/EditPane.vue
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/EditPane.vue
@@ -7,6 +7,12 @@
Loading...
+
+
{{ $t('select_an_address_title') }}
@@ -25,6 +31,8 @@
@@ -33,13 +41,17 @@
v-bind:context="context"
v-bind:focusOnAddress="focusOnAddress"
v-bind:updateMapCenter="updateMapCenter"
+ v-bind:flag="flag"
+ v-bind:checkErrors="checkErrors"
@getReferenceAddresses="$emit('getReferenceAddresses', selected.city)">
+ v-bind:updateMapCenter="updateMapCenter"
+ v-bind:flag="flag"
+ v-bind:checkErrors="checkErrors">
@@ -99,7 +111,9 @@ export default {
'flag',
'entity',
'errorMsg',
- 'insideModal'
+ 'insideModal',
+ 'errors',
+ 'checkErrors',
],
emits: ['getCities', 'getReferenceAddresses'],
data() {
@@ -128,7 +142,7 @@ export default {
get() {
return this.entity.selected.isNoAddress;
}
- }
+ },
},
methods: {
focusOnAddress() {
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue
index d4342fdee..8c93eec71 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue
@@ -90,7 +90,7 @@ export default {
OnTheFlyThirdparty,
OnTheFlyCreate
},
- props: ['type', 'id', 'action', 'buttonText', 'displayBadge', 'parent'],
+ props: ['type', 'id', 'action', 'buttonText', 'displayBadge', 'parent', 'canCloseModal'],
emits: ['saveFormOnTheFly'],
data() {
return {
@@ -162,7 +162,20 @@ export default {
return 'entity-' + this.type + ' badge-' + this.type;
}
},
+ watch: {
+ canCloseModal: {
+ handler: function(val, oldVal) {
+ if (val) {
+ this.closeModal();
+ }
+ },
+ deep: true
+ }
+ },
methods: {
+ closeModal() {
+ this.modal.showModal = false;
+ },
openModal() {
//console.log('## OPEN ON THE FLY MODAL');
//console.log('## type:', this.type, ', action:', this.action);
@@ -200,8 +213,6 @@ export default {
// pass datas to parent
this.$emit('saveFormOnTheFly', { type: type, data: data });
-
- this.modal.showModal = false;
},
buildLocation(id, type) {
if (type === 'person') {
diff --git a/src/Bundle/ChillMainBundle/Resources/views/LocationType/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/LocationType/index.html.twig
index 5402d5e89..22cb6de44 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/LocationType/index.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/LocationType/index.html.twig
@@ -8,6 +8,7 @@
{{ 'Title'|trans }}
{{ 'Available for users'|trans }}
+ {{ 'Editable by users'|trans }}
{{ 'Address required'|trans }}
{{ 'Contact data'|trans }}
{{ 'Active'|trans }}
@@ -25,6 +26,13 @@
{%- endif -%}
+
+ {%- if entity.editableByUsers -%}
+
+ {%- else -%}
+
+ {%- endif -%}
+
{{ entity.addressRequired|trans }}
{{ entity.contactData|trans }}
diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php
index 975a7c9f8..365433ef3 100644
--- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php
+++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php
@@ -58,7 +58,7 @@ class UserNormalizer implements ContextAwareNormalizerInterface, NormalizerAware
);
$locationContext = array_merge(
$context,
- ['docgen:expects' => Location::class, 'groups' => 'dogen:read']
+ ['docgen:expects' => Location::class, 'groups' => 'docgen:read']
);
if (null === $user && 'docgen' === $format) {
@@ -67,6 +67,7 @@ class UserNormalizer implements ContextAwareNormalizerInterface, NormalizerAware
'main_center' => $this->normalizer->normalize(null, $format, $centerContext),
'main_scope' => $this->normalizer->normalize(null, $format, $scopeContext),
'current_location' => $this->normalizer->normalize(null, $format, $locationContext),
+ 'main_location' => $this->normalizer->normalize(null, $format, $locationContext),
]);
}
@@ -84,6 +85,7 @@ class UserNormalizer implements ContextAwareNormalizerInterface, NormalizerAware
if ('docgen' === $format) {
$data['current_location'] = $this->normalizer->normalize($user->getCurrentLocation(), $format, $locationContext);
+ $data['main_location'] = $this->normalizer->normalize($user->getMainLocation(), $format, $locationContext);
}
return $data;
diff --git a/src/Bundle/ChillMainBundle/migrations/Version20220112150413.php b/src/Bundle/ChillMainBundle/migrations/Version20220112150413.php
new file mode 100644
index 000000000..c38649711
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/migrations/Version20220112150413.php
@@ -0,0 +1,36 @@
+addSql('ALTER TABLE chill_main_location_type DROP editableByUsers');
+ }
+
+ public function getDescription(): string
+ {
+ return 'Add editableByUsers field to ChillMain/LocationType';
+ }
+
+ public function up(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE chill_main_location_type ADD editableByUsers BOOLEAN DEFAULT TRUE');
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/migrations/Version20220112161136.php b/src/Bundle/ChillMainBundle/migrations/Version20220112161136.php
new file mode 100644
index 000000000..89abc11d7
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/migrations/Version20220112161136.php
@@ -0,0 +1,40 @@
+addSql('ALTER TABLE users DROP CONSTRAINT FK_1483A5E9DB622A42');
+ $this->addSql('DROP INDEX IDX_1483A5E9DB622A42');
+ $this->addSql('ALTER TABLE users DROP mainLocation_id');
+ }
+
+ public function getDescription(): string
+ {
+ return 'Add mainLocation to User';
+ }
+
+ public function up(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE users ADD mainLocation_id INT DEFAULT NULL');
+ $this->addSql('ALTER TABLE users ADD CONSTRAINT FK_1483A5E9DB622A42 FOREIGN KEY (mainLocation_id) REFERENCES chill_main_location (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('CREATE INDEX IDX_1483A5E9DB622A42 ON users (mainLocation_id)');
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml
index 2e726a48c..af0dc77d7 100644
--- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml
@@ -202,6 +202,7 @@ Location: Localisation
Location type list: Liste des types de localisation
Create a new location type: Créer un nouveau type de localisation
Available for users: Disponible aux utilisateurs
+Editable by users: Éditable par les utilisateurs
Address required: Adresse requise?
Contact data: Données de contact?
optional: optionnel
diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php
index 73b83f246..91e430a2f 100644
--- a/src/Bundle/ChillPersonBundle/Entity/Person.php
+++ b/src/Bundle/ChillPersonBundle/Entity/Person.php
@@ -151,7 +151,6 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
* @var DateTime
*
* @ORM\Column(type="date", nullable=true)
- * @Assert\Date
* @Birthdate
*/
private $birthdate;
@@ -259,7 +258,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
* @var string
*
* @ORM\Column(type="string", length=255)
- * @Assert\NotBlank
+ * @Assert\NotBlank(message="The firstname cannot be empty")
* @Assert\Length(
* max=255,
* )
@@ -282,7 +281,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
* @var string
*
* @ORM\Column(type="string", length=9, nullable=true)
- * @Assert\NotNull
+ * @Assert\NotNull(message="The gender must be set")
*/
private $gender;
@@ -326,7 +325,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
* @var string
*
* @ORM\Column(type="string", length=255)
- * @Assert\NotBlank
+ * @Assert\NotBlank(message="The lastname cannot be empty")
* @Assert\Length(
* max=255,
* )
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/badge.scss b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/badge.scss
index 46c13d152..e8a98bc80 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/badge.scss
+++ b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/badge.scss
@@ -184,5 +184,9 @@ div[class*='activity-'] {
background-color: $chill-ll-gray;
color: $chill-blue;
}
+ &.bg-confidential {
+ background-color: $chill-ll-gray;
+ color: $chill-red;
+ }
}
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue
index 97bda5fc5..b5e5d3221 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue
+++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue
@@ -233,18 +233,6 @@
-
-
-
- {{ $t('Generate doc') }}
-
-
-
-
{{ $t('fix_these_errors') }}
@@ -458,10 +446,6 @@ export default {
submit() {
this.$store.dispatch('submit');
},
- beforeGenerateTemplate() {
- console.log('before generate');
- return Promise.resolve();
- },
saveFormOnTheFly(payload) {
console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
payload.target = 'resource';
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue
index f118671ed..59647e160 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue
+++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue
@@ -66,9 +66,10 @@
+ @saveFormOnTheFly="saveFormOnTheFly"
+ :canCloseModal="canCloseOnTheFlyModal">
@@ -91,8 +92,7 @@ import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
import PersonSuggestion from './AddPersons/PersonSuggestion';
import { searchEntities } from 'ChillPersonAssets/vuejs/_api/AddPersons';
-import { postPerson } from "ChillPersonAssets/vuejs/_api/OnTheFly";
-import { postThirdparty } from "ChillThirdPartyAssets/vuejs/_api/OnTheFly";
+import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
export default {
name: 'AddPersons',
@@ -120,7 +120,8 @@ export default {
suggested: [],
selected: [],
priorSuggestion: {}
- }
+ },
+ canCloseOnTheFlyModal: false
}
},
computed: {
@@ -267,22 +268,36 @@ export default {
saveFormOnTheFly({ type, data }) {
console.log('saveFormOnTheFly from addPersons, type', type, ', data', data);
if (type === 'person') {
- console.log('type person with', data);
- postPerson(data)
- .then(person => new Promise((resolve, reject) => {
- console.log('onthefly create: post person', person);
- this.newPriorSuggestion(person);
- resolve();
- }));
+ makeFetch('POST', '/api/1.0/person/person.json', data)
+ .then(response => {
+ this.newPriorSuggestion(response);
+ this.canCloseOnTheFlyModal = true;
+ })
+ .catch((error) => {
+ if (error.name === 'ValidationException') {
+ for (let v of error.violations) {
+ this.$toast.open({message: v });
+ }
+ } else {
+ this.$toast.open({message: 'An error occurred'});
+ }
+ })
}
else if (type === 'thirdparty') {
- console.log('type thirdparty with', data);
- postThirdparty(data)
- .then(thirdparty => new Promise((resolve, reject) => {
- console.log('onthefly create: post thirdparty', thirdparty);
- this.newPriorSuggestion(thirdparty);
- resolve();
- }));
+ makeFetch('POST', '/api/1.0/thirdparty/thirdparty.json', data)
+ .then(response => {
+ this.newPriorSuggestion(response);
+ this.canCloseOnTheFlyModal = true;
+ })
+ .catch((error) => {
+ if (error.name === 'ValidationException') {
+ for (let v of error.violations) {
+ this.$toast.open({message: v });
+ }
+ } else {
+ this.$toast.open({message: 'An error occurred'});
+ }
+ })
}
}
},
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue
index 799e5651b..9543da3bb 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue
+++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue
@@ -22,24 +22,45 @@
@@ -80,11 +101,17 @@
+
+
@@ -108,6 +135,7 @@ export default {
config: {
altNames: []
},
+ errors: []
}
},
computed: {
@@ -183,6 +211,18 @@ export default {
}
},
methods: {
+ checkErrors(e) {
+ this.errors = [];
+ if (!this.person.lastName) {
+ this.errors.push("Le nom ne doit pas être vide.");
+ }
+ if (!this.person.firstName) {
+ this.errors.push("Le prénom ne doit pas être vide.");
+ }
+ if (!this.person.gender) {
+ this.errors.push("Le genre doit être renseigné");
+ }
+ },
loadData() {
getPerson(this.id)
.then(person => new Promise((resolve, reject) => {
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig
index a38aa913f..96775ca70 100644
--- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig
+++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig
@@ -96,7 +96,9 @@
'type': 'accompanying_period',
'id': accompanyingCourse.id
}
- } %}
+ }
+ }
+ %}
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig
index 79e159596..3c89bf3e3 100644
--- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig
+++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig
@@ -11,7 +11,7 @@
{{- 'Emergency'|trans|upper -}}
{% endif %}
{% if period.confidential %}
- {{- 'Confidential'|trans|upper -}}
+ {{- 'Confidential'|trans|upper -}}
{% endif %}
@@ -45,7 +45,7 @@
{% if chill_accompanying_periods.fields.user == 'visible' %}
{% if period.user %}
{{ 'Referrer'|trans }}:
- {{ period.user.username|chill_entity_render_box }}
+ {{ period.user|chill_entity_render_box }}
{% else %}
{{ 'No accompanying user'|trans }}
{% endif %}
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Person/list_with_period.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Person/list_with_period.html.twig
index f28115d8d..4b0076078 100644
--- a/src/Bundle/ChillPersonBundle/Resources/views/Person/list_with_period.html.twig
+++ b/src/Bundle/ChillPersonBundle/Resources/views/Person/list_with_period.html.twig
@@ -80,7 +80,14 @@
{% set app = person.findParticipationForPeriod(acp) %}
-
+
+ {% if acp.emergency %}
+ {{- 'Emergency'|trans|upper -}}
+ {% endif %}
+ {% if acp.confidential %}
+ {{- 'Confidential'|trans|upper -}}
+ {% endif %}
+
{% if acp.step == 'DRAFT' %}
{{ 'course.draft'|trans }}
diff --git a/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkContext.php b/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkContext.php
index b47c46b00..514f396c6 100644
--- a/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkContext.php
+++ b/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkContext.php
@@ -21,10 +21,7 @@ use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
-class AccompanyingPeriodWorkContext implements
- DocGeneratorContextInterface,
- DocGeneratorContextWithAdminFormInterface,
- DocGeneratorContextWithPublicFormInterface
+class AccompanyingPeriodWorkContext
{
private NormalizerInterface $normalizer;
diff --git a/src/Bundle/ChillPersonBundle/translations/validators.fr.yml b/src/Bundle/ChillPersonBundle/translations/validators.fr.yml
index b421e9f43..96cfd565f 100644
--- a/src/Bundle/ChillPersonBundle/translations/validators.fr.yml
+++ b/src/Bundle/ChillPersonBundle/translations/validators.fr.yml
@@ -16,6 +16,9 @@ The birthdate must be before %date%: La date de naissance doit être avant le %d
'Invalid phone number: it should begin with the international prefix starting with "+", hold only digits and be smaller than 20 characters. Ex: +33623456789': 'Numéro de téléphone invalide: il doit commencer par le préfixe international précédé de "+", ne comporter que des chiffres et faire moins de 20 caractères. Ex: +33623456789'
'The email is not valid': 'Le courriel n''est pas valide'
Two addresses has the same validFrom date: La date de validité est identique à celle d'une autre adresse
+The firstname cannot be empty: Le prénom ne peut pas être vide
+The lastname cannot be empty: Le nom de famille ne peut pas être vide
+The gender must be set: Le genre doit être renseigné
#export list
You must select at least one element: Vous devez sélectionner au moins un élément