Merge conflicts in translations.yaml resolved.

# Conflicts:
#   src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml
#   src/Bundle/ChillMainBundle/translations/messages.fr.yml
This commit is contained in:
2021-10-04 11:22:03 +00:00
170 changed files with 3615 additions and 1970 deletions

View File

@@ -4,9 +4,9 @@ const fetchScopes = () => {
return response.json();
}
}).then(data => {
console.log(data);
//console.log(data);
return new Promise((resolve, reject) => {
console.log(data);
//console.log(data);
resolve(data.results);
});
});

View File

@@ -53,32 +53,6 @@ export default {
}
},
/*
* Patch date
* TO MOVE in DatePane
addDateToAddressAndPostAddressTo(payload) {
payload.body = {
validFrom: {
datetime: `${this.context.valid.from.toISOString().split('T')[0]}T00:00:00+0100`
}
};
console.log('addDateToAddress', payload);
this.$refs.addAddress.flag.loading = true;
return patchAddress(payload.addressId, payload.body)
.then(address => new Promise((resolve, reject) => {
this.context.valid.from = address.validFrom;
resolve();
})
.then(this.postAddressTo(payload))
)
.catch((error) => {
this.$refs.addAddress.errorMsg.push(error);
this.$refs.addAddress.flag.loading = false;
});
},
*/
/*
* Post new created address to targetEntity
*/

View File

