mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch 'issue307_location' into 'master'
improve location encoding See merge request Chill-Projet/chill-bundles!230
This commit is contained in:
commit
6d6f930afa
@ -21,6 +21,8 @@ and this project adheres to
|
|||||||
* [list for accompanying course in person] filter list using ACL
|
* [list for accompanying course in person] filter list using ACL
|
||||||
* [validation] toasts are displayed for errors when modifying accompanying course (generalization required).
|
* [validation] toasts are displayed for errors when modifying accompanying course (generalization required).
|
||||||
* add an endpoint for checking permissions. See https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/232
|
* add an endpoint for checking permissions. See https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/232
|
||||||
|
* [activity] for a new activity: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties
|
||||||
|
* [calendar] for a new rdv: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties
|
||||||
|
|
||||||
## Test releases
|
## Test releases
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ final class ActivityController extends AbstractController
|
|||||||
static fn (ActivityReason $ar): int => $ar->getId()
|
static fn (ActivityReason $ar): int => $ar->getId()
|
||||||
)
|
)
|
||||||
->toArray(),
|
->toArray(),
|
||||||
'type_id' => $activity->getType()->getId(),
|
'type_id' => $activity->getActivityType()->getId(),
|
||||||
'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null,
|
'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null,
|
||||||
'date' => $activity->getDate()->format('Y-m-d'),
|
'date' => $activity->getDate()->format('Y-m-d'),
|
||||||
'attendee' => $activity->getAttendee(),
|
'attendee' => $activity->getAttendee(),
|
||||||
@ -194,7 +194,7 @@ final class ActivityController extends AbstractController
|
|||||||
$form = $this->createForm(ActivityType::class, $entity, [
|
$form = $this->createForm(ActivityType::class, $entity, [
|
||||||
'center' => $entity->getCenter(),
|
'center' => $entity->getCenter(),
|
||||||
'role' => new Role('CHILL_ACTIVITY_UPDATE'),
|
'role' => new Role('CHILL_ACTIVITY_UPDATE'),
|
||||||
'activityType' => $entity->getType(),
|
'activityType' => $entity->getActivityType(),
|
||||||
'accompanyingPeriod' => $accompanyingPeriod,
|
'accompanyingPeriod' => $accompanyingPeriod,
|
||||||
])->handleRequest($request);
|
])->handleRequest($request);
|
||||||
|
|
||||||
@ -327,7 +327,7 @@ final class ActivityController extends AbstractController
|
|||||||
$entity->setAccompanyingPeriod($accompanyingPeriod);
|
$entity->setAccompanyingPeriod($accompanyingPeriod);
|
||||||
}
|
}
|
||||||
|
|
||||||
$entity->setType($activityType);
|
$entity->setActivityType($activityType);
|
||||||
$entity->setDate(new DateTime('now'));
|
$entity->setDate(new DateTime('now'));
|
||||||
|
|
||||||
if ($request->query->has('activityData')) {
|
if ($request->query->has('activityData')) {
|
||||||
@ -385,7 +385,7 @@ final class ActivityController extends AbstractController
|
|||||||
$form = $this->createForm(ActivityType::class, $entity, [
|
$form = $this->createForm(ActivityType::class, $entity, [
|
||||||
'center' => $entity->getCenter(),
|
'center' => $entity->getCenter(),
|
||||||
'role' => new Role('CHILL_ACTIVITY_CREATE'),
|
'role' => new Role('CHILL_ACTIVITY_CREATE'),
|
||||||
'activityType' => $entity->getType(),
|
'activityType' => $entity->getActivityType(),
|
||||||
'accompanyingPeriod' => $accompanyingPeriod,
|
'accompanyingPeriod' => $accompanyingPeriod,
|
||||||
])->handleRequest($request);
|
])->handleRequest($request);
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { getSocialIssues } from 'ChillPersonAssets/vuejs/AccompanyingCourse/api.js';
|
import { getSocialIssues } from 'ChillPersonAssets/vuejs/AccompanyingCourse/api.js';
|
||||||
|
import { fetchResults } from 'ChillMainAssets/lib/api/apiMethods';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load socialActions by socialIssue (id)
|
* Load socialActions by socialIssue (id)
|
||||||
@ -12,33 +13,20 @@ const getSocialActionByIssue = (id) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
const getLocations = () => fetchResults('/api/1.0/main/location.json');
|
||||||
* Load Locations
|
|
||||||
*/
|
const getLocationTypes = () => fetchResults('/api/1.0/main/location-type.json');
|
||||||
const getLocations = () => {
|
|
||||||
const url = `/api/1.0/main/location.json`;
|
|
||||||
return fetch(url)
|
|
||||||
.then(response => {
|
|
||||||
if (response.ok) { return response.json(); }
|
|
||||||
throw Error('Error with request resource response');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load Location Types
|
* Load Location Type by defaultFor
|
||||||
|
* @param {string} entity - can be "person" or "thirdparty"
|
||||||
*/
|
*/
|
||||||
const getLocationTypes = () => {
|
const getLocationTypeByDefaultFor = (entity) => {
|
||||||
const url = `/api/1.0/main/location-type.json`;
|
return getLocationTypes().then(results =>
|
||||||
return fetch(url)
|
results.filter(t => t.defaultFor === entity)[0]
|
||||||
.then(response => {
|
);
|
||||||
if (response.ok) { return response.json(); }
|
|
||||||
throw Error('Error with request resource response');
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Post a Location
|
|
||||||
*/
|
|
||||||
const postLocation = (body) => {
|
const postLocation = (body) => {
|
||||||
const url = `/api/1.0/main/location.json`;
|
const url = `/api/1.0/main/location.json`;
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
@ -59,5 +47,6 @@ export {
|
|||||||
getSocialActionByIssue,
|
getSocialActionByIssue,
|
||||||
getLocations,
|
getLocations,
|
||||||
getLocationTypes,
|
getLocationTypes,
|
||||||
|
getLocationTypeByDefaultFor,
|
||||||
postLocation
|
postLocation
|
||||||
};
|
};
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
<teleport to="#location">
|
<teleport to="#location">
|
||||||
<div class="mb-3 row">
|
<div class="mb-3 row">
|
||||||
<label class="col-form-label col-sm-4">
|
<label class="col-form-label col-sm-4">
|
||||||
{{ $t('activity.location') }}
|
{{ $t("activity.location") }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
|
|
||||||
<VueMultiselect
|
<VueMultiselect
|
||||||
name="selectLocation"
|
name="selectLocation"
|
||||||
id="selectLocation"
|
id="selectLocation"
|
||||||
@ -17,7 +16,10 @@
|
|||||||
:placeholder="$t('activity.choose_location')"
|
:placeholder="$t('activity.choose_location')"
|
||||||
:custom-label="customLabel"
|
:custom-label="customLabel"
|
||||||
:options="locations"
|
:options="locations"
|
||||||
v-model="location">
|
group-values="locations"
|
||||||
|
group-label="locationGroup"
|
||||||
|
v-model="location"
|
||||||
|
>
|
||||||
</VueMultiselect>
|
</VueMultiselect>
|
||||||
|
|
||||||
<new-location v-bind:locations="locations"></new-location>
|
<new-location v-bind:locations="locations"></new-location>
|
||||||
@ -27,49 +29,146 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from "vuex";
|
import { mapState, mapGetters } from "vuex";
|
||||||
import VueMultiselect from 'vue-multiselect';
|
import VueMultiselect from "vue-multiselect";
|
||||||
import NewLocation from './Location/NewLocation.vue';
|
import NewLocation from "./Location/NewLocation.vue";
|
||||||
import { getLocations } from '../api.js';
|
import { getLocations, getLocationTypeByDefaultFor } from "../api.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Location",
|
name: "Location",
|
||||||
components: {
|
components: {
|
||||||
NewLocation,
|
NewLocation,
|
||||||
VueMultiselect
|
VueMultiselect,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
locations: []
|
locations: [],
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['activity']),
|
...mapState(["activity"]),
|
||||||
|
...mapGetters(["suggestedEntities"]),
|
||||||
location: {
|
location: {
|
||||||
get() {
|
get() {
|
||||||
return this.activity.location;
|
return this.activity.location;
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
this.$store.dispatch('updateLocation', value);
|
this.$store.dispatch("updateLocation", value);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
getLocations().then(response => new Promise(resolve => {
|
getLocations().then(
|
||||||
console.log('getLocations', response);
|
(results) => {
|
||||||
this.locations = response.results;
|
getLocationTypeByDefaultFor('person').then(
|
||||||
if (window.default_location_id) {
|
(personLocationType) => {
|
||||||
let location = this.locations.filter(l => l.id === window.default_location_id);
|
if (personLocationType) {
|
||||||
this.$store.dispatch('updateLocation', location);
|
const personLocation = this.makeAccompanyingPeriodLocation(personLocationType);
|
||||||
|
const concernedPersonsLocation =
|
||||||
|
this.makeConcernedPersonsLocation(personLocationType);
|
||||||
|
getLocationTypeByDefaultFor('thirdparty').then(
|
||||||
|
thirdpartyLocationType => {
|
||||||
|
const concernedThirdPartiesLocation =
|
||||||
|
this.makeConcernedThirdPartiesLocation(thirdpartyLocationType);
|
||||||
|
this.locations = [
|
||||||
|
{
|
||||||
|
locationGroup: 'Localisation du parcours',
|
||||||
|
locations: [personLocation]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
locationGroup: 'Parties concernées',
|
||||||
|
locations: [...concernedPersonsLocation, ...concernedThirdPartiesLocation]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
locationGroup: 'Autres localisations',
|
||||||
|
locations: results
|
||||||
}
|
}
|
||||||
resolve();
|
];
|
||||||
}))
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.locations = [
|
||||||
|
{
|
||||||
|
locationGroup: 'Localisations',
|
||||||
|
locations: response.results
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (window.default_location_id) {
|
||||||
|
let location = this.locations.filter(
|
||||||
|
(l) => l.id === window.default_location_id
|
||||||
|
);
|
||||||
|
this.$store.dispatch("updateLocation", location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
labelAccompanyingCourseLocation(value) {
|
||||||
|
return `${value.address.text} (${value.locationType.title.fr})`
|
||||||
|
},
|
||||||
customLabel(value) {
|
customLabel(value) {
|
||||||
return `${value.locationType.title.fr} ${value.name ? value.name : ''}`;
|
return value.locationType
|
||||||
|
? value.name
|
||||||
|
? value.name === '__AccompanyingCourseLocation__'
|
||||||
|
? this.labelAccompanyingCourseLocation(value)
|
||||||
|
: `${value.name} (${value.locationType.title.fr})`
|
||||||
|
: value.locationType.title.fr
|
||||||
|
: '';
|
||||||
|
},
|
||||||
|
makeConcernedPersonsLocation(locationType) {
|
||||||
|
let locations = [];
|
||||||
|
this.suggestedEntities.forEach(
|
||||||
|
(e) => {
|
||||||
|
if (e.type === 'person' && e.current_household_address !== null){
|
||||||
|
locations.push({
|
||||||
|
type: 'location',
|
||||||
|
id: -this.suggestedEntities.indexOf(e)*10,
|
||||||
|
onthefly: true,
|
||||||
|
name: e.text,
|
||||||
|
address: {
|
||||||
|
id: e.current_household_address.address_id,
|
||||||
|
},
|
||||||
|
locationType: locationType
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
|
return locations;
|
||||||
|
},
|
||||||
|
makeConcernedThirdPartiesLocation(locationType) {
|
||||||
|
let locations = [];
|
||||||
|
this.suggestedEntities.forEach(
|
||||||
|
(e) => {
|
||||||
|
if (e.type === 'thirdparty' && e.address !== null){
|
||||||
|
locations.push({
|
||||||
|
type: 'location',
|
||||||
|
id: -this.suggestedEntities.indexOf(e)*10,
|
||||||
|
onthefly: true,
|
||||||
|
name: e.text,
|
||||||
|
address: { id: e.address.address_id },
|
||||||
|
locationType: locationType
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return locations;
|
||||||
|
},
|
||||||
|
makeAccompanyingPeriodLocation(locationType) {
|
||||||
|
const accPeriodLocation = this.activity.accompanyingPeriod.location;
|
||||||
|
return {
|
||||||
|
type: 'location',
|
||||||
|
id: -1,
|
||||||
|
onthefly: true,
|
||||||
|
name: '__AccompanyingCourseLocation__',
|
||||||
|
address: {
|
||||||
|
id: accPeriodLocation.address_id,
|
||||||
|
text: `${accPeriodLocation.text} - ${accPeriodLocation.postcode.code} ${accPeriodLocation.postcode.name}`
|
||||||
|
},
|
||||||
|
locationType: locationType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -214,11 +214,9 @@ export default {
|
|||||||
return cond;
|
return cond;
|
||||||
},
|
},
|
||||||
getLocationTypesList() {
|
getLocationTypesList() {
|
||||||
getLocationTypes().then(response => new Promise(resolve => {
|
getLocationTypes().then(results => {
|
||||||
console.log('getLocationTypes', response);
|
this.locationTypes = results.filter(t => t.availableForUsers === true);
|
||||||
this.locationTypes = response.results.filter(t => t.availableForUsers === true);
|
})
|
||||||
resolve();
|
|
||||||
}))
|
|
||||||
},
|
},
|
||||||
openModal() {
|
openModal() {
|
||||||
this.modal.showModal = true;
|
this.modal.showModal = true;
|
||||||
@ -247,7 +245,6 @@ export default {
|
|||||||
postLocation(body)
|
postLocation(body)
|
||||||
.then(
|
.then(
|
||||||
location => new Promise(resolve => {
|
location => new Promise(resolve => {
|
||||||
console.log('postLocation', location);
|
|
||||||
this.locations.push(location);
|
this.locations.push(location);
|
||||||
this.$store.dispatch('updateLocation', location);
|
this.$store.dispatch('updateLocation', location);
|
||||||
resolve();
|
resolve();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'es6-promise/auto';
|
import 'es6-promise/auto';
|
||||||
import { createStore } from 'vuex';
|
import { createStore } from 'vuex';
|
||||||
|
import { postLocation } from './api';
|
||||||
|
|
||||||
const debug = process.env.NODE_ENV !== 'production';
|
const debug = process.env.NODE_ENV !== 'production';
|
||||||
//console.log('window.activity', window.activity);
|
//console.log('window.activity', window.activity);
|
||||||
@ -27,7 +28,6 @@ const store = createStore({
|
|||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
suggestedEntities(state) {
|
suggestedEntities(state) {
|
||||||
console.log(state.activity);
|
|
||||||
if (typeof state.activity.accompanyingPeriod === "undefined") {
|
if (typeof state.activity.accompanyingPeriod === "undefined") {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -303,7 +303,33 @@ const store = createStore({
|
|||||||
let hiddenLocation = document.getElementById(
|
let hiddenLocation = document.getElementById(
|
||||||
"chill_activitybundle_activity_location"
|
"chill_activitybundle_activity_location"
|
||||||
);
|
);
|
||||||
|
if (value.onthefly) {
|
||||||
|
const body = {
|
||||||
|
"type": "location",
|
||||||
|
"name": value.name === '__AccompanyingCourseLocation__' ? null : value.name,
|
||||||
|
"locationType": {
|
||||||
|
"id": value.locationType.id,
|
||||||
|
"type": "location-type"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (value.address.id) {
|
||||||
|
Object.assign(body, {
|
||||||
|
"address": {
|
||||||
|
"id": value.address.id
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
postLocation(body)
|
||||||
|
.then(
|
||||||
|
location => hiddenLocation.value = location.id
|
||||||
|
).catch(
|
||||||
|
err => {
|
||||||
|
console.log(err.message);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
hiddenLocation.value = value.id;
|
hiddenLocation.value = value.id;
|
||||||
|
}
|
||||||
commit("updateLocation", value);
|
commit("updateLocation", value);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -67,8 +67,8 @@
|
|||||||
<dd>
|
<dd>
|
||||||
{% if entity.location is not null %}
|
{% if entity.location is not null %}
|
||||||
<p>
|
<p>
|
||||||
<span>{{ entity.location.locationType.title|localize_translatable_string }}</span>
|
|
||||||
{{ entity.location.name }}
|
{{ entity.location.name }}
|
||||||
|
<span> ({{ entity.location.locationType.title|localize_translatable_string }})</span>
|
||||||
</p>
|
</p>
|
||||||
{{ entity.location.address|chill_entity_render_box }}
|
{{ entity.location.address|chill_entity_render_box }}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -332,12 +332,12 @@ class CalendarController extends AbstractController
|
|||||||
|
|
||||||
$personsId = array_map(
|
$personsId = array_map(
|
||||||
static fn (Person $p): int => $p->getId(),
|
static fn (Person $p): int => $p->getId(),
|
||||||
$entity->getPersons()
|
$entity->getPersons()->toArray()
|
||||||
);
|
);
|
||||||
|
|
||||||
$professionalsId = array_map(
|
$professionalsId = array_map(
|
||||||
static fn (ThirdParty $thirdParty): ?int => $thirdParty->getId(),
|
static fn (ThirdParty $thirdParty): ?int => $thirdParty->getId(),
|
||||||
$entity->getProfessionals()
|
$entity->getProfessionals()->toArray()
|
||||||
);
|
);
|
||||||
|
|
||||||
$durationTime = $entity->getEndDate()->diff($entity->getStartDate());
|
$durationTime = $entity->getEndDate()->diff($entity->getStartDate());
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'es6-promise/auto';
|
import 'es6-promise/auto';
|
||||||
import { createStore } from 'vuex';
|
import { createStore } from 'vuex';
|
||||||
|
import { postLocation } from 'ChillActivityAssets/vuejs/Activity/api';
|
||||||
|
|
||||||
const debug = process.env.NODE_ENV !== 'production';
|
const debug = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
@ -33,7 +34,6 @@ const store = createStore({
|
|||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
suggestedEntities(state) {
|
suggestedEntities(state) {
|
||||||
console.log(state.activity)
|
|
||||||
if (typeof(state.activity.accompanyingPeriod) === 'undefined') {
|
if (typeof(state.activity.accompanyingPeriod) === 'undefined') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -189,8 +189,35 @@ const store = createStore({
|
|||||||
updateLocation({ commit }, value) {
|
updateLocation({ commit }, value) {
|
||||||
console.log('### action: updateLocation', value);
|
console.log('### action: updateLocation', value);
|
||||||
let hiddenLocation = document.getElementById("chill_calendarbundle_calendar_location");
|
let hiddenLocation = document.getElementById("chill_calendarbundle_calendar_location");
|
||||||
|
if (value.onthefly) {
|
||||||
|
const body = {
|
||||||
|
"type": "location",
|
||||||
|
"name": value.name === '__AccompanyingCourseLocation__' ? null : value.name,
|
||||||
|
"locationType": {
|
||||||
|
"id": value.locationType.id,
|
||||||
|
"type": "location-type"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (value.address.id) {
|
||||||
|
Object.assign(body, {
|
||||||
|
"address": {
|
||||||
|
"id": value.address.id
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
postLocation(body)
|
||||||
|
.then(
|
||||||
|
location => hiddenLocation.value = location.id
|
||||||
|
).catch(
|
||||||
|
err => {
|
||||||
|
console.log(err.message);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
hiddenLocation.value = value.id;
|
hiddenLocation.value = value.id;
|
||||||
commit('updateLocation', value);
|
}
|
||||||
|
commit("updateLocation", value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,8 @@
|
|||||||
<dd>
|
<dd>
|
||||||
{% if entity.location is not null %}
|
{% if entity.location is not null %}
|
||||||
<p>
|
<p>
|
||||||
<span>{{ entity.location.locationType.title|localize_translatable_string }}</span>
|
|
||||||
{{ entity.location.name }}
|
{{ entity.location.name }}
|
||||||
|
<span> ({{ entity.location.locationType.title|localize_translatable_string }})</span>
|
||||||
</p>
|
</p>
|
||||||
{{ entity.location.address|chill_entity_render_box }}
|
{{ entity.location.address|chill_entity_render_box }}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
namespace Chill\MainBundle\Controller;
|
namespace Chill\MainBundle\Controller;
|
||||||
|
|
||||||
use Chill\MainBundle\CRUD\Controller\ApiController;
|
use Chill\MainBundle\CRUD\Controller\ApiController;
|
||||||
use DateInterval;
|
|
||||||
use DateTime;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,22 +19,11 @@ class LocationApiController extends ApiController
|
|||||||
{
|
{
|
||||||
public function customizeQuery(string $action, Request $request, $query): void
|
public function customizeQuery(string $action, Request $request, $query): void
|
||||||
{
|
{
|
||||||
$query->andWhere($query->expr()->orX(
|
$query->andWhere(
|
||||||
$query->expr()->andX(
|
|
||||||
$query->expr()->eq('e.createdBy', ':user'),
|
|
||||||
$query->expr()->gte('e.createdAt', ':dateBefore')
|
|
||||||
),
|
|
||||||
$query->expr()->andX(
|
$query->expr()->andX(
|
||||||
$query->expr()->eq('e.availableForUsers', "'TRUE'"),
|
$query->expr()->eq('e.availableForUsers', "'TRUE'"),
|
||||||
$query->expr()->eq('e.active', "'TRUE'"),
|
$query->expr()->eq('e.active', "'TRUE'"),
|
||||||
$query->expr()->isNotNull('e.name'),
|
|
||||||
$query->expr()->neq('e.name', ':emptyString'),
|
|
||||||
)
|
)
|
||||||
))
|
);
|
||||||
->setParameters([
|
|
||||||
'user' => $this->getUser(),
|
|
||||||
'dateBefore' => (new DateTime())->sub(new DateInterval('P6M')),
|
|
||||||
'emptyString' => '',
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ namespace Chill\MainBundle\Entity;
|
|||||||
|
|
||||||
use Chill\MainBundle\Repository\LocationTypeRepository;
|
use Chill\MainBundle\Repository\LocationTypeRepository;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||||
|
|
||||||
@ -20,9 +21,14 @@ use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
|||||||
* @DiscriminatorMap(typeProperty="type", mapping={
|
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||||
* "location-type": LocationType::class
|
* "location-type": LocationType::class
|
||||||
* })
|
* })
|
||||||
|
* @UniqueEntity({"defaultFor"})
|
||||||
*/
|
*/
|
||||||
class LocationType
|
class LocationType
|
||||||
{
|
{
|
||||||
|
public const DEFAULT_FOR_3PARTY = 'thirdparty';
|
||||||
|
|
||||||
|
public const DEFAULT_FOR_PERSON = 'person';
|
||||||
|
|
||||||
public const STATUS_NEVER = 'never';
|
public const STATUS_NEVER = 'never';
|
||||||
|
|
||||||
public const STATUS_OPTIONAL = 'optional';
|
public const STATUS_OPTIONAL = 'optional';
|
||||||
@ -53,6 +59,12 @@ class LocationType
|
|||||||
*/
|
*/
|
||||||
private string $contactData = self::STATUS_OPTIONAL;
|
private string $contactData = self::STATUS_OPTIONAL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", nullable=true, length=32, unique=true)
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
|
*/
|
||||||
|
private ?string $defaultFor = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
* @ORM\GeneratedValue
|
* @ORM\GeneratedValue
|
||||||
@ -87,6 +99,11 @@ class LocationType
|
|||||||
return $this->contactData;
|
return $this->contactData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDefaultFor(): ?string
|
||||||
|
{
|
||||||
|
return $this->defaultFor;
|
||||||
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
@ -125,6 +142,13 @@ class LocationType
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setDefaultFor(?string $defaultFor): self
|
||||||
|
{
|
||||||
|
$this->defaultFor = $defaultFor;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setTitle(array $title): self
|
public function setTitle(array $title): self
|
||||||
{
|
{
|
||||||
$this->title = $title;
|
$this->title = $title;
|
||||||
|
@ -71,6 +71,18 @@ final class LocationTypeType extends AbstractType
|
|||||||
],
|
],
|
||||||
'expanded' => true,
|
'expanded' => true,
|
||||||
]
|
]
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'defaultFor',
|
||||||
|
ChoiceType::class,
|
||||||
|
[
|
||||||
|
'choices' => [
|
||||||
|
'none' => null,
|
||||||
|
'person' => LocationType::DEFAULT_FOR_PERSON,
|
||||||
|
'thirdparty' => LocationType::DEFAULT_FOR_3PARTY,
|
||||||
|
],
|
||||||
|
'expanded' => true,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
<th>{{ 'Address required'|trans }}</th>
|
<th>{{ 'Address required'|trans }}</th>
|
||||||
<th>{{ 'Contact data'|trans }}</th>
|
<th>{{ 'Contact data'|trans }}</th>
|
||||||
<th>{{ 'Active'|trans }}</th>
|
<th>{{ 'Active'|trans }}</th>
|
||||||
|
<th>{{ 'Default for'|trans }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -33,6 +34,7 @@
|
|||||||
<i class="fa fa-square-o"></i>
|
<i class="fa fa-square-o"></i>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</td>
|
</td>
|
||||||
|
<td>{{ entity.defaultFor|trans }}</td>
|
||||||
<td>
|
<td>
|
||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li>
|
<li>
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add defaultFor to LocationType.
|
||||||
|
*/
|
||||||
|
final class Version20211123093355 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('DROP INDEX UNIQ_A459B5CADD3E4105');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_location_type DROP defaultFor');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Add defaultFor to LocationType';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_main_location_type ADD defaultFor VARCHAR(32) DEFAULT NULL');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_A459B5CADD3E4105 ON chill_main_location_type (defaultFor)');
|
||||||
|
}
|
||||||
|
}
|
@ -212,6 +212,10 @@ Location type: Type de localisation
|
|||||||
Phonenumber1: Numéro de téléphone
|
Phonenumber1: Numéro de téléphone
|
||||||
Phonenumber2: Autre numéro de téléphone
|
Phonenumber2: Autre numéro de téléphone
|
||||||
Configure location and location type: Configuration des localisations
|
Configure location and location type: Configuration des localisations
|
||||||
|
Default for: Type de localisation par défaut pour
|
||||||
|
none: aucun
|
||||||
|
person: usager
|
||||||
|
thirdparty: tiers
|
||||||
|
|
||||||
# circles / scopes
|
# circles / scopes
|
||||||
Choose the circle: Choisir le cercle
|
Choose the circle: Choisir le cercle
|
||||||
|
Loading…
x
Reference in New Issue
Block a user