@@ -1,4 +1,4 @@
/*
/**
* Endpoint chill_api_single_country__index
* method GET, get Country Object
* @returns {Promise} a promise containing all Country object
@@ -14,7 +14,7 @@ const fetchCountries = () => {
});
};
/*
/**
* Endpoint chill_api_single_postal_code__index
* method GET, get Country Object
* @returns {Promise} a promise containing all Postal Code objects filtered with country
@@ -29,7 +29,7 @@ const fetchCities = (country) => {
});
};
/*
/**
* Endpoint chill_api_single_address_reference__index
* method GET, get AddressReference Object
* @returns {Promise} a promise containing all AddressReference objects filtered with postal code
@@ -44,7 +44,7 @@ const fetchReferenceAddresses = (postalCode) => {
});
};
/*
/**
* Endpoint chill_api_single_address_reference__index
* method GET, get AddressReference Object
* @returns {Promise} a promise containing all AddressReference objects filtered with postal code
@@ -60,7 +60,7 @@ const fetchAddresses = () => {
});
};
/*
/**
* Endpoint chill_api_single_address__entity__create
* method POST, post Address Object
* @returns {Promise}
@@ -81,8 +81,28 @@ const postAddress = (address) => {
});
};
/**
*
* @param address
* @returns {Promise<Response>}
*/
const duplicateAddress = (address) => {
const url = `/api/1.0/main/address/${address.address_id}/duplicate.json`;
return fetch(url, {
'method': 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
}).then(response => {
if (response.ok) {
return response.json();
}
throw Error('Error with request resource response');
});
};
/*
/**
* Endpoint chill_api_single_address__entity__create
* method PATCH, patch Address Instance
*
@@ -142,6 +162,7 @@ const getAddress = (id) => {
};
export {
duplicateAddress,
fetchCountries,
fetchCities,
fetchReferenceAddresses,

View File

@@ -1,17 +1,18 @@
<template>
<ul class="record_actions"
<ul class="record_actions" v-if="!options.onlyButton"
:class="{ 'sticky-form-buttons': isStickyForm }">
<li v-if="isStickyForm" class="cancel">
<slot name="before"></slot>
</li>
<slot name="action"></slot>
<li>
<slot name="action"></slot>
</li>
<li v-if="isStickyForm">
<slot name="after"></slot>
</li>
</ul>
<slot v-else name="action"></slot>
</template>
<script>
@@ -23,9 +24,6 @@ export default {
return (typeof this.options.stickyActions !== 'undefined') ?
this.options.stickyActions : this.defaultz.stickyActions;
},
},
methods: {
}
}
</script>

View File

@@ -34,6 +34,7 @@
v-bind:defaultz="this.defaultz"
v-bind:entity="this.entity"
v-bind:flag="this.flag"
@pick-address="this.pickAddress"
ref="suggestAddress">
</suggest-pane>
</template>
@@ -55,6 +56,7 @@
v-bind:entity="this.entity"
v-bind:flag="this.flag"
v-bind:insideModal="false"
@pick-address="this.pickAddress"
ref="suggestAddress">
<template v-slot:before v-if="!bypassFirstStep">
@@ -217,7 +219,16 @@
<script>
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import { getAddress, fetchCountries, fetchCities, fetchReferenceAddresses, patchAddress, postAddress, postPostalCode } from '../api';
import {
duplicateAddress,
fetchCountries,
fetchCities,
fetchReferenceAddresses,
getAddress,
patchAddress,
postAddress,
postPostalCode,
} from '../api';
import { postAddressToPerson, postAddressToHousehold } from "ChillPersonAssets/vuejs/_api/AddAddress.js";
import ShowPane from './ShowPane.vue';
import SuggestPane from './SuggestPane.vue';
@@ -234,6 +245,9 @@ export default {
EditPane,
DatePane
},
emits: {
pickAddress: null
},
data() {
return {
flag: {
@@ -257,7 +271,7 @@ export default {
validFrom: false,
validTo: false
},
hideAddress: false
onlyButton: false
},
entity: {
address: {}, // <== loaded and returned
@@ -299,18 +313,22 @@ export default {
return (typeof this.options.openPanesInModal !== 'undefined') ?
this.options.openPanesInModal : this.defaultz.openPanesInModal;
},
useDatePane() {
let vFrom = (typeof this.options.useDate !== 'undefined'
&& typeof this.options.useDate.validFrom !== 'undefined') ?
this.options.useDate.validFrom : this.defaultz.useDate.validFrom ;
let vTo = (typeof this.options.useDate !== 'undefined'
&& typeof this.options.useDate.validTo !== 'undefined') ?
validFrom() {
return (typeof this.options.useDate !== 'undefined' && typeof this.options.useDate.validFrom !== 'undefined') ?
this.options.useDate.validFrom : this.defaultz.useDate.validFrom;
},
validTo() {
return (typeof this.options.useDate !== 'undefined' && typeof this.options.useDate.validTo !== 'undefined') ?
this.options.useDate.validTo : this.defaultz.useDate.validTo ;
return (vFrom || vTo) ? true : false;
},
useDatePane() {
return (this.validFrom || this.validTo) ? true : false;
},
hasSuggestions() {
// TODO
//return addressSuggestions.length > 0
if (typeof(this.context.suggestions) !== 'undefined') {
console.log('hasSuggestions', this.context.suggestions);
return this.context.suggestions.length > 0;
}
return false;
},
displaySuggestions() {
@@ -335,7 +353,9 @@ export default {
},
mounted() {
console.log('useDatePane', this.useDatePane);
//console.log('validFrom', this.validFrom);
//console.log('validTo', this.validTo);
//console.log('useDatePane', this.useDatePane);
console.log('Mounted now !');
if (this.context.edit) {
@@ -566,6 +586,22 @@ export default {
'point': this.entity.selected.address.point.coordinates
});
}
if (this.validFrom) {
console.log('add validFrom in fetch body', this.entity.selected.valid.from);
newAddress = Object.assign(newAddress, {
'validFrom': {
datetime: `${this.entity.selected.valid.from.toISOString().split('T')[0]}T00:00:00+0100`
}
});
}
if (this.validTo && null !== this.entity.selected.valid.to) {
console.log('add validTo in fetch body', this.entity.selected.valid.to);
newAddress = Object.assign(newAddress, {
'validTo': {
datetime: `${this.entity.selected.valid.to.toISOString().split('T')[0]}T00:00:00+0100`
}
});
}
if (this.entity.selected.writeNew.postcode) {
let newPostcode = this.entity.selected.postcode;
newPostcode = Object.assign(newPostcode, {
@@ -627,9 +663,12 @@ export default {
this.flag.loading = false;
this.flag.success = true;
resolve({
address,
targetOrigin: this.context.target,
// for "legacy" use:
target: this.context.target.name,
targetId: this.context.target.id,
addressId: this.entity.address.address_id
addressId: this.entity.address.address_id,
}
);
}))
@@ -675,6 +714,9 @@ export default {
this.flag.loading = false;
this.flag.success = true;
return resolve({
address,
targetOrigin: this.context.target,
// for "legacy" use:
target: this.context.target.name,
targetId: this.context.target.id,
addressId: this.entity.address.address_id
@@ -687,18 +729,28 @@ export default {
});
},
/*
* Method just add closing pane to the callback method
* (get out step1 show pane, submit button)
closePaneAndCallbackSubmit(payload)
{
//this.initForm();
//this.resetPane(); // because parent callback will cast afterLastPaneAction()
console.log('will call parent callback method', payload);
// callback props method from parent
this.addressChangedCallback(payload);
}
/**
*
* @param address the address selected
*/
pickAddress(address) {
console.log('pickAddress', address);
duplicateAddress(address).then(newAddress => {
this.entity.address = newAddress;
this.flag.loading = false;
this.flag.success = true;
let payload = {
address: newAddress,
targetOrigin: this.context.target,
// for "legacy" use:
target: this.context.target.name,
targetId: this.context.target.id,
addressId: this.entity.address.address_id
};
this.addressChangedCallback(payload);
this.closeSuggestPane();
});
}
}
}
</script>

View File

@@ -54,7 +54,7 @@
</template>
<script>
import { dateToISO, ISOToDate, ISOToDatetime } from 'ChillMainAssets/chill/js/date.js';
import { dateToISO, ISOToDate } from 'ChillMainAssets/chill/js/date.js';
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue';
import ActionButtons from './ActionButtons.vue';

View File

@@ -1,6 +1,6 @@
<template>
<div v-if="!hideAddress">
<div v-if="!onlyButton">
<div class="loading">
<i v-if="flag.loading" class="fa fa-circle-o-notch fa-spin fa-2x fa-fw"></i>
<span class="sr-only">{{ $t('loading') }}</span>
@@ -28,13 +28,11 @@
:options="this.options"
:defaultz="this.defaultz">
<template v-slot:action>
<li>
<button @click.prevent="$emit('openEditPane')"
class="btn" :class="getClassButton"
type="button" name="button" :title="$t(getTextButton)">
<span v-if="displayTextButton">{{ $t(getTextButton) }}</span>
</button>
</li>
<button @click.prevent="$emit('openEditPane')"
class="btn" :class="getClassButton"
type="button" name="button" :title="$t(getTextButton)">
<span v-if="displayTextButton">{{ $t(getTextButton) }}</span>
</button>
</template>
</action-buttons>
@@ -86,9 +84,9 @@ export default {
getSuccessText() {
return (this.context.edit) ? 'address_edit_success' : 'address_new_success';
},
hideAddress() {
return (typeof this.options.hideAddress !== 'undefined') ?
this.options.hideAddress : this.defaultz.hideAddress;
onlyButton() {
return (typeof this.options.onlyButton !== 'undefined') ?
this.options.onlyButton : this.defaultz.onlyButton;
},
forceRedirect() {
return (!(this.context.backUrl === null || typeof this.context.backUrl === 'undefined'));

View File

@@ -10,13 +10,14 @@
<h4 class="h3">{{ $t('address_suggestions') }}</h4>
<div class="flex-table AddressSuggestionList">
<div class="item-bloc">
<div v-for="a in context.suggestions" class="item-bloc">
<div class="float-button bottom">
<div class="box">
<div class="action">
<!-- QUESTION normal que ça vienne avant l'adresse ? pourquoi pas après avoir affiché le address-render-box ? -->
<ul class="record_actions">
<li>
<button class="btn btn-sm btn-choose">
<button class="btn btn-sm btn-choose" @click="this.pickAddress(a)">
{{ $t('use_this_address') }}
</button>
</li>
@@ -25,9 +26,7 @@
<ul class="list-content fa-ul">
<li>
<i class="fa fa-li fa-map-marker"></i>
<!--
<address-render-box></address-render-box>
-->
<address-render-box :address="a"></address-render-box>
</li>
</ul>
</div>
@@ -68,9 +67,14 @@ export default {
'flag',
'entity',
'errorMsg',
'insideModal'
'insideModal',
],
computed: {},
methods: {}
methods: {
pickAddress(address) {
console.log('pickAddress in suggest pane', address);
this.$emit('pickAddress', address);
},
}
}
</script>

View File

@@ -53,7 +53,7 @@ containers.forEach((container) => {
},
/// Don't display show renderbox Address: showPane display only a button
hideAddress: container.dataset.hideAddress === 'true' //boolean, default: false
onlyButton: container.dataset.onlyButton === 'true' //boolean, default: false
}
}
}

View File

@@ -0,0 +1,41 @@
<template>
<on-the-fly
:type="context.type"
:id="context.id"
:action="context.action"
:buttonText="options.buttonText"
:displayBadge="options.displayBadge === 'true'"
@saveFormOnTheFly="saveFormOnTheFly">
</on-the-fly>
</template>
<script>
import OnTheFly from './components/OnTheFly.vue';
export default {
name: "App",
components: {
OnTheFly
},
props: ['onTheFly'],
computed: {
context() {
return this.onTheFly.context;
},
options() {
return this.onTheFly.options;
}
},
mounted() {
//console.log('OnTheFly mounted');
//console.log('OnTheFly: data context', this.context);
//console.log('OnTheFly: data options', this.options);
},
methods: {
saveFormOnTheFly(payload) {
console.log('saveFormOnTheFly', payload);
}
}
}
</script>

View File

@@ -3,7 +3,7 @@
<li class="nav-item">
<a class="nav-link" :class="{ active: isActive('person') }">
<label for="person">
<input type="radio" name="person" v-model="radioType" value="person">
<input type="radio" name="person" id="person" v-model="radioType" value="person">
{{ $t('onthefly.create.person') }}
</label>
</a>
@@ -11,7 +11,7 @@
<li class="nav-item">
<a class="nav-link" :class="{ active: isActive('thirdparty') }">
<label for="thirdparty">
<input type="radio" name="thirdparty" v-model="radioType" value="thirdparty">
<input type="radio" name="thirdparty" id="thirdparty" v-model="radioType" value="thirdparty">
{{ $t('onthefly.create.thirdparty') }}
</label>
</a>
@@ -56,6 +56,7 @@ export default {
radioType: {
set(type) {
this.type = type;
console.log('## type:', type, ', action:', this.action);
},
get() {
return this.type;
@@ -71,7 +72,10 @@ export default {
case 'person':
return this.$refs.castPerson.$data.person;
case 'thirdparty':
return this.$refs.castThirdparty.$data.thirdparty;
let data = this.$refs.castThirdparty.$data.thirdparty;
data.name = data.text;
data.address = { id: data.address.address_id }
return data;
default:
throw Error('Invalid type of entity')
}

View File

@@ -1,6 +1,11 @@
<template>
<a class="btn btn-sm" target="_blank"
<a v-if="isDisplayBadge" @click="openModal">
<span class="chill-entity" :class="badgeType">
{{ buttonText }}
</span>
</a>
<a v-else class="btn btn-sm" target="_blank"
:class="classAction"
:title="$t(titleAction)"
@click="openModal">
@@ -42,16 +47,16 @@
</template>
<template v-slot:footer>
<button v-if="action === 'show'"
@click="goToLocation(id, type)"
<a v-if="action === 'show'"
:href="buildLocation(id, type)"
:title="$t(titleMessage)"
class="btn btn-show">{{ $t(buttonMessage) }}
</button>
<button v-else
</a>
<a v-else
class="btn btn-save"
@click="saveAction">
{{ $t('action.save')}}
</button>
</a>
</template>
</modal>
@@ -61,7 +66,7 @@
<script>
import Modal from 'ChillMainAssets/vuejs/_components/Modal.vue';
import OnTheFlyCreate from './OnTheFly/Create.vue';
import OnTheFlyCreate from './Create.vue';
import OnTheFlyPerson from 'ChillPersonAssets/vuejs/_components/OnTheFly/Person.vue';
import OnTheFlyThirdparty from 'ChillThirdPartyAssets/vuejs/_components/OnTheFly/ThirdParty.vue';
@@ -73,7 +78,7 @@ export default {
OnTheFlyThirdparty,
OnTheFlyCreate
},
props: ['type', 'id', 'action', 'buttonText'],
props: ['type', 'id', 'action', 'buttonText', 'displayBadge'],
emits: ['saveFormOnTheFly'],
data() {
return {
@@ -123,17 +128,25 @@ export default {
return 'action.redirect.' + this.type;
}
},
buttonMessage(){
buttonMessage() {
switch (this.type){
case 'person':
return 'onthefly.show.file_' + this.type;
case 'thirdparty':
return 'onthefly.show.file_' + this.type;
}
},
isDisplayBadge() {
return (this.displayBadge === true && this.buttonText !== null);
},
badgeType() {
return 'entity-' + this.type + ' badge-' + this.type;
}
},
methods: {
openModal() {
console.log('## OPEN ON THE FLY MODAL');
console.log('## type:', this.type, ', action:', this.action);
this.modal.showModal = true;
this.$nextTick(function() {
//this.$refs.search.focus();
@@ -144,7 +157,6 @@ export default {
},
saveAction() {
console.log('saveAction button: create/edit action with', this.type);
let
type = this.type,
data = {} ;
@@ -159,10 +171,9 @@ export default {
break;
default:
if (typeof this.type === 'undefined') {
if (typeof this.type === 'undefined') { // action=create
type = this.$refs.castNew.radioType;
data = this.$refs.castNew.castDataByType();
} else {
throw 'error with object type';
}
@@ -173,11 +184,12 @@ export default {
this.modal.showModal = false;
},
goToLocation(id, type){
if(type == 'person'){
window.location = `../../person/${id}/general`
} else if(type == 'thirdparty') {
window.location = `../../thirdparty/thirdparty/${id}/show`
buildLocation(id, type) {
if (type === 'person') {
// TODO i18n
return `/fr/person/${id}/general`;
} else if (type === 'thirdparty') {
return `/fr/thirdparty/thirdparty/${id}/show`;
}
}
}
@@ -188,5 +200,4 @@ export default {
a {
cursor: pointer;
}
</style>

View File

@@ -0,0 +1,24 @@
const ontheflyMessages = {
fr: {
onthefly: {
show: {
person: "Détails de l'usager",
thirdparty: "Détails du tiers",
file_person: "Ouvrir la fiche de l'usager",
file_thirdparty: "Voir le Tiers",
},
edit: {
person: "Modifier un usager",
thirdparty: "Modifier un tiers"
},
create: {
button: "Créer \"{q}\"",
title: "Création d'un nouvel usager ou d'un tiers professionnel",
person: "un nouvel usager",
thirdparty: "un nouveau tiers professionnel"
},
}
}
}
export { ontheflyMessages };

View File

@@ -0,0 +1,35 @@
import { createApp } from "vue";
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n';
import { ontheflyMessages } from './i18n.js';
import App from "./App.vue";
const i18n = _createI18n( ontheflyMessages );
let containers = document.querySelectorAll('.onthefly-container');
containers.forEach((container) => {
const app = createApp({
template: `<app :onTheFly="this.onTheFly" ></app>`,
data() {
return {
onTheFly: {
context: {
action: container.dataset.action,
type: container.dataset.targetName,
id: parseInt(container.dataset.targetId),
},
options: {
buttonText: container.dataset.buttonText || null,
displayBadge: container.dataset.displayBadge || false
}
}
}
}
})
.use(i18n)
.component('app', App)
.mount(container);
//console.log('container dataset', container.dataset);
});

View File

@@ -53,24 +53,6 @@ const messages = {
top: "Haut",
bottom: "Bas",
},
onthefly: {
show: {
person: "Détails de l'usager",
thirdparty: "Détails du tiers",
file_person: "Ouvrir la fiche de l'usager",
file_thirdparty: "Voir le Tiers",
},
edit: {
person: "Modifier un usager",
thirdparty: "Modifier un tiers"
},
create: {
button: "Créer \"{q}\"",
title: "Création d'un nouvel usager ou d'un tiers professionnel",
person: "un nouvel usager",
thirdparty: "un nouveau tiers professionnel"
},
},
renderbox: {
person: "Usager",
birthday: {

View File

@@ -18,7 +18,7 @@
* stickyActions bool (default: false)
* useValidFrom bool (default: false)
* useValidTo bool (default: false)
* hideAddress bool (default: false)
* onlyButton bool (default: false)
#}
<div class="address-container"
@@ -69,7 +69,7 @@
data-use-valid-to="true"
{% endif %}
{% if hideAddress is defined and hideAddress == 1 %}
{% if onlyButton is defined and onlyButton == 1 %}
data-hide-address="true"
{% endif %}
></div>

View File

@@ -0,0 +1,8 @@
{% extends '@ChillMain/Admin/layout_permissions.html.twig' %}
{% block title %}{{ ('crud.' ~ crud_name ~ '.index.title')|trans({'%crud_name%': crud_name}) }}{% endblock %}
{% block content %}
{% embed '@ChillMain/CRUD/_index.html.twig' %}
{% endembed %}
{% endblock content %}

View File

@@ -1,17 +1,15 @@
{% extends "@ChillMain/Admin/layoutWithVerticalMenu.html.twig" %}
{% block vertical_menu_content %}
{% endblock %}
{% block admin_content %}
<h1>{{ 'Administration interface'|trans }}</h1>
{{ 'welcome_message_raw'|trans|raw }}
<div>
<h2>{{ 'Configuration alerts'|trans }}</h2>
<p>{{ 'Here you can check the configuration of your instance.'|trans }}</p>
{{ chill_widget('configuration_warnings', {}) }}
</div>
{% endblock %}
<p>{{ 'Welcome to the admin section !'|trans }}</p>
{{ chill_menu('admin_index', {
'layout': '@ChillMain/Admin/menu_admin_index.html.twig'
}) }}
{% endblock %}

View File

@@ -1,26 +1,3 @@
{#
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
<info@champs-libres.coop> / <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{#
The layout of the admin section. All the page / template of the admin section must use this
layout.
#}
{% extends "@ChillMain/layout.html.twig" %}
{% block navigation_search_bar %}{% endblock %}
@@ -38,4 +15,4 @@
</div>
</div>
{% endblock %}
{% endblock %}
{% endblock %}

View File

@@ -1,37 +1,14 @@
{#
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
<info@champs-libres.coop> / <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{#
The layout of the admin section. All the page / template of the admin section must use this
layout.
#}
{% extends "@ChillMain/layoutWithVerticalMenu.html.twig" %}
{% block navigation_search_bar %}{% endblock %}
{% block navigation_section_menu %}
{{ chill_menu('admin_section', {
'layout': '@ChillMain/Menu/adminSection.html.twig',
'layout': '@ChillMain/Admin/menu_admin_section.html.twig',
}) }}
{% endblock %}
{% block layout_wvm_content %}
{% block admin_content %}<!-- block personcontent empty -->
<h2>{{ 'Welcome to the admin section !'|trans }}</h2>
{% block admin_content %}
<!-- block admin content emty -->
{% endblock %}
{% endblock %}
{% endblock %}

View File

@@ -1,5 +1,5 @@
{#
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
<info@champs-libres.coop> / <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
@@ -20,7 +20,7 @@
{% block vertical_menu_content %}
{{ chill_menu('admin_permissions', {
'layout': '@ChillMain/Menu/admin_permissions.html.twig',
'layout': '@ChillMain/Admin/menu_admin_permissions.html.twig',
}) }}
{% endblock %}
@@ -28,4 +28,4 @@
{% block admin_content %}<!-- block personcontent empty -->
<h1>{{ 'Permissions management of your chill installation' |trans }}</h1>
{% endblock %}
{% endblock %}
{% endblock %}

View File

@@ -0,0 +1,18 @@
<div class="{{ 'menu-' ~ menus.name }}">
<ul>
{% for menu in menus %}
<li>
<a class=""
href="{{ menu.uri }}">
<h3>{{ menu.label|trans }}</h3>
{% if menu.extras.explain is defined %}
<div class="" >
{{ menu.extras.explain|trans }}
</div>
{% endif %}
</a>
</li>
{% endfor %}
</ul>
</div>

View File

@@ -1,17 +1,22 @@
{% set formId = crudMainFormId|default('crud_main_form') %}
<div class="{% block crud_content_main_div_class %}{% endblock %}">
{% block crud_content_header %}
<h1>{{ ('crud.'~crud_name~'.title_edit')|trans }}</h1>
{% endblock crud_content_header %}
{% block crud_content_form %}
{{ form_start(form) }}
{{ form_start(form, { 'attr' : { 'id': formId } } ) }}
{% block crud_content_form_rows %}
{% for f in form %}
{{ form_row(f) }}
{% endfor %}
{% endblock crud_content_form_rows %}
{{ form_end(form) }}
{% block crud_content_after_form %}{% endblock %}
{% block crud_content_form_actions %}
<ul class="record_actions sticky-form-buttons">
{% block content_form_actions_back %}
@@ -30,7 +35,7 @@
</li>
{% endif %}
{% endif %}
{% endblock content_form_actions_delete %}
{% endblock content_form_actions_delete %}
{% block content_form_actions_view %}
{% if chill_crud_action_exists(crud_name, 'view') %}
{% if is_granted(chill_crud_config('role', crud_name, 'view'), entity) %}
@@ -39,17 +44,17 @@
</li>
{% endif %}
{% endif %}
{% endblock content_form_actions_view %}
{% endblock content_form_actions_view %}
{% block content_form_actions_save_and_close %}
<li class="">
<button type="submit" name="submit" value="save-and-close" class="btn btn-update">
<button type="submit" name="submit" value="save-and-close" class="btn btn-update" form="{{ formId }}">
{{ 'crud.edit.save_and_close'|trans }}
</button>
</li>
{% endblock %}
{% block content_form_actions_save_and_show %}
<li class="">
<button type="submit" name="submit" value="save-and-show" class="btn btn-update">
<button type="submit" name="submit" value="save-and-show" class="btn btn-update" form="{{ formId }}">
{{ 'crud.edit.save_and_show'|trans }}
</button>
</li>
@@ -58,6 +63,5 @@
</ul>
{% endblock %}
{{ form_end(form) }}
{% endblock %}
</div>

View File

@@ -5,14 +5,16 @@
{% block crud_content_form %}
{{ form_start(form) }}
{% block crud_content_form_rows %}
{% for f in form %}{% if f.vars.name != 'submit' %}
{{ form_row(f) }}
{% endif %}{% endfor %}
{% endblock crud_content_form_rows %}
{% block crud_content_form_actions %}
{% block crud_content_after_form %}{% endblock %}
{% block crud_content_form_actions %}
<ul class="record_actions sticky-form-buttons">
{% block content_form_actions_back %}
<li class="cancel">
@@ -20,7 +22,7 @@
{{ 'Cancel'|trans }}
</a>
</li>
{% endblock %}
{% endblock %}
{% block content_form_actions_save_and_close %}
<li class="">
<button type="submit" name="submit" value="save-and-close" class="btn btn-create">

View File

@@ -1,20 +1,3 @@
{#
* Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS,
* <info@champs-libres.coop> / <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
<header>
<nav class="navbar navbar-dark bg-primary navbar-expand-md">
<div class="container-xxl">
@@ -24,12 +7,12 @@
{{ include('@ChillMain/Layout/_header-logo.html.twig') }}
</a>
</div>
<div class="col-8">
<button class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
<button class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarContent"
aria-controls="navbarContent"
aria-expanded="false"
@@ -43,8 +26,8 @@
{% block navigation_search_bar %}
<li class="nav-item navigation-search">
<form class="form-inline" action="{{ path('chill_main_search') }}" method="get">
<input class="form-control"
name="q" type="search" placeholder="{{ 'Search'|trans }}"
<input class="form-control"
name="q" type="search" placeholder="{{ 'Search'|trans }}"
{% if _search_pattern is defined %}value="{{ _search_pattern }}"{% endif %}/>
<button class="btn text-white-50" type="submit">
<i class="fa fa-lg fa-search fa-flip-horizontal"></i>
@@ -71,15 +54,15 @@
</li>
{% else %}
<li class="nav-item dropdown btn btn-primary nav-language">
<a id="menu-languages"
class="nav-link dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-haspopup="true"
<a id="menu-languages"
class="nav-link dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
<a href="#" class="more">{{ app.request.locale | capitalize }}</a>
</a>
<div class="dropdown-menu dropdown-menu-end"
<div class="dropdown-menu dropdown-menu-end"
aria-labelledby="menu-languages">
{% for lang in available_languages %}
<a class="dropdown-item list-group-item bg-dark text-white{% if lang == app.request.locale %} active{% endif %}"
@@ -93,7 +76,7 @@
</ul>
</div>
</div>
</div>
</nav>

View File

@@ -25,7 +25,7 @@
aria-expanded="false">
{{ 'Welcome' | trans }}<br/>
<b>
{{ app.user.username }}
{{ render(controller('ChillMainBundle:UI:showNotificationUserCounter')) }}
@@ -40,8 +40,8 @@
{% for menu in menus %}
{% if is_granted('ROLE_PREVIOUS_ADMIN') and menu.name == 'Logout' %}
<a class="dropdown-item list-group-item bg-dark text-white"
href="{{ path('admin_user', {'_switch_user': '_exit'}) }}">
<a class="dropdown-item list-group-item bg-dark text-white"
href="{{ path('chill_crud_admin_user_index', {'_switch_user': '_exit'}) }}">
{{ 'Exit impersonation'|trans }}
{% else %}
<a class="dropdown-item list-group-item bg-dark text-white"

View File

@@ -1,5 +1,5 @@
{#
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
<info@champs-libres.coop> / <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
@@ -17,7 +17,7 @@
#}
{#
Layout for a vertical menu (like admin, export) to use with the
Layout for a vertical menu (like admin, export) to use with the
layout ../layoutWithVerticalMenu.html.twig.
#}
@@ -25,13 +25,9 @@
<li class="title">
{% block v_menu_title %}<!-- title of the verticalMenu is empty -->{% endblock %}
</li>
{% for route in routes %}
<li class="{% apply spaceless %}
{% if route.key == activeRouteKey %}
active
{% endif %}
{% endapply %} ">
<a href="{{ path(route.key, args ) }}" >{{ route.label|trans }}</a>
{% for menu in menus %}
<li class="{% if menu is knp_menu_current %}current {% endif %}">
<a href="{{ menu.uri }}" >{{ menu.label|trans }}</a>
</li>
{% endfor %}
</ul>
</ul>

View File

@@ -0,0 +1,37 @@
{#
This Twig template include load vue_onthefly component.
It push all variables from context in OnTheFly/App.vue.
OPTIONS
* targetEntity {
name: string 'person', 'thirdparty'
id: integer
}
* action string 'show', 'edit', 'create'
* buttonText string
* displayBadge boolean (default: false) replace button by badge, need to define buttonText for content
#}
<span class="onthefly-container"
data-target-name="{{ targetEntity.name|e('html_attr') }}"
data-target-id="{{ targetEntity.id|e('html_attr') }}"
{% if action is defined %}
data-action="{{ action|e('html_attr') }}"
{% else %}
data-action="show"
{% endif %}
{% if buttonText is defined %}
data-button-text="{{ buttonText|e('html_attr') }}"
{% endif %}
{% if displayBadge is defined and displayBadge == 1 %}
data-display-badge="true"
{% endif %}
></span>
{{ encore_entry_script_tags('vue_onthefly') }}
{{ encore_entry_link_tags('vue_onthefly') }}

View File

@@ -1,78 +1,56 @@
{% extends '@ChillMain/Admin/layout_permissions.html.twig' %}
{% block title %}{{ 'User edit'|trans }}{% endblock %}
{% extends '@ChillMain/Admin/Permission/layout_crud_permission_index.html.twig' %}
{% block admin_content -%}
<h1>{{ 'User edit'|trans }}</h1>
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
{% block crud_content_after_form %}
<h2>{{ 'Permissions granted'|trans }}</h2>
{{ form_start(edit_form) }}
{{ form_row(edit_form.username) }}
{{ form_row(edit_form.email) }}
{{ form_row(edit_form.enabled, { 'label': "User'status"}) }}
{{ form_widget(edit_form.submit, { 'attr': { 'class' : 'btn btn-chill-green center' } } ) }}
<a href="{{ path('admin_user_edit_password', { 'id' : entity.id }) }}" class="btn btn-chill-orange">{{ 'Edit password'|trans }}</a>
{{ form_end(edit_form) }}
<h2>{{ 'Permissions granted'|trans }}</h2>
{% if entity.groupcenters|length > 0 %}
<table>
<thead>
<tr>
<th>{{ 'Permission group'|trans }}</th>
<th>{{ 'Center'|trans }}</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for groupcenter in entity.groupcenters %}
<tr>
<td>
{% if entity.groupcenters|length > 0 %}
<table>
<thead>
<tr>
<th>{{ 'Permission group'|trans }}</th>
<th>{{ 'Center'|trans }}</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for groupcenter in entity.groupcenters %}
<tr>
<td>
<span class="user_group permissionsgroup">
{{ groupcenter.permissionsgroup.name }}
</span>
</td>
<td>
</td>
<td>
<span class="user_group center">
{{ groupcenter.center.name }}
</span>
</td>
<td>
{{ form_start(delete_groupcenter_form[groupcenter.id]) }}
{{ form_row(delete_groupcenter_form[groupcenter.id].submit, { 'attr': { 'class': 'btn btn-chill-red' } } ) }}
{{ form_rest(delete_groupcenter_form[groupcenter.id]) }}
{{ form_end(delete_groupcenter_form[groupcenter.id]) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>{{ 'Any permissions granted to this user'|trans }}.</p>
{% endif %}
<h3>{{ 'Grant new permissions'|trans }}</h3>
{{ form_start(add_groupcenter_form) }}
{{ form_row(add_groupcenter_form.composed_groupcenter.center) }}
{{ form_row(add_groupcenter_form.composed_groupcenter.permissionsgroup) }}
{{ form_row(add_groupcenter_form.submit, { 'attr' : { 'class': 'btn btn-chill-green' } } ) }}
</td>
<td>
{{ form_start(delete_groupcenter_form[groupcenter.id]) }}
{{ form_row(delete_groupcenter_form[groupcenter.id].submit, { 'attr': { 'class': 'btn btn-chill-red' } } ) }}
{{ form_rest(delete_groupcenter_form[groupcenter.id]) }}
{{ form_end(delete_groupcenter_form[groupcenter.id]) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>{{ 'Any permissions granted to this user'|trans }}.</p>
{% endif %}
{{ form_end(add_groupcenter_form) }}
<ul class="record_actions">
<li>
<a href="{{ path('admin_user_show', { 'id': entity.id }) }}">
{{ 'show'|trans }}
</a>
</li>
<li>
<a href="{{ path('admin_user') }}">
{{ 'Back to the list'|trans }}
</a>
</li>
</ul>
<h3>{{ 'Grant new permissions'|trans }}</h3>
{{ form_start(add_groupcenter_form) }}
{{ form_row(add_groupcenter_form.composed_groupcenter.center) }}
{{ form_row(add_groupcenter_form.composed_groupcenter.permissionsgroup) }}
{{ form_row(add_groupcenter_form.submit, { 'attr' : { 'class': 'btn btn-chill-green' } } ) }}
{{ form_end(add_groupcenter_form) }}
{% endblock %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends '@ChillMain/Admin/layout_permissions.html.twig' %}
{% extends '@ChillMain/Admin/Permission/layout_crud_permission_index.html.twig' %}
{% block title %}{{ 'Edit password for %username%'|trans( { '%username%': entity.username } ) }}{% endblock %}
@@ -7,19 +7,17 @@
{{ form_start(edit_form) }}
{{ form_row(edit_form.new_password) }}
{{ form_widget(edit_form.submit, { 'attr': { 'class': 'btn btn-chill-orange' } } ) }}
<ul class="record_actions">
<li class="cancel">
<a href="{{ chill_return_path_or('chill_crud_admin_user_index') }}" class="btn btn-cancel">
{{ 'Cancel'|trans }}
</a>
</li>
<li>
{{ form_widget(edit_form.submit, { 'attr': { 'class': 'btn btn-edit' } } ) }}
</li>
</ul>
{{ form_end(edit_form) }}
<ul class="record_actions">
<li>
<a href="{{ path('admin_user') }}">
{{ 'Back to the list'|trans }}
</a>
</li>
<li>
<a href="{{ path('admin_user_edit', { 'id' : entity.id }) }}">
{{ 'Back to the user edition'|trans }}
</a>
</li>
</ul>
{% endblock %}

View File

@@ -1,53 +1,60 @@
{% extends '@ChillMain/Admin/layout_permissions.html.twig' %}
{% block title %}{{ 'user list'|trans|capitalize }}{% endblock %}
{% extends '@ChillMain/Admin/Permission/layout_crud_permission_index.html.twig' %}
{% block admin_content -%}
<h1>{{ 'user list'|trans|capitalize }}</h1>
<table class="records_list">
<thead>
<tr>
<th>{{ 'Username'|trans|capitalize }}</th>
<th>{{ 'Actions'|trans|capitalize }}</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr class="{% if entity.isEnabled == false %}user-disabled{% else %}user-enabled{% endif %}" >
<td><a href="{{ path('admin_user_show', { 'id': entity.id }) }}">{{ entity.username }}</a></td>
{% embed '@ChillMain/CRUD/_index.html.twig' %}
{% block table_entities_thead_tr %}
<th>{{ 'crud.admin_user.index.is_active'|trans }}</th>
<th>{{ 'crud.admin_user.index.usernames'|trans }}</th>
<th>{{ 'crud.admin_user.index.mains'|trans }}</th>
<th>&nbsp;</th>
{% endblock %}
{% block table_entities_tbody %}
{% for entity in entities %}
<tr data-username="{{ entity.username|e('html_attr') }}">
<td>
<ul>
<li>
<a href="{{ path('admin_user_show', { 'id': entity.id }) }}">{{ 'show'|trans }}</a>
</li>
<li>
<a href="{{ path('admin_user_edit', { 'id': entity.id }) }}">{{ 'edit'|trans }}</a>
</li>
<li>
<a href="{{ path('admin_user_edit_password', { 'id' : entity.id }) }}">{{ 'Edit password'|trans }}</a>
</li>
{% if is_granted('ROLE_ALLOWED_TO_SWITCH') %}
<li>
<a href="{{ path('chill_main_homepage', {'_switch_user': entity.username }) }}">
{{ 'Impersonate'|trans }}
</a>
</li>
{% if entity.isEnabled %}
<i class="fa fa-check chill-green"></i>
{% else %}
<i class="fa fa-times chill-red"></i>
{% endif %}
</ul>
</td>
<td>
{{ entity.username }}
<br/>
{{ entity.label }}
<br/>
{{ entity.email }}
</td>
<td>
{% if entity.userJob %}
{{ entity.userJob.label|localize_translatable_string }}
<br/>
{% endif %}
{% if entity.mainScope %}
{{ entity.mainScope.name|localize_translatable_string }}
<br/>
{% endif %}
{% if entity.mainCenter %}
{{ entity.mainCenter.name }}
{% endif %}
</td>
<td>
<ul class="record_actions">
<li>
<a class="btn btn-edit" href="{{ path('chill_crud_admin_user_edit', { 'id': entity.id }) }}"></a>
</li>
<li>
<a class="btn btn-chill-red" href="{{ path('admin_user_edit_password', { 'id' : entity.id }) }}" title="{{ 'Edit password'|trans|e('html_attr') }}"><i class="fa fa-ellipsis-h"></i></a>
</li>
{% if is_granted('ROLE_ALLOWED_TO_SWITCH') %}
<li>
<a class="btn btn-chill-blue" href="{{ path('chill_main_homepage', {'_switch_user': entity.username }) }}" title="{{ "Impersonate"|trans|e('html_attr') }}"><i class="fa fa-user-secret"></i></a>
</li>
{% endif %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<ul>
<li>
<a href="{{ path('admin_user_new') }}">
{{ 'Add a new user'|trans|capitalize }}
</a>
</li>
</ul>
{% endblock admin_content %}
{% endfor %}
{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -1,22 +1,7 @@
{% extends '@ChillMain/Admin/layout_permissions.html.twig' %}
{% block title %}{{ 'User creation'|trans }}{% endblock %}
{% extends '@ChillMain/Admin/Permission/layout_crud_permission_index.html.twig' %}
{% block admin_content -%}
<h1>{{ 'User creation'|trans }}</h1>
{{ form_start(form) }}
{{ form_row(form.username) }}
{{ form_row(form.email) }}
{{ form_row(form.plainPassword) }}
{{ form_widget(form.submit, { 'attr' : { 'class': 'btn btn-chill-blue' } }) }}
{{ form_end(form) }}
<ul class="record_actions">
<li>
<a href="{{ path('admin_user') }}">
{{ 'Back to the list'|trans }}
</a>
</li>
</ul>
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -1,25 +1,3 @@
{#
* Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS,
<info@champs-libres.coop> / <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{#
The basic layout of Chill. All the page / template of Chill must use this template.
#}
<!DOCTYPE html>
<html lang="fr">
<head>

View File

@@ -1,26 +1,3 @@
{#
* Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS,
<info@champs-libres.coop> / <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{#
Layout with a vertical menu and a conainer for the content (like admin, export)
( for the vertical menu you can extends Menu/veticalMenu.html.twig ).
#}
{% extends "@ChillMain/layout.html.twig" %}
{% block sublayout_content %}