mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-21 22:24:59 +00:00
Compare commits
58 Commits
v3.8.1
...
translatio
Author | SHA1 | Date | |
---|---|---|---|
171f7585c2 | |||
fe6949ea26 | |||
8a444a12f4 | |||
8b7b5ceed7
|
|||
b0e826d05a
|
|||
6fb9c3af3f
|
|||
7f101ba616
|
|||
cea82fac10 | |||
1344fc33e1 | |||
c8e09a28e6 | |||
c52d4b2a0e
|
|||
7f326d5441
|
|||
2840c06476 | |||
7ddf84ea5a | |||
f202625ea8
|
|||
7a9168fcdb
|
|||
40eb71f95a | |||
84b7cc8145 | |||
08af530726 | |||
03b2496817
|
|||
f638ce71fd | |||
b39997f00a | |||
38b21a2159 | |||
17db571244 | |||
8c8c16c1a1 | |||
046d3ec9f1 | |||
596833f1a5 | |||
66e4bab558 | |||
d1c9926bb1 | |||
a71d066765 | |||
217ac7b9e7 | |||
be901822bc | |||
7ed10efcd1 | |||
350661a4fa | |||
08207b656a | |||
8de63de6d6 | |||
51804b10c0 | |||
02f555efae | |||
d2fcb6945b | |||
c89e3785ef | |||
9f17ec4841 | |||
b277a7749a | |||
c8b6b6e33a | |||
10eaebf610 | |||
0a34f9086f
|
|||
739e0b1692 | |||
8db8f5fdf5
|
|||
fc32f9eca9 | |||
ab35e8c034
|
|||
2aded2974f | |||
f84c1632b2
|
|||
|
03717a1a87 | ||
|
02c524dd79 | ||
|
bc7f0907ab | ||
|
fbdc0d32f0 | ||
|
5f31473c90 | ||
|
98cf167040 | ||
|
6c37d798bf |
6
.changes/v3.10.0.md
Normal file
6
.changes/v3.10.0.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
## v3.10.0 - 2025-03-17
|
||||||
|
### Feature
|
||||||
|
* ([#363](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/363)) Display social actions grouped per social issue within activity form
|
||||||
|
### Fixed
|
||||||
|
* ([#362](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/362)) Fix Dependency Injection, which prevented to save the CalendarRange
|
||||||
|
* ([#368](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/368)) fix search query for user groups
|
3
.changes/v3.10.1.md
Normal file
3
.changes/v3.10.1.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## v3.10.1 - 2025-03-17
|
||||||
|
### DX
|
||||||
|
* Remove yarn dependency to symfony/ux-translator, to ease the build process
|
3
.changes/v3.10.2.md
Normal file
3
.changes/v3.10.2.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## v3.10.2 - 2025-03-17
|
||||||
|
### Fixed
|
||||||
|
* Replace a ts-expect-error with a ts-ignore
|
3
.changes/v3.10.3.md
Normal file
3
.changes/v3.10.3.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## v3.10.3 - 2025-03-18
|
||||||
|
### DX
|
||||||
|
* Eslint fixes
|
3
.changes/v3.8.2.md
Normal file
3
.changes/v3.8.2.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## v3.8.2 - 2025-02-10
|
||||||
|
### Fixed
|
||||||
|
* ([#358](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/358)) Remove "filter" button on list of documents in the workflow's "add attachement" modal
|
10
.changes/v3.9.0.md
Normal file
10
.changes/v3.9.0.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
## v3.9.0 - 2025-02-27
|
||||||
|
### Feature
|
||||||
|
* ([#349](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/349)) Suggest all referrers within actions of the accompanying period when creating an activity
|
||||||
|
* ([#343](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/343)) Add possibility to export a csv with all social issues and social actions
|
||||||
|
* ([#360](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/360)) Restore document to previous kept version when a workflow is canceled
|
||||||
|
* ([#341](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/341)) Add a list of third parties from within the admin (csv download)
|
||||||
|
### Fixed
|
||||||
|
* fix generation of document with accompanying period context, and list of activities and works
|
||||||
|
### DX
|
||||||
|
* ([#333](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/333)) Create an unique source of trust for translations
|
3
.changes/v3.9.1.md
Normal file
3
.changes/v3.9.1.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## v3.9.1 - 2025-02-27
|
||||||
|
### Fixed
|
||||||
|
* Fix post/patch request with missing 'type' property for gender
|
3
.changes/v3.9.2.md
Normal file
3
.changes/v3.9.2.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## v3.9.2 - 2025-02-27
|
||||||
|
### Fixed
|
||||||
|
* Use fetchResults method to fetch all social issues instead of only the first page
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -12,6 +12,8 @@ docker/rabbitmq/data
|
|||||||
|
|
||||||
# in this development bundle, we want to ignore directories related to a real app
|
# in this development bundle, we want to ignore directories related to a real app
|
||||||
assets/*
|
assets/*
|
||||||
|
!assets/translator.ts
|
||||||
|
!assets/ux-translator
|
||||||
migrations/*
|
migrations/*
|
||||||
templates/*
|
templates/*
|
||||||
translations/*
|
translations/*
|
||||||
|
@@ -113,7 +113,7 @@ lint:
|
|||||||
- export PATH="./node_modules/.bin:$PATH"
|
- export PATH="./node_modules/.bin:$PATH"
|
||||||
script:
|
script:
|
||||||
- yarn install --ignore-optional
|
- yarn install --ignore-optional
|
||||||
- npx eslint-baseline "**/*.{js,vue}"
|
- npx eslint-baseline "src/**/*.{js,ts,vue}"
|
||||||
cache:
|
cache:
|
||||||
paths:
|
paths:
|
||||||
- node_modules/
|
- node_modules/
|
||||||
|
42
CHANGELOG.md
42
CHANGELOG.md
@@ -6,6 +6,48 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
|
|||||||
and is generated by [Changie](https://github.com/miniscruff/changie).
|
and is generated by [Changie](https://github.com/miniscruff/changie).
|
||||||
|
|
||||||
|
|
||||||
|
## v3.10.3 - 2025-03-18
|
||||||
|
### DX
|
||||||
|
* Eslint fixes
|
||||||
|
|
||||||
|
## v3.10.2 - 2025-03-17
|
||||||
|
### Fixed
|
||||||
|
* Replace a ts-expect-error with a ts-ignore
|
||||||
|
|
||||||
|
## v3.10.1 - 2025-03-17
|
||||||
|
### DX
|
||||||
|
* Remove yarn dependency to symfony/ux-translator, to ease the build process
|
||||||
|
|
||||||
|
## v3.10.0 - 2025-03-17
|
||||||
|
### Feature
|
||||||
|
* ([#363](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/363)) Display social actions grouped per social issue within activity form
|
||||||
|
### Fixed
|
||||||
|
* ([#362](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/362)) Fix Dependency Injection, which prevented to save the CalendarRange
|
||||||
|
* ([#368](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/368)) fix search query for user groups
|
||||||
|
|
||||||
|
## v3.9.2 - 2025-02-27
|
||||||
|
### Fixed
|
||||||
|
* Use fetchResults method to fetch all social issues instead of only the first page
|
||||||
|
|
||||||
|
## v3.9.1 - 2025-02-27
|
||||||
|
### Fixed
|
||||||
|
* Fix post/patch request with missing 'type' property for gender
|
||||||
|
|
||||||
|
## v3.9.0 - 2025-02-27
|
||||||
|
### Feature
|
||||||
|
* ([#349](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/349)) Suggest all referrers within actions of the accompanying period when creating an activity
|
||||||
|
* ([#343](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/343)) Add possibility to export a csv with all social issues and social actions
|
||||||
|
* ([#360](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/360)) Restore document to previous kept version when a workflow is canceled
|
||||||
|
* ([#341](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/341)) Add a list of third parties from within the admin (csv download)
|
||||||
|
### Fixed
|
||||||
|
* fix generation of document with accompanying period context, and list of activities and works
|
||||||
|
### DX
|
||||||
|
* ([#333](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/333)) Create an unique source of trust for translations
|
||||||
|
|
||||||
|
## v3.8.2 - 2025-02-10
|
||||||
|
### Fixed
|
||||||
|
* ([#358](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/358)) Remove "filter" button on list of documents in the workflow's "add attachement" modal
|
||||||
|
|
||||||
## v3.8.1 - 2025-02-05
|
## v3.8.1 - 2025-02-05
|
||||||
### Fixed
|
### Fixed
|
||||||
* Fix household link in the parcours banner
|
* Fix household link in the parcours banner
|
||||||
|
7
assets/translator.ts
Normal file
7
assets/translator.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { trans, setLocale, setLocaleFallbacks } from "./ux-translator";
|
||||||
|
|
||||||
|
setLocaleFallbacks({"en": "fr", "nl": "fr", "fr": "en"});
|
||||||
|
setLocale('fr');
|
||||||
|
|
||||||
|
export { trans };
|
||||||
|
export * from '../var/translations';
|
3
assets/ux-translator/README.md
Normal file
3
assets/ux-translator/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
This directory import the symfony ux-translator files directly into chill-bundles.
|
||||||
|
|
||||||
|
This remove the yarn dependencies from the real package, which breaks our installation.
|
1
assets/ux-translator/dist/formatters/formatter.d.ts
vendored
Normal file
1
assets/ux-translator/dist/formatters/formatter.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export declare function format(id: string, parameters: Record<string, string | number>, locale: string): string;
|
1
assets/ux-translator/dist/formatters/intl-formatter.d.ts
vendored
Normal file
1
assets/ux-translator/dist/formatters/intl-formatter.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export declare function formatIntl(id: string, parameters: Record<string, string | number>, locale: string): string;
|
27
assets/ux-translator/dist/translator.d.ts
vendored
Normal file
27
assets/ux-translator/dist/translator.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export type DomainType = string;
|
||||||
|
export type LocaleType = string;
|
||||||
|
export type TranslationsType = Record<DomainType, {
|
||||||
|
parameters: ParametersType;
|
||||||
|
}>;
|
||||||
|
export type NoParametersType = Record<string, never>;
|
||||||
|
export type ParametersType = Record<string, string | number | Date> | NoParametersType;
|
||||||
|
export type RemoveIntlIcuSuffix<T> = T extends `${infer U}+intl-icu` ? U : T;
|
||||||
|
export type DomainsOf<M> = M extends Message<infer Translations, LocaleType> ? keyof Translations : never;
|
||||||
|
export type LocaleOf<M> = M extends Message<TranslationsType, infer Locale> ? Locale : never;
|
||||||
|
export type ParametersOf<M, D extends DomainType> = M extends Message<infer Translations, LocaleType> ? Translations[D] extends {
|
||||||
|
parameters: infer Parameters;
|
||||||
|
} ? Parameters : never : never;
|
||||||
|
export interface Message<Translations extends TranslationsType, Locale extends LocaleType> {
|
||||||
|
id: string;
|
||||||
|
translations: {
|
||||||
|
[domain in DomainType]: {
|
||||||
|
[locale in Locale]: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export declare function setLocale(locale: LocaleType | null): void;
|
||||||
|
export declare function getLocale(): LocaleType;
|
||||||
|
export declare function throwWhenNotFound(enabled: boolean): void;
|
||||||
|
export declare function setLocaleFallbacks(localeFallbacks: Record<LocaleType, LocaleType>): void;
|
||||||
|
export declare function getLocaleFallbacks(): Record<LocaleType, LocaleType>;
|
||||||
|
export declare function trans<M extends Message<TranslationsType, LocaleType>, D extends DomainsOf<M>, P extends ParametersOf<M, D>>(...args: P extends NoParametersType ? [message: M, parameters?: P, domain?: RemoveIntlIcuSuffix<D>, locale?: LocaleOf<M>] : [message: M, parameters: P, domain?: RemoveIntlIcuSuffix<D>, locale?: LocaleOf<M>]): string;
|
1
assets/ux-translator/dist/translator_controller.d.ts
vendored
Normal file
1
assets/ux-translator/dist/translator_controller.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './translator';
|
283
assets/ux-translator/dist/translator_controller.js
vendored
Normal file
283
assets/ux-translator/dist/translator_controller.js
vendored
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
import { IntlMessageFormat } from 'intl-messageformat';
|
||||||
|
|
||||||
|
function strtr(string, replacePairs) {
|
||||||
|
const regex = Object.entries(replacePairs).map(([from]) => {
|
||||||
|
return from.replace(/([-[\]{}()*+?.\\^$|#,])/g, '\\$1');
|
||||||
|
});
|
||||||
|
if (regex.length === 0) {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
return string.replace(new RegExp(regex.join('|'), 'g'), (matched) => replacePairs[matched].toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function format(id, parameters, locale) {
|
||||||
|
if (null === id || '' === id) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (typeof parameters['%count%'] === 'undefined' || Number.isNaN(parameters['%count%'])) {
|
||||||
|
return strtr(id, parameters);
|
||||||
|
}
|
||||||
|
const number = Number(parameters['%count%']);
|
||||||
|
let parts = [];
|
||||||
|
if (/^\|+$/.test(id)) {
|
||||||
|
parts = id.split('|');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parts = id.match(/(?:\|\||[^|])+/g) || [];
|
||||||
|
}
|
||||||
|
const intervalRegex = /^(?<interval>({\s*(-?\d+(\.\d+)?[\s*,\s*\-?\d+(.\d+)?]*)\s*})|(?<left_delimiter>[[\]])\s*(?<left>-Inf|-?\d+(\.\d+)?)\s*,\s*(?<right>\+?Inf|-?\d+(\.\d+)?)\s*(?<right_delimiter>[[\]]))\s*(?<message>.*?)$/s;
|
||||||
|
const standardRules = [];
|
||||||
|
for (let part of parts) {
|
||||||
|
part = part.trim().replace(/\|\|/g, '|');
|
||||||
|
const matches = part.match(intervalRegex);
|
||||||
|
if (matches) {
|
||||||
|
const matchGroups = matches.groups || {};
|
||||||
|
if (matches[2]) {
|
||||||
|
for (const n of matches[3].split(',')) {
|
||||||
|
if (number === Number(n)) {
|
||||||
|
return strtr(matchGroups.message, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const leftNumber = '-Inf' === matchGroups.left ? Number.NEGATIVE_INFINITY : Number(matchGroups.left);
|
||||||
|
const rightNumber = ['Inf', '+Inf'].includes(matchGroups.right)
|
||||||
|
? Number.POSITIVE_INFINITY
|
||||||
|
: Number(matchGroups.right);
|
||||||
|
if (('[' === matchGroups.left_delimiter ? number >= leftNumber : number > leftNumber) &&
|
||||||
|
(']' === matchGroups.right_delimiter ? number <= rightNumber : number < rightNumber)) {
|
||||||
|
return strtr(matchGroups.message, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const ruleMatch = part.match(/^\w+:\s*(.*?)$/);
|
||||||
|
standardRules.push(ruleMatch ? ruleMatch[1] : part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const position = getPluralizationRule(number, locale);
|
||||||
|
if (typeof standardRules[position] === 'undefined') {
|
||||||
|
if (1 === parts.length && typeof standardRules[0] !== 'undefined') {
|
||||||
|
return strtr(standardRules[0], parameters);
|
||||||
|
}
|
||||||
|
throw new Error(`Unable to choose a translation for "${id}" with locale "${locale}" for value "${number}". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %count% apples").`);
|
||||||
|
}
|
||||||
|
return strtr(standardRules[position], parameters);
|
||||||
|
}
|
||||||
|
function getPluralizationRule(number, locale) {
|
||||||
|
number = Math.abs(number);
|
||||||
|
let _locale = locale;
|
||||||
|
if (locale === 'pt_BR' || locale === 'en_US_POSIX') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_locale = _locale.length > 3 ? _locale.substring(0, _locale.indexOf('_')) : _locale;
|
||||||
|
switch (_locale) {
|
||||||
|
case 'af':
|
||||||
|
case 'bn':
|
||||||
|
case 'bg':
|
||||||
|
case 'ca':
|
||||||
|
case 'da':
|
||||||
|
case 'de':
|
||||||
|
case 'el':
|
||||||
|
case 'en':
|
||||||
|
case 'en_US_POSIX':
|
||||||
|
case 'eo':
|
||||||
|
case 'es':
|
||||||
|
case 'et':
|
||||||
|
case 'eu':
|
||||||
|
case 'fa':
|
||||||
|
case 'fi':
|
||||||
|
case 'fo':
|
||||||
|
case 'fur':
|
||||||
|
case 'fy':
|
||||||
|
case 'gl':
|
||||||
|
case 'gu':
|
||||||
|
case 'ha':
|
||||||
|
case 'he':
|
||||||
|
case 'hu':
|
||||||
|
case 'is':
|
||||||
|
case 'it':
|
||||||
|
case 'ku':
|
||||||
|
case 'lb':
|
||||||
|
case 'ml':
|
||||||
|
case 'mn':
|
||||||
|
case 'mr':
|
||||||
|
case 'nah':
|
||||||
|
case 'nb':
|
||||||
|
case 'ne':
|
||||||
|
case 'nl':
|
||||||
|
case 'nn':
|
||||||
|
case 'no':
|
||||||
|
case 'oc':
|
||||||
|
case 'om':
|
||||||
|
case 'or':
|
||||||
|
case 'pa':
|
||||||
|
case 'pap':
|
||||||
|
case 'ps':
|
||||||
|
case 'pt':
|
||||||
|
case 'so':
|
||||||
|
case 'sq':
|
||||||
|
case 'sv':
|
||||||
|
case 'sw':
|
||||||
|
case 'ta':
|
||||||
|
case 'te':
|
||||||
|
case 'tk':
|
||||||
|
case 'ur':
|
||||||
|
case 'zu':
|
||||||
|
return 1 === number ? 0 : 1;
|
||||||
|
case 'am':
|
||||||
|
case 'bh':
|
||||||
|
case 'fil':
|
||||||
|
case 'fr':
|
||||||
|
case 'gun':
|
||||||
|
case 'hi':
|
||||||
|
case 'hy':
|
||||||
|
case 'ln':
|
||||||
|
case 'mg':
|
||||||
|
case 'nso':
|
||||||
|
case 'pt_BR':
|
||||||
|
case 'ti':
|
||||||
|
case 'wa':
|
||||||
|
return number < 2 ? 0 : 1;
|
||||||
|
case 'be':
|
||||||
|
case 'bs':
|
||||||
|
case 'hr':
|
||||||
|
case 'ru':
|
||||||
|
case 'sh':
|
||||||
|
case 'sr':
|
||||||
|
case 'uk':
|
||||||
|
return 1 === number % 10 && 11 !== number % 100
|
||||||
|
? 0
|
||||||
|
: number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 10 || number % 100 >= 20)
|
||||||
|
? 1
|
||||||
|
: 2;
|
||||||
|
case 'cs':
|
||||||
|
case 'sk':
|
||||||
|
return 1 === number ? 0 : number >= 2 && number <= 4 ? 1 : 2;
|
||||||
|
case 'ga':
|
||||||
|
return 1 === number ? 0 : 2 === number ? 1 : 2;
|
||||||
|
case 'lt':
|
||||||
|
return 1 === number % 10 && 11 !== number % 100
|
||||||
|
? 0
|
||||||
|
: number % 10 >= 2 && (number % 100 < 10 || number % 100 >= 20)
|
||||||
|
? 1
|
||||||
|
: 2;
|
||||||
|
case 'sl':
|
||||||
|
return 1 === number % 100 ? 0 : 2 === number % 100 ? 1 : 3 === number % 100 || 4 === number % 100 ? 2 : 3;
|
||||||
|
case 'mk':
|
||||||
|
return 1 === number % 10 ? 0 : 1;
|
||||||
|
case 'mt':
|
||||||
|
return 1 === number
|
||||||
|
? 0
|
||||||
|
: 0 === number || (number % 100 > 1 && number % 100 < 11)
|
||||||
|
? 1
|
||||||
|
: number % 100 > 10 && number % 100 < 20
|
||||||
|
? 2
|
||||||
|
: 3;
|
||||||
|
case 'lv':
|
||||||
|
return 0 === number ? 0 : 1 === number % 10 && 11 !== number % 100 ? 1 : 2;
|
||||||
|
case 'pl':
|
||||||
|
return 1 === number
|
||||||
|
? 0
|
||||||
|
: number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 12 || number % 100 > 14)
|
||||||
|
? 1
|
||||||
|
: 2;
|
||||||
|
case 'cy':
|
||||||
|
return 1 === number ? 0 : 2 === number ? 1 : 8 === number || 11 === number ? 2 : 3;
|
||||||
|
case 'ro':
|
||||||
|
return 1 === number ? 0 : 0 === number || (number % 100 > 0 && number % 100 < 20) ? 1 : 2;
|
||||||
|
case 'ar':
|
||||||
|
return 0 === number
|
||||||
|
? 0
|
||||||
|
: 1 === number
|
||||||
|
? 1
|
||||||
|
: 2 === number
|
||||||
|
? 2
|
||||||
|
: number % 100 >= 3 && number % 100 <= 10
|
||||||
|
? 3
|
||||||
|
: number % 100 >= 11 && number % 100 <= 99
|
||||||
|
? 4
|
||||||
|
: 5;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatIntl(id, parameters, locale) {
|
||||||
|
if (id === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
const intlMessage = new IntlMessageFormat(id, [locale.replace('_', '-')], undefined, { ignoreTag: true });
|
||||||
|
parameters = { ...parameters };
|
||||||
|
Object.entries(parameters).forEach(([key, value]) => {
|
||||||
|
if (key.includes('%') || key.includes('{')) {
|
||||||
|
delete parameters[key];
|
||||||
|
parameters[key.replace(/[%{} ]/g, '').trim()] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return intlMessage.format(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
let _locale = null;
|
||||||
|
let _localeFallbacks = {};
|
||||||
|
let _throwWhenNotFound = false;
|
||||||
|
function setLocale(locale) {
|
||||||
|
_locale = locale;
|
||||||
|
}
|
||||||
|
function getLocale() {
|
||||||
|
return (_locale ||
|
||||||
|
document.documentElement.getAttribute('data-symfony-ux-translator-locale') ||
|
||||||
|
(document.documentElement.lang ? document.documentElement.lang.replace('-', '_') : null) ||
|
||||||
|
'en');
|
||||||
|
}
|
||||||
|
function throwWhenNotFound(enabled) {
|
||||||
|
_throwWhenNotFound = enabled;
|
||||||
|
}
|
||||||
|
function setLocaleFallbacks(localeFallbacks) {
|
||||||
|
_localeFallbacks = localeFallbacks;
|
||||||
|
}
|
||||||
|
function getLocaleFallbacks() {
|
||||||
|
return _localeFallbacks;
|
||||||
|
}
|
||||||
|
function trans(message, parameters = {}, domain = 'messages', locale = null) {
|
||||||
|
if (typeof domain === 'undefined') {
|
||||||
|
domain = 'messages';
|
||||||
|
}
|
||||||
|
if (typeof locale === 'undefined' || null === locale) {
|
||||||
|
locale = getLocale();
|
||||||
|
}
|
||||||
|
if (typeof message.translations === 'undefined') {
|
||||||
|
return message.id;
|
||||||
|
}
|
||||||
|
const localesFallbacks = getLocaleFallbacks();
|
||||||
|
const translationsIntl = message.translations[`${domain}+intl-icu`];
|
||||||
|
if (typeof translationsIntl !== 'undefined') {
|
||||||
|
while (typeof translationsIntl[locale] === 'undefined') {
|
||||||
|
locale = localesFallbacks[locale];
|
||||||
|
if (!locale) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (locale) {
|
||||||
|
return formatIntl(translationsIntl[locale], parameters, locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const translations = message.translations[domain];
|
||||||
|
if (typeof translations !== 'undefined') {
|
||||||
|
while (typeof translations[locale] === 'undefined') {
|
||||||
|
locale = localesFallbacks[locale];
|
||||||
|
if (!locale) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (locale) {
|
||||||
|
return format(translations[locale], parameters, locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_throwWhenNotFound) {
|
||||||
|
throw new Error(`No translation message found with id "${message.id}".`);
|
||||||
|
}
|
||||||
|
return message.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { getLocale, getLocaleFallbacks, setLocale, setLocaleFallbacks, throwWhenNotFound, trans };
|
1
assets/ux-translator/dist/utils.d.ts
vendored
Normal file
1
assets/ux-translator/dist/utils.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export declare function strtr(string: string, replacePairs: Record<string, string | number>): string;
|
34
assets/ux-translator/package.json
Normal file
34
assets/ux-translator/package.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "@symfony/ux-translator",
|
||||||
|
"description": "Symfony Translator for JavaScript",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "dist/translator_controller.js",
|
||||||
|
"types": "dist/translator_controller.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "node ../../../bin/build_package.js .",
|
||||||
|
"watch": "node ../../../bin/build_package.js . --watch",
|
||||||
|
"test": "../../../bin/test_package.sh .",
|
||||||
|
"check": "biome check",
|
||||||
|
"ci": "biome ci"
|
||||||
|
},
|
||||||
|
"symfony": {
|
||||||
|
"importmap": {
|
||||||
|
"intl-messageformat": "^10.5.11",
|
||||||
|
"@symfony/ux-translator": "path:%PACKAGE%/dist/translator_controller.js",
|
||||||
|
"@app/translations": "path:var/translations/index.js",
|
||||||
|
"@app/translations/configuration": "path:var/translations/configuration.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"intl-messageformat": "^10.5.11"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"intl-messageformat": {
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"intl-messageformat": "^10.5.11"
|
||||||
|
}
|
||||||
|
}
|
@@ -75,6 +75,7 @@
|
|||||||
"symfony/templating": "^5.4",
|
"symfony/templating": "^5.4",
|
||||||
"symfony/translation": "^5.4",
|
"symfony/translation": "^5.4",
|
||||||
"symfony/twig-bundle": "^5.4",
|
"symfony/twig-bundle": "^5.4",
|
||||||
|
"symfony/ux-translator": "^2.22",
|
||||||
"symfony/validator": "^5.4",
|
"symfony/validator": "^5.4",
|
||||||
"symfony/webpack-encore-bundle": "^1.11",
|
"symfony/webpack-encore-bundle": "^1.11",
|
||||||
"symfony/workflow": "^5.4",
|
"symfony/workflow": "^5.4",
|
||||||
|
@@ -36,4 +36,5 @@ return [
|
|||||||
Chill\BudgetBundle\ChillBudgetBundle::class => ['all' => true],
|
Chill\BudgetBundle\ChillBudgetBundle::class => ['all' => true],
|
||||||
Chill\WopiBundle\ChillWopiBundle::class => ['all' => true],
|
Chill\WopiBundle\ChillWopiBundle::class => ['all' => true],
|
||||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||||
|
Symfony\UX\Translator\UxTranslatorBundle::class => ['all' => true],
|
||||||
];
|
];
|
||||||
|
3
config/packages/ux_translator.yaml
Normal file
3
config/packages/ux_translator.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ux_translator:
|
||||||
|
# The directory where the JavaScript translations are dumped
|
||||||
|
dump_directory: '%kernel.project_dir%/var/translations'
|
107
docs/source/development/translations.rst
Normal file
107
docs/source/development/translations.rst
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
Translations
|
||||||
|
************
|
||||||
|
|
||||||
|
One source of truth
|
||||||
|
===================
|
||||||
|
|
||||||
|
As of January 2025 we have opted to use one source of truth for translations in our backend as well as our frontend.
|
||||||
|
You will find translations still being present in i18ns files for our vue components, but these will slowly be replaced.
|
||||||
|
The goal is to only use the messages.{locale}.yaml files to create our translations and keys.
|
||||||
|
|
||||||
|
Each time we do `symfony console cache:clear` a javascript and typescript file are generated containing all the keys and the corresponding translations.
|
||||||
|
These can then be imported into our vue components together with the `trans` method, for use in the vue templates.
|
||||||
|
|
||||||
|
Vue import example
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
. code-block:: js
|
||||||
|
import {
|
||||||
|
ACTIVITY_BLOC_PERSONS,
|
||||||
|
ACTIVITY_BLOC_PERSONS_ASSOCIATED,
|
||||||
|
ACTIVITY_BLOC_THIRDPARTY,
|
||||||
|
ACTIVITY_BLOC_USERS,
|
||||||
|
ACTIVITY_ADD_PERSONS,
|
||||||
|
trans,
|
||||||
|
} from "translator";
|
||||||
|
|
||||||
|
Setup
|
||||||
|
=====
|
||||||
|
|
||||||
|
For development purposes we generally make use of the chill-bundles standalone project. Here the new translation setup will work out of the box.
|
||||||
|
|
||||||
|
However when working on a customer chill instance (with a root project and a chill-bundles implementation) it is required to execute the chill translations recipe
|
||||||
|
using the command
|
||||||
|
|
||||||
|
Translation key conventions
|
||||||
|
===========================
|
||||||
|
|
||||||
|
When adding new translation keys we have chosen to adhere to the following conventions as of April 2025.
|
||||||
|
Older translation keys will gradually be adapted to respect these conventions.
|
||||||
|
|
||||||
|
Conventions
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
Entity related messages
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Translation keys will be structured as followed as follows:
|
||||||
|
|
||||||
|
`[bundle].[entity].[page or component].[action / message]`
|
||||||
|
|
||||||
|
. code-block:: yaml
|
||||||
|
person:
|
||||||
|
household:
|
||||||
|
index:
|
||||||
|
edit_comment: "Mettre à jour le commentaire"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
So the key to be used will be `person.household.index.edit_comment` when used in a twig template
|
||||||
|
or
|
||||||
|
`PERSON_HOUSEHOLD_INDEX_EDIT_COMMENT` when used in a vue component.
|
||||||
|
|
||||||
|
|
||||||
|
Export related messages
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Translation keys will be structured as followed as follows:
|
||||||
|
|
||||||
|
[bundle]
|
||||||
|
|
|
||||||
|
|__ export
|
||||||
|
|
|
||||||
|
|__ ['count | list' | 'filter' | 'aggregator']
|
||||||
|
|
|
||||||
|
|__ [export | filter | aggregator - name] OR [ properties (end of hierarchy) ]
|
||||||
|
|
|
||||||
|
|__ [action / message]
|
||||||
|
|
||||||
|
ex. Filter
|
||||||
|
|
||||||
|
. code-block:: yaml
|
||||||
|
activity:
|
||||||
|
export:
|
||||||
|
filter:
|
||||||
|
by_users_job:
|
||||||
|
title: Filtrer les échanges par type
|
||||||
|
'Filtered activity by users job: only %jobs%': 'Filtré par métier d''au moins un utilisateur participant: seulement %jobs%'
|
||||||
|
|
||||||
|
ex. Export type
|
||||||
|
|
||||||
|
. code-block:: yaml
|
||||||
|
activity:
|
||||||
|
export:
|
||||||
|
count:
|
||||||
|
count_persons_on_activity:
|
||||||
|
title: Nombre d'usagers concernés par les échanges
|
||||||
|
list:
|
||||||
|
activities_by_parcours:
|
||||||
|
title: Liste des échanges liés à un parcours
|
||||||
|
|
||||||
|
ex. Export properties shared by a certain export type
|
||||||
|
|
||||||
|
. code-block:: yaml
|
||||||
|
activity:
|
||||||
|
export:
|
||||||
|
list:
|
||||||
|
users ids: Identifiant des utilisateurs
|
@@ -29,8 +29,7 @@ We strongly encourage you to initialize a git repository at this step, to track
|
|||||||
# add the flex endpoints required for custom recipes
|
# add the flex endpoints required for custom recipes
|
||||||
cat <<< "$(jq '.extra.symfony += {"endpoint": ["flex://defaults", "https://gitlab.com/api/v4/projects/57371968/repository/files/index.json/raw?ref=main"]}' composer.json)" > composer.json
|
cat <<< "$(jq '.extra.symfony += {"endpoint": ["flex://defaults", "https://gitlab.com/api/v4/projects/57371968/repository/files/index.json/raw?ref=main"]}' composer.json)" > composer.json
|
||||||
# install chill and some dependencies
|
# install chill and some dependencies
|
||||||
# TODO fix the suffix "alpha1" and replace by ^3.0.0 when version 3.0.0 will be released
|
symfony composer require chill-project/chill-bundles ^3.7.1 champs-libres/wopi-lib dev-master@dev champs-libres/wopi-bundle dev-master@dev symfony/amqp-messenger
|
||||||
symfony composer require chill-project/chill-bundles v3.0.0-RC3 champs-libres/wopi-lib dev-master@dev champs-libres/wopi-bundle dev-master@dev
|
|
||||||
|
|
||||||
We encourage you to accept the inclusion of the "Docker configuration from recipes": this is the documented way to run the database.
|
We encourage you to accept the inclusion of the "Docker configuration from recipes": this is the documented way to run the database.
|
||||||
You must also accept to configure recipes from the contrib repository, unless you want to configure the bundles manually).
|
You must also accept to configure recipes from the contrib repository, unless you want to configure the bundles manually).
|
||||||
@@ -48,7 +47,7 @@ You must also accept to configure recipes from the contrib repository, unless yo
|
|||||||
|
|
||||||
If you encounter this error during assets compilation (:code:`yarn run encore production`) (repeated multiple times):
|
If you encounter this error during assets compilation (:code:`yarn run encore production`) (repeated multiple times):
|
||||||
|
|
||||||
.. code-block:: txt
|
.. code-block::
|
||||||
|
|
||||||
[tsl] ERROR in /tmp/chill/v1/public/bundles/chillcalendar/types.ts(2,65)
|
[tsl] ERROR in /tmp/chill/v1/public/bundles/chillcalendar/types.ts(2,65)
|
||||||
TS2307: Cannot find module '../../../ChillMainBundle/Resources/public/types' or its corresponding type declarations.
|
TS2307: Cannot find module '../../../ChillMainBundle/Resources/public/types' or its corresponding type declarations.
|
||||||
@@ -74,14 +73,22 @@ or in the :code:`.env.local` file, which should not be committed to the git repo
|
|||||||
You do not need to set variables for the smtp server, redis server and relatorio server, as they are generated automatically
|
You do not need to set variables for the smtp server, redis server and relatorio server, as they are generated automatically
|
||||||
by the symfony server, from the docker compose services.
|
by the symfony server, from the docker compose services.
|
||||||
|
|
||||||
The only required variable is the :code:`ADMIN_PASSWORD`. You can generate a hashed and salted admin password using the command
|
The required variables are:
|
||||||
:code:`symfony console security:hash-password <your password> 'Symfony\Component\Security\Core\User\User'`. Then,
|
|
||||||
|
- the :code:`ADMIN_PASSWORD`;
|
||||||
|
- the :code:`OVHCLOUD_DSN` variable;
|
||||||
|
|
||||||
|
:code:`ADMIN_PASSWORD`
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
You can generate a hashed and salted admin password using the command
|
||||||
|
:code:`symfony console security:hash-password <your password> 'Symfony\Component\Security\Core\User\User'`.Then,
|
||||||
you can either:
|
you can either:
|
||||||
|
|
||||||
- add this password to the :code:`.env.local` file, you must escape the character :code:`$`: if the generated password
|
- add this password to the :code:`.env.local` file, you must escape the character :code:`$`: if the generated password
|
||||||
is :code:`$2y$13$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm`, your :code:`.env.local` file will be:
|
is :code:`$2y$13$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm`, your :code:`.env.local` file will be:
|
||||||
|
|
||||||
.. code-block:: env
|
.. code-block:: bash
|
||||||
|
|
||||||
ADMIN_PASSWORD=\$2y\$13\$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm
|
ADMIN_PASSWORD=\$2y\$13\$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm
|
||||||
# note: if you copy-paste the line above, the password will be "admin".
|
# note: if you copy-paste the line above, the password will be "admin".
|
||||||
@@ -89,12 +96,24 @@ you can either:
|
|||||||
- add the generated password to the secrets manager (**note**: you must add the generated hashed password to the secrets env,
|
- add the generated password to the secrets manager (**note**: you must add the generated hashed password to the secrets env,
|
||||||
not the password in clear text).
|
not the password in clear text).
|
||||||
|
|
||||||
- set up the jwt authentication bundle
|
:code:`OVHCLOUD_DSN` and sending SMS messages
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This is a temporary dependency, for ensuring compatibility for previous behaviour.
|
||||||
|
|
||||||
|
You can set it to :code:`null://null` if you do not plan to use sending SMS.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
OVHCLOUD_DSN=null://null
|
||||||
|
|
||||||
|
If you plan to do it, you can configure the notifier component `as described in the symfony documentation <https://symfony.com/doc/current/notifier.html#notifier-sms-channel>`_.
|
||||||
|
|
||||||
|
|
||||||
Some environment variables are available for the JWT authentication bundle in the :code:`.env` file.
|
Some environment variables are available for the JWT authentication bundle in the :code:`.env` file.
|
||||||
|
|
||||||
Prepare migrations and other tools
|
Prepare database, messenger queue, and other configuration
|
||||||
----------------------------------
|
----------------------------------------------------------
|
||||||
|
|
||||||
To continue the installation process, you will have to run migrations:
|
To continue the installation process, you will have to run migrations:
|
||||||
|
|
||||||
@@ -109,17 +128,22 @@ To continue the installation process, you will have to run migrations:
|
|||||||
symfony console messenger:setup-transports
|
symfony console messenger:setup-transports
|
||||||
# prepare some views
|
# prepare some views
|
||||||
symfony console chill:db:sync-views
|
symfony console chill:db:sync-views
|
||||||
|
# load languages data
|
||||||
|
symfony console chill:main:languages:populate
|
||||||
# generate jwt token, required for some api features (webdav access, ...)
|
# generate jwt token, required for some api features (webdav access, ...)
|
||||||
symfony console lexik:jwt:generate-keypair
|
symfony console lexik:jwt:generate-keypair
|
||||||
|
|
||||||
.. warning::
|
.. note::
|
||||||
|
|
||||||
If you encounter an error while running :code:`symfony console messenger:setup-transports`, you can set up the messenger
|
If you encounter this error:
|
||||||
transport to redis, by adding this in the :code:`.env.local` or :code:`.env` file:
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
No transport supports the given Messenger DSN.
|
||||||
|
|
||||||
|
Please check that you installed the package `symfony/amqp-messenger`.
|
||||||
|
|
||||||
.. code-block:: env
|
|
||||||
|
|
||||||
MESSENGER_TRANSPORT_DSN=redis://${REDIS_HOST}:${REDIS_PORT}/messages
|
|
||||||
|
|
||||||
Start your web server locally
|
Start your web server locally
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
@@ -41,16 +41,18 @@ Postal code are loaded from this database. There is no need to load postal codes
|
|||||||
The data are prepared for Chill (`See this repository <https://gitea.champs-libres.be/Chill-project/belgian-bestaddresses-transform/releases>`_).
|
The data are prepared for Chill (`See this repository <https://gitea.champs-libres.be/Chill-project/belgian-bestaddresses-transform/releases>`_).
|
||||||
One can select postal code by his first number (:code:`1xxx` for postal codes from 1000 to 1999), or a limited list for development purpose.
|
One can select postal code by his first number (:code:`1xxx` for postal codes from 1000 to 1999), or a limited list for development purpose.
|
||||||
|
|
||||||
|
The command expects a language code as first argument.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# load postal code from 1000 to 3999:
|
# load postal code from 1000 to 3999:
|
||||||
bin/console chill:main:address-ref-from-best-addresse 1xxx 2xxx 3xxx
|
bin/console chill:main:address-ref-from-best-addresse fr 1xxx 2xxx 3xxx
|
||||||
|
|
||||||
# load only an extract (for dev purposes)
|
# load only an extract (for dev purposes)
|
||||||
bin/console chill:main:address-ref-from-best-addresse extract
|
bin/console chill:main:address-ref-from-best-addresse fr extract
|
||||||
|
|
||||||
# load full addresses (discouraged)
|
# load full addresses (discouraged)
|
||||||
bin/console chill:main:address-ref-from-best-addresse full
|
bin/console chill:main:address-ref-from-best-addresse fr full
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@@ -34,6 +34,7 @@ export default ts.config(
|
|||||||
// override/add rules settings here, such as:
|
// override/add rules settings here, such as:
|
||||||
"vue/multi-word-component-names": "off",
|
"vue/multi-word-component-names": "off",
|
||||||
"@typescript-eslint/no-require-imports": "off",
|
"@typescript-eslint/no-require-imports": "off",
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
16
package.json
16
package.json
@@ -6,15 +6,11 @@
|
|||||||
"@apidevtools/swagger-cli": "^4.0.4",
|
"@apidevtools/swagger-cli": "^4.0.4",
|
||||||
"@babel/core": "^7.20.5",
|
"@babel/core": "^7.20.5",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@ckeditor/ckeditor5-build-classic": "^41.4.2",
|
"@ckeditor/ckeditor5-vue": "^7.3.0",
|
||||||
"@ckeditor/ckeditor5-dev-translations": "^40.2.0",
|
|
||||||
"@ckeditor/ckeditor5-dev-utils": "^40.2.0",
|
|
||||||
"@ckeditor/ckeditor5-dev-webpack-plugin": "^31.1.13",
|
|
||||||
"@ckeditor/ckeditor5-markdown-gfm": "^41.4.2",
|
|
||||||
"@ckeditor/ckeditor5-theme-lark": "^41.4.2",
|
|
||||||
"@ckeditor/ckeditor5-vue": "^5.1.0",
|
|
||||||
"@eslint/js": "^9.14.0",
|
"@eslint/js": "^9.14.0",
|
||||||
|
"@hotwired/stimulus": "^3.0.0",
|
||||||
"@luminateone/eslint-baseline": "^1.0.9",
|
"@luminateone/eslint-baseline": "^1.0.9",
|
||||||
|
"@symfony/stimulus-bridge": "^3.2.0",
|
||||||
"@symfony/webpack-encore": "^4.1.0",
|
"@symfony/webpack-encore": "^4.1.0",
|
||||||
"@tsconfig/node20": "^20.1.4",
|
"@tsconfig/node20": "^20.1.4",
|
||||||
"@types/dompurify": "^3.0.5",
|
"@types/dompurify": "^3.0.5",
|
||||||
@@ -23,12 +19,14 @@
|
|||||||
"bindings": "^1.5.0",
|
"bindings": "^1.5.0",
|
||||||
"bootstrap": "5.2.3",
|
"bootstrap": "5.2.3",
|
||||||
"chokidar": "^3.5.1",
|
"chokidar": "^3.5.1",
|
||||||
|
"ckeditor5": "^44.1.0",
|
||||||
"dompurify": "^3.1.0",
|
"dompurify": "^3.1.0",
|
||||||
"eslint": "^9.14.0",
|
"eslint": "^9.14.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-vue": "^9.30.0",
|
"eslint-plugin-vue": "^9.30.0",
|
||||||
"fork-awesome": "^1.1.7",
|
"fork-awesome": "^1.1.7",
|
||||||
|
"intl-messageformat": "^10.5.11",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"node-sass": "^8.0.0",
|
"node-sass": "^8.0.0",
|
||||||
"popper.js": "^1.16.1",
|
"popper.js": "^1.16.1",
|
||||||
@@ -54,11 +52,13 @@
|
|||||||
"@fullcalendar/timegrid": "^6.1.4",
|
"@fullcalendar/timegrid": "^6.1.4",
|
||||||
"@fullcalendar/vue3": "^6.1.4",
|
"@fullcalendar/vue3": "^6.1.4",
|
||||||
"@popperjs/core": "^2.9.2",
|
"@popperjs/core": "^2.9.2",
|
||||||
|
"@tsconfig/node20": "^20.1.4",
|
||||||
"@types/dompurify": "^3.0.5",
|
"@types/dompurify": "^3.0.5",
|
||||||
"@types/leaflet": "^1.9.3",
|
"@types/leaflet": "^1.9.3",
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
"dropzone": "^5.7.6",
|
"dropzone": "^5.7.6",
|
||||||
"es6-promise": "^4.2.8",
|
"es6-promise": "^4.2.8",
|
||||||
|
"intl-messageformat": "^10.5.11",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
"marked": "^12.0.2",
|
"marked": "^12.0.2",
|
||||||
"masonry-layout": "^4.2.2",
|
"masonry-layout": "^4.2.2",
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
"vuex": "^4.0.0"
|
"vuex": "^4.0.0"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"Firefox ESR"
|
"defaults and fully supports es6-module and not dead"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev-server": "encore dev-server",
|
"dev-server": "encore dev-server",
|
||||||
|
@@ -30,13 +30,14 @@
|
|||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li class="add-persons">
|
<li class="add-persons">
|
||||||
<add-persons
|
<add-persons
|
||||||
button-title="activity.add_persons"
|
:buttonTitle="trans(ACTIVITY_ADD_PERSONS)"
|
||||||
modal-title="activity.add_persons"
|
:modalTitle="trans(ACTIVITY_ADD_PERSONS)"
|
||||||
:key="addPersons.key"
|
v-bind:key="addPersons.key"
|
||||||
:options="addPersonsOptions"
|
v-bind:options="addPersonsOptions"
|
||||||
@add-new-persons="addNewPersons"
|
@addNewPersons="addNewPersons"
|
||||||
ref="addPersons"
|
ref="addPersons"
|
||||||
/>
|
>
|
||||||
|
</add-persons>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</teleport>
|
</teleport>
|
||||||
@@ -47,6 +48,14 @@ import { mapState, mapGetters } from "vuex";
|
|||||||
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
||||||
import PersonsBloc from "./ConcernedGroups/PersonsBloc.vue";
|
import PersonsBloc from "./ConcernedGroups/PersonsBloc.vue";
|
||||||
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
||||||
|
import {
|
||||||
|
ACTIVITY_BLOC_PERSONS,
|
||||||
|
ACTIVITY_BLOC_PERSONS_ASSOCIATED,
|
||||||
|
ACTIVITY_BLOC_THIRDPARTY,
|
||||||
|
ACTIVITY_BLOC_USERS,
|
||||||
|
ACTIVITY_ADD_PERSONS,
|
||||||
|
trans,
|
||||||
|
} from "translator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ConcernedGroups",
|
name: "ConcernedGroups",
|
||||||
@@ -55,18 +64,24 @@ export default {
|
|||||||
PersonsBloc,
|
PersonsBloc,
|
||||||
PersonText,
|
PersonText,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
trans,
|
||||||
|
ACTIVITY_ADD_PERSONS,
|
||||||
|
};
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
personsBlocs: [
|
personsBlocs: [
|
||||||
{
|
{
|
||||||
key: "persons",
|
key: "persons",
|
||||||
title: "activity.bloc_persons",
|
title: trans(ACTIVITY_BLOC_PERSONS),
|
||||||
persons: [],
|
persons: [],
|
||||||
included: false,
|
included: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "personsAssociated",
|
key: "personsAssociated",
|
||||||
title: "activity.bloc_persons_associated",
|
title: trans(ACTIVITY_BLOC_PERSONS_ASSOCIATED),
|
||||||
persons: [],
|
persons: [],
|
||||||
included: window.activity
|
included: window.activity
|
||||||
? window.activity.activityType.personsVisible !== 0
|
? window.activity.activityType.personsVisible !== 0
|
||||||
@@ -82,7 +97,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "thirdparty",
|
key: "thirdparty",
|
||||||
title: "activity.bloc_thirdparty",
|
title: trans(ACTIVITY_BLOC_THIRDPARTY),
|
||||||
persons: [],
|
persons: [],
|
||||||
included: window.activity
|
included: window.activity
|
||||||
? window.activity.activityType.thirdPartiesVisible !== 0
|
? window.activity.activityType.thirdPartiesVisible !== 0
|
||||||
@@ -90,7 +105,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "users",
|
key: "users",
|
||||||
title: "activity.bloc_users",
|
title: trans(ACTIVITY_BLOC_USERS),
|
||||||
persons: [],
|
persons: [],
|
||||||
included: window.activity
|
included: window.activity
|
||||||
? window.activity.activityType.usersVisible !== 0
|
? window.activity.activityType.usersVisible !== 0
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<teleport to="#location">
|
<teleport to="#location">
|
||||||
<div class="mb-3 row">
|
<div class="mb-3 row">
|
||||||
<label :class="locationClassList">
|
<label :class="locationClassList">
|
||||||
{{ $t("activity.location") }}
|
{{ trans(ACTIVITY_LOCATION) }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<VueMultiselect
|
<VueMultiselect
|
||||||
@@ -13,17 +13,17 @@
|
|||||||
open-direction="top"
|
open-direction="top"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:searchable="true"
|
:searchable="true"
|
||||||
:placeholder="$t('activity.choose_location')"
|
:placeholder="trans(ACTIVITY_CHOOSE_LOCATION)"
|
||||||
:custom-label="customLabel"
|
:custom-label="customLabel"
|
||||||
:select-label="$t('multiselect.select_label')"
|
:select-label="trans(MULTISELECT_SELECT_LABEL)"
|
||||||
:deselect-label="$t('multiselect.deselect_label')"
|
:deselect-label="trans(MULTISELECT_DESELECT_LABEL)"
|
||||||
:selected-label="$t('multiselect.selected_label')"
|
:selected-label="trans(MULTISELECT_SELECTED_LABEL)"
|
||||||
:options="availableLocations"
|
:options="availableLocations"
|
||||||
group-values="locations"
|
group-values="locations"
|
||||||
group-label="locationGroup"
|
group-label="locationGroup"
|
||||||
v-model="location"
|
v-model="location"
|
||||||
/>
|
/>
|
||||||
<new-location :available-locations="availableLocations" />
|
<new-location v-bind:available-locations="availableLocations" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</teleport>
|
</teleport>
|
||||||
@@ -33,6 +33,14 @@
|
|||||||
import { mapState, mapGetters } 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 {
|
||||||
|
trans,
|
||||||
|
ACTIVITY_LOCATION,
|
||||||
|
ACTIVITY_CHOOSE_LOCATION,
|
||||||
|
MULTISELECT_SELECT_LABEL,
|
||||||
|
MULTISELECT_DESELECT_LABEL,
|
||||||
|
MULTISELECT_SELECTED_LABEL,
|
||||||
|
} from "translator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Location",
|
name: "Location",
|
||||||
@@ -40,6 +48,16 @@ export default {
|
|||||||
NewLocation,
|
NewLocation,
|
||||||
VueMultiselect,
|
VueMultiselect,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
trans,
|
||||||
|
ACTIVITY_LOCATION,
|
||||||
|
ACTIVITY_CHOOSE_LOCATION,
|
||||||
|
MULTISELECT_SELECT_LABEL,
|
||||||
|
MULTISELECT_DESELECT_LABEL,
|
||||||
|
MULTISELECT_SELECTED_LABEL,
|
||||||
|
};
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
locationClassList: `col-form-label col-sm-4 ${document.querySelector("input#chill_activitybundle_activity_location").getAttribute("required") ? "required" : ""}`,
|
locationClassList: `col-form-label col-sm-4 ${document.querySelector("input#chill_activitybundle_activity_location").getAttribute("required") ? "required" : ""}`,
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li>
|
<li>
|
||||||
<a class="btn btn-sm btn-create" @click="openModal">
|
<a class="btn btn-sm btn-create" @click="openModal">
|
||||||
{{ $t("activity.create_new_location") }}
|
{{ trans(ACTIVITY_CREATE_NEW_LOCATION) }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -11,12 +11,12 @@
|
|||||||
<teleport to="body">
|
<teleport to="body">
|
||||||
<modal
|
<modal
|
||||||
v-if="modal.showModal"
|
v-if="modal.showModal"
|
||||||
:modal-dialog-class="modal.modalDialogClass"
|
:modalDialogClass="modal.modalDialogClass"
|
||||||
@close="modal.showModal = false"
|
@close="modal.showModal = false"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3 class="modal-title">
|
<h3 class="modal-title">
|
||||||
{{ $t("activity.create_new_location") }}
|
{{ trans(ACTIVITY_CREATE_NEW_LOCATION) }}
|
||||||
</h3>
|
</h3>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
v-model="selectType"
|
v-model="selectType"
|
||||||
>
|
>
|
||||||
<option selected disabled value="">
|
<option selected disabled value="">
|
||||||
{{ $t("activity.choose_location_type") }}
|
{{ trans(ACTIVITY_CHOOSE_LOCATION_TYPE) }}
|
||||||
</option>
|
</option>
|
||||||
<option
|
<option
|
||||||
v-for="t in locationTypes"
|
v-for="t in locationTypes"
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<label>{{
|
<label>{{
|
||||||
$t("activity.location_fields.type")
|
trans(ACTIVITY_LOCATION_FIELDS_TYPE)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -60,14 +60,14 @@
|
|||||||
placeholder
|
placeholder
|
||||||
/>
|
/>
|
||||||
<label for="name">{{
|
<label for="name">{{
|
||||||
$t("activity.location_fields.name")
|
trans(ACTIVITY_LOCATION_FIELDS_NAME)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<add-address
|
<add-address
|
||||||
:context="addAddress.context"
|
:context="addAddress.context"
|
||||||
:options="addAddress.options"
|
:options="addAddress.options"
|
||||||
:address-changed-callback="submitNewAddress"
|
:addressChangedCallback="submitNewAddress"
|
||||||
v-if="showAddAddress"
|
v-if="showAddAddress"
|
||||||
ref="addAddress"
|
ref="addAddress"
|
||||||
/>
|
/>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
placeholder
|
placeholder
|
||||||
/>
|
/>
|
||||||
<label for="phonenumber1">{{
|
<label for="phonenumber1">{{
|
||||||
$t("activity.location_fields.phonenumber1")
|
trans(ACTIVITY_LOCATION_FIELDS_PHONENUMBER1)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-floating mb-3" v-if="hasPhonenumber1">
|
<div class="form-floating mb-3" v-if="hasPhonenumber1">
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
placeholder
|
placeholder
|
||||||
/>
|
/>
|
||||||
<label for="phonenumber2">{{
|
<label for="phonenumber2">{{
|
||||||
$t("activity.location_fields.phonenumber2")
|
trans(ACTIVITY_LOCATION_FIELDS_PHONENUMBER2)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-floating mb-3" v-if="showContactData">
|
<div class="form-floating mb-3" v-if="showContactData">
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
placeholder
|
placeholder
|
||||||
/>
|
/>
|
||||||
<label for="email">{{
|
<label for="email">{{
|
||||||
$t("activity.location_fields.email")
|
trans(ACTIVITY_LOCATION_FIELDS_EMAIL)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
class="btn btn-save"
|
class="btn btn-save"
|
||||||
@click.prevent="saveNewLocation"
|
@click.prevent="saveNewLocation"
|
||||||
>
|
>
|
||||||
{{ $t("action.save") }}
|
{{ trans(SAVE) }}
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</modal>
|
||||||
@@ -126,6 +126,17 @@ import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue"
|
|||||||
import { mapState } from "vuex";
|
import { mapState } from "vuex";
|
||||||
import { getLocationTypes } from "../../api";
|
import { getLocationTypes } from "../../api";
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
|
import {
|
||||||
|
SAVE,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_EMAIL,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_PHONENUMBER1,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_PHONENUMBER2,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_NAME,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_TYPE,
|
||||||
|
ACTIVITY_CHOOSE_LOCATION_TYPE,
|
||||||
|
ACTIVITY_CREATE_NEW_LOCATION,
|
||||||
|
trans,
|
||||||
|
} from "translator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "NewLocation",
|
name: "NewLocation",
|
||||||
@@ -133,6 +144,19 @@ export default {
|
|||||||
Modal,
|
Modal,
|
||||||
AddAddress,
|
AddAddress,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
trans,
|
||||||
|
SAVE,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_EMAIL,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_PHONENUMBER1,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_PHONENUMBER2,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_NAME,
|
||||||
|
ACTIVITY_LOCATION_FIELDS_TYPE,
|
||||||
|
ACTIVITY_CHOOSE_LOCATION_TYPE,
|
||||||
|
ACTIVITY_CREATE_NEW_LOCATION,
|
||||||
|
};
|
||||||
|
},
|
||||||
props: ["availableLocations"],
|
props: ["availableLocations"],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
<div class="mb-3 row">
|
<div class="mb-3 row">
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<label :class="socialIssuesClassList">{{
|
<label :class="socialIssuesClassList">{{
|
||||||
$t("activity.social_issues")
|
trans(ACTIVITY_SOCIAL_ISSUES)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
@@ -12,8 +12,9 @@
|
|||||||
:key="issue.id"
|
:key="issue.id"
|
||||||
:issue="issue"
|
:issue="issue"
|
||||||
:selection="socialIssuesSelected"
|
:selection="socialIssuesSelected"
|
||||||
@update-selected="updateIssuesSelected"
|
@updateSelected="updateIssuesSelected"
|
||||||
/>
|
>
|
||||||
|
</check-social-issue>
|
||||||
|
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<VueMultiselect
|
<VueMultiselect
|
||||||
@@ -31,10 +32,11 @@
|
|||||||
:allow-empty="true"
|
:allow-empty="true"
|
||||||
:show-labels="false"
|
:show-labels="false"
|
||||||
:loading="issueIsLoading"
|
:loading="issueIsLoading"
|
||||||
:placeholder="$t('activity.choose_other_social_issue')"
|
:placeholder="trans(ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE)"
|
||||||
:options="socialIssuesOther"
|
:options="socialIssuesOther"
|
||||||
@select="addIssueInList"
|
@select="addIssueInList"
|
||||||
/>
|
>
|
||||||
|
</VueMultiselect>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -42,35 +44,46 @@
|
|||||||
<div class="mb-3 row">
|
<div class="mb-3 row">
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<label :class="socialActionsClassList">{{
|
<label :class="socialActionsClassList">{{
|
||||||
$t("activity.social_actions")
|
trans(ACTIVITY_SOCIAL_ACTIONS)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
<div v-if="actionIsLoading === true">
|
<div v-if="actionIsLoading === true">
|
||||||
<i class="chill-green fa fa-circle-o-notch fa-spin fa-lg" />
|
<i
|
||||||
|
class="chill-green fa fa-circle-o-notch fa-spin fa-lg"
|
||||||
|
></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
v-else-if="socialIssuesSelected.length === 0"
|
v-else-if="socialIssuesSelected.length === 0"
|
||||||
class="inline-choice chill-no-data-statement mt-3"
|
class="inline-choice chill-no-data-statement mt-3"
|
||||||
>
|
>
|
||||||
{{ $t("activity.select_first_a_social_issue") }}
|
{{ trans(ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE) }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<template v-else-if="socialActionsList.length > 0">
|
<template
|
||||||
|
v-else-if="
|
||||||
|
socialActionsList.length > 0 &&
|
||||||
|
(socialIssuesSelected.length ||
|
||||||
|
socialActionsSelected.length)
|
||||||
|
"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-if="
|
id="actionsList"
|
||||||
socialIssuesSelected.length ||
|
v-for="group in socialActionsList"
|
||||||
socialActionsSelected.length
|
:key="group.issue"
|
||||||
"
|
|
||||||
>
|
>
|
||||||
|
<span class="badge bg-chill-l-gray text-dark">{{
|
||||||
|
group.issue
|
||||||
|
}}</span>
|
||||||
<check-social-action
|
<check-social-action
|
||||||
v-for="action in socialActionsList"
|
v-for="action in group.actions"
|
||||||
:key="action.id"
|
:key="action.id"
|
||||||
:action="action"
|
:action="action"
|
||||||
:selection="socialActionsSelected"
|
:selection="socialActionsSelected"
|
||||||
@update-selected="updateActionsSelected"
|
@updateSelected="updateActionsSelected"
|
||||||
/>
|
>
|
||||||
|
</check-social-action>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -80,7 +93,7 @@
|
|||||||
"
|
"
|
||||||
class="inline-choice chill-no-data-statement mt-3"
|
class="inline-choice chill-no-data-statement mt-3"
|
||||||
>
|
>
|
||||||
{{ $t("activity.social_action_list_empty") }}
|
{{ trans(ACTIVITY_SOCIAL_ACTION_LIST_EMPTY) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -92,6 +105,14 @@ import VueMultiselect from "vue-multiselect";
|
|||||||
import CheckSocialIssue from "./SocialIssuesAcc/CheckSocialIssue.vue";
|
import CheckSocialIssue from "./SocialIssuesAcc/CheckSocialIssue.vue";
|
||||||
import CheckSocialAction from "./SocialIssuesAcc/CheckSocialAction.vue";
|
import CheckSocialAction from "./SocialIssuesAcc/CheckSocialAction.vue";
|
||||||
import { getSocialIssues, getSocialActionByIssue } from "../api.js";
|
import { getSocialIssues, getSocialActionByIssue } from "../api.js";
|
||||||
|
import {
|
||||||
|
ACTIVITY_SOCIAL_ACTION_LIST_EMPTY,
|
||||||
|
ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE,
|
||||||
|
ACTIVITY_SOCIAL_ACTIONS,
|
||||||
|
ACTIVITY_SOCIAL_ISSUES,
|
||||||
|
ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE,
|
||||||
|
trans,
|
||||||
|
} from "translator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "SocialIssuesAcc",
|
name: "SocialIssuesAcc",
|
||||||
@@ -100,6 +121,16 @@ export default {
|
|||||||
CheckSocialAction,
|
CheckSocialAction,
|
||||||
VueMultiselect,
|
VueMultiselect,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
trans,
|
||||||
|
ACTIVITY_SOCIAL_ACTION_LIST_EMPTY,
|
||||||
|
ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE,
|
||||||
|
ACTIVITY_SOCIAL_ACTIONS,
|
||||||
|
ACTIVITY_SOCIAL_ISSUES,
|
||||||
|
ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE,
|
||||||
|
};
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
issueIsLoading: false,
|
issueIsLoading: false,
|
||||||
@@ -127,53 +158,44 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
/* Load others issues in multiselect
|
/* Load other issues in multiselect */
|
||||||
*/
|
|
||||||
this.issueIsLoading = true;
|
this.issueIsLoading = true;
|
||||||
this.actionAreLoaded = false;
|
this.actionAreLoaded = false;
|
||||||
getSocialIssues().then(
|
|
||||||
(response) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
this.$store.commit("updateIssuesOther", response.results);
|
|
||||||
|
|
||||||
/* Add in list the issues already associated (if not yet listed)
|
getSocialIssues().then((response) => {
|
||||||
*/
|
/* Add issues to the store */
|
||||||
this.socialIssuesSelected.forEach((issue) => {
|
this.$store.commit("updateIssuesOther", response);
|
||||||
if (
|
|
||||||
this.socialIssuesList.filter(
|
|
||||||
(i) => i.id === issue.id,
|
|
||||||
).length !== 1
|
|
||||||
) {
|
|
||||||
this.$store.commit("addIssueInList", issue);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
/* Remove from multiselect the issues that are not yet in checkbox list
|
/* Add in list the issues already associated (if not yet listed) */
|
||||||
*/
|
this.socialIssuesSelected.forEach((issue) => {
|
||||||
this.socialIssuesList.forEach((issue) => {
|
if (
|
||||||
this.$store.commit("removeIssueInOther", issue);
|
this.socialIssuesList.filter((i) => i.id === issue.id)
|
||||||
}, this);
|
.length !== 1
|
||||||
|
) {
|
||||||
|
this.$store.commit("addIssueInList", issue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* Filter issues
|
/* Remove from multiselect the issues that are not yet in the checkbox list */
|
||||||
*/
|
this.socialIssuesList.forEach((issue) => {
|
||||||
this.$store.commit("filterList", "issues");
|
this.$store.commit("removeIssueInOther", issue);
|
||||||
|
});
|
||||||
|
|
||||||
/* Add in list the actions already associated (if not yet listed)
|
/* Filter issues */
|
||||||
*/
|
this.$store.commit("filterList", "issues");
|
||||||
this.socialActionsSelected.forEach((action) => {
|
|
||||||
this.$store.commit("addActionInList", action);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
/* Filter issues
|
/* Add in list the actions already associated (if not yet listed) */
|
||||||
*/
|
this.socialActionsSelected.forEach((action) => {
|
||||||
this.$store.commit("filterList", "actions");
|
this.$store.commit("addActionInList", action);
|
||||||
|
});
|
||||||
|
|
||||||
this.issueIsLoading = false;
|
/* Filter actions */
|
||||||
this.actionAreLoaded = true;
|
this.$store.commit("filterList", "actions");
|
||||||
this.updateActionsList();
|
|
||||||
resolve();
|
this.issueIsLoading = false;
|
||||||
}),
|
this.actionAreLoaded = true;
|
||||||
);
|
this.updateActionsList();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/* When choosing an issue in multiselect, add it in checkboxes (as selected),
|
/* When choosing an issue in multiselect, add it in checkboxes (as selected),
|
||||||
@@ -208,7 +230,7 @@ export default {
|
|||||||
this.actionIsLoading = true;
|
this.actionIsLoading = true;
|
||||||
getSocialActionByIssue(item.id).then(
|
getSocialActionByIssue(item.id).then(
|
||||||
(actions) =>
|
(actions) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve) => {
|
||||||
actions.results.forEach((action) => {
|
actions.results.forEach((action) => {
|
||||||
this.$store.commit("addActionInList", action);
|
this.$store.commit("addActionInList", action);
|
||||||
}, this);
|
}, this);
|
||||||
@@ -235,9 +257,24 @@ export default {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@import "ChillMainAssets/module/bootstrap/shared";
|
||||||
|
@import "ChillPersonAssets/chill/scss/mixins";
|
||||||
|
@import "ChillMainAssets/chill/scss/chill_variables";
|
||||||
|
|
||||||
span.multiselect__single {
|
span.multiselect__single {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#actionsList {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 0.5rem;
|
||||||
|
background-color: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.badge {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
@include badge_social($social-issue-color);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -10,7 +10,9 @@
|
|||||||
:value="action"
|
:value="action"
|
||||||
/>
|
/>
|
||||||
<label class="form-check-label" :for="action.id">
|
<label class="form-check-label" :for="action.id">
|
||||||
<span class="badge bg-light text-dark">{{ action.text }}</span>
|
<span class="badge bg-light text-dark" :title="action.text">{{
|
||||||
|
action.text
|
||||||
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
@@ -43,5 +45,9 @@ span.badge {
|
|||||||
font-size: 95%;
|
font-size: 95%;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
|
max-width: 100%; /* Adjust as needed */
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -26,6 +26,7 @@ const store = createStore({
|
|||||||
state: {
|
state: {
|
||||||
me: null,
|
me: null,
|
||||||
activity: window.activity,
|
activity: window.activity,
|
||||||
|
accompanyingPeriodWorks: [],
|
||||||
socialIssuesOther: [],
|
socialIssuesOther: [],
|
||||||
socialActionsList: [],
|
socialActionsList: [],
|
||||||
availableLocations: [],
|
availableLocations: [],
|
||||||
@@ -41,7 +42,7 @@ const store = createStore({
|
|||||||
const allEntities = [
|
const allEntities = [
|
||||||
...store.getters.suggestedPersons,
|
...store.getters.suggestedPersons,
|
||||||
...store.getters.suggestedRequestor,
|
...store.getters.suggestedRequestor,
|
||||||
...store.getters.suggestedUser,
|
...store.getters.suggestedUsers,
|
||||||
...store.getters.suggestedResources,
|
...store.getters.suggestedResources,
|
||||||
];
|
];
|
||||||
const uniqueIds = [
|
const uniqueIds = [
|
||||||
@@ -80,8 +81,7 @@ const store = createStore({
|
|||||||
state.activity.activityType.thirdPartiesVisible !== 0),
|
state.activity.activityType.thirdPartiesVisible !== 0),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
suggestedUser(state) {
|
suggestedUsers(state) {
|
||||||
// console.log('current user', state.me)
|
|
||||||
const existingUserIds = state.activity.users.map((p) => p.id);
|
const existingUserIds = state.activity.users.map((p) => p.id);
|
||||||
let suggestedUsers =
|
let suggestedUsers =
|
||||||
state.activity.activityType.usersVisible === 0
|
state.activity.activityType.usersVisible === 0
|
||||||
@@ -90,11 +90,18 @@ const store = createStore({
|
|||||||
(u) => u !== null && !existingUserIds.includes(u.id),
|
(u) => u !== null && !existingUserIds.includes(u.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
state.accompanyingPeriodWorks.forEach((work) => {
|
||||||
|
work.referrers.forEach((r) => {
|
||||||
|
if (!existingUserIds.includes(r.id)) {
|
||||||
|
suggestedUsers.push(r);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
// Add the current user from the state
|
// Add the current user from the state
|
||||||
if (state.me && !existingUserIds.includes(state.me.id)) {
|
if (state.me && !existingUserIds.includes(state.me.id)) {
|
||||||
suggestedUsers.push(state.me);
|
suggestedUsers.push(state.me);
|
||||||
}
|
}
|
||||||
console.log("suggested users", suggestedUsers);
|
// console.log("suggested users", suggestedUsers);
|
||||||
|
|
||||||
return suggestedUsers;
|
return suggestedUsers;
|
||||||
},
|
},
|
||||||
@@ -117,9 +124,19 @@ const store = createStore({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
socialActionsListSorted(state) {
|
socialActionsListSorted(state) {
|
||||||
return [...state.socialActionsList].sort(
|
return [...state.socialActionsList]
|
||||||
(a, b) => a.ordering - b.ordering,
|
.sort((a, b) => a.ordering - b.ordering)
|
||||||
);
|
.reduce((acc, action) => {
|
||||||
|
const issueText = action.issue?.text || "Uncategorized";
|
||||||
|
// Find if the group for the issue already exists
|
||||||
|
let group = acc.find((item) => item.issue === issueText);
|
||||||
|
if (!group) {
|
||||||
|
group = { issue: issueText, actions: [] };
|
||||||
|
acc.push(group);
|
||||||
|
}
|
||||||
|
group.actions.push(action);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
@@ -223,6 +240,9 @@ const store = createStore({
|
|||||||
addAvailableLocationGroup(state, group) {
|
addAvailableLocationGroup(state, group) {
|
||||||
state.availableLocations.push(group);
|
state.availableLocations.push(group);
|
||||||
},
|
},
|
||||||
|
setAccompanyingPeriodWorks(state, works) {
|
||||||
|
state.accompanyingPeriodWorks = works;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
addIssueSelected({ commit }, issue) {
|
addIssueSelected({ commit }, issue) {
|
||||||
@@ -341,6 +361,17 @@ const store = createStore({
|
|||||||
}
|
}
|
||||||
commit("updateLocation", value);
|
commit("updateLocation", value);
|
||||||
},
|
},
|
||||||
|
async fetchAccompanyingPeriodWorks({ state, commit }) {
|
||||||
|
const accompanyingPeriodId = state.activity.accompanyingPeriod.id;
|
||||||
|
const url = `/api/1.0/person/accompanying-course/${accompanyingPeriodId}/works.json`;
|
||||||
|
try {
|
||||||
|
const works = await makeFetch("GET", url);
|
||||||
|
// console.log("works", works);
|
||||||
|
commit("setAccompanyingPeriodWorks", works);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch accompanying period works:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
getWhoAmI({ commit }) {
|
getWhoAmI({ commit }) {
|
||||||
const url = `/api/1.0/main/whoami.json`;
|
const url = `/api/1.0/main/whoami.json`;
|
||||||
makeFetch("GET", url).then((user) => {
|
makeFetch("GET", url).then((user) => {
|
||||||
@@ -353,5 +384,6 @@ const store = createStore({
|
|||||||
store.dispatch("getWhoAmI");
|
store.dispatch("getWhoAmI");
|
||||||
|
|
||||||
prepareLocations(store);
|
prepareLocations(store);
|
||||||
|
store.dispatch("fetchAccompanyingPeriodWorks");
|
||||||
|
|
||||||
export default store;
|
export default store;
|
||||||
|
@@ -143,7 +143,10 @@ class ListActivitiesByAccompanyingPeriodContext implements
|
|||||||
array_filter(
|
array_filter(
|
||||||
$works,
|
$works,
|
||||||
function ($work) use ($user) {
|
function ($work) use ($user) {
|
||||||
$workUsernames = array_map(static fn (User $user) => $user['username'], $work['referrers'] ?? []);
|
$workUsernames = [];
|
||||||
|
foreach ($work['referrers'] as $referrer) {
|
||||||
|
$workUsernames[] = $referrer['username'];
|
||||||
|
}
|
||||||
|
|
||||||
return \in_array($user->getUserIdentifier(), $workUsernames, true);
|
return \in_array($user->getUserIdentifier(), $workUsernames, true);
|
||||||
}
|
}
|
||||||
|
@@ -102,6 +102,32 @@ activity:
|
|||||||
Remove a document: Supprimer le document
|
Remove a document: Supprimer le document
|
||||||
comment: Commentaire
|
comment: Commentaire
|
||||||
deleted: Échange supprimé
|
deleted: Échange supprimé
|
||||||
|
|
||||||
|
errors: Le formulaire contient des erreurs
|
||||||
|
social_issues: Problématiques sociales
|
||||||
|
choose_other_social_issue: Ajouter une autre problématique sociale...
|
||||||
|
social_actions: Actions d'accompagnement
|
||||||
|
select_first_a_social_issue: Sélectionnez d'abord une problématique sociale
|
||||||
|
social_action_list_empty: Aucune action sociale disponible
|
||||||
|
add_persons: Ajouter des personnes concernées
|
||||||
|
bloc_persons: Usagers
|
||||||
|
bloc_persons_associated: Usagers du parcours
|
||||||
|
bloc_persons_not_associated: Tiers non-pro.
|
||||||
|
bloc_thirdparty: Tiers professionnels
|
||||||
|
bloc_users: T(M)S
|
||||||
|
location: Localisation
|
||||||
|
choose_location: Choisissez une localisation
|
||||||
|
choose_location_type: Choisissez un type de localisation
|
||||||
|
create_new_location: Créer une nouvelle localisation
|
||||||
|
location_fields:
|
||||||
|
name: Nom
|
||||||
|
type: Type
|
||||||
|
phonenumber1: Téléphone
|
||||||
|
phonenumber2: Autre téléphone
|
||||||
|
email: Adresse courriel
|
||||||
|
create_address: Créer une adresse
|
||||||
|
edit_address: Modifier l'adresse
|
||||||
|
|
||||||
No documents: Aucun document
|
No documents: Aucun document
|
||||||
|
|
||||||
# activity filter in list page
|
# activity filter in list page
|
||||||
|
@@ -96,13 +96,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<FullCalendar :options="calendarOptions" ref="calendarRef">
|
<FullCalendar :options="calendarOptions" ref="calendarRef">
|
||||||
<template v-slot:eventContent="arg: EventApi">
|
<template v-slot:eventContent="{ arg }: { arg: { event: EventApi } }">
|
||||||
<span :class="eventClasses(arg.event)">
|
<span :class="eventClasses(arg.event)">
|
||||||
<b v-if="arg.event.extendedProps.is === 'remote'">{{
|
<b v-if="arg.event.extendedProps.is === 'remote'">{{
|
||||||
arg.event.title
|
arg.event.title
|
||||||
}}</b>
|
}}</b>
|
||||||
<b v-else-if="arg.event.extendedProps.is === 'range'"
|
<b v-else-if="arg.event.extendedProps.is === 'range'"
|
||||||
>{{ arg.timeText }} -
|
>{{ arg.event.startStr }} -
|
||||||
{{ arg.event.extendedProps.locationName }}</b
|
{{ arg.event.extendedProps.locationName }}</b
|
||||||
>
|
>
|
||||||
<b v-else-if="arg.event.extendedProps.is === 'local'">{{
|
<b v-else-if="arg.event.extendedProps.is === 'local'">{{
|
||||||
|
@@ -91,10 +91,7 @@
|
|||||||
class="col-5 p-0 text-center turnSignature"
|
class="col-5 p-0 text-center turnSignature"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
:disabled="
|
:disabled="isFirstSignatureZone"
|
||||||
userSignatureZone === null ||
|
|
||||||
userSignatureZone?.index < 1
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(-1)"
|
@click="turnSignature(-1)"
|
||||||
>
|
>
|
||||||
@@ -102,9 +99,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<button
|
<button
|
||||||
:disabled="
|
:disabled="isLastSignatureZone"
|
||||||
userSignatureZone?.index >= signature.zones.length - 1
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(1)"
|
@click="turnSignature(1)"
|
||||||
>
|
>
|
||||||
@@ -200,10 +195,7 @@
|
|||||||
class="col-4 d-xl-none text-center turnSignature p-0"
|
class="col-4 d-xl-none text-center turnSignature p-0"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
:disabled="
|
:disabled="!hasSignatureZoneSelected"
|
||||||
userSignatureZone === null ||
|
|
||||||
userSignatureZone?.index < 1
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(-1)"
|
@click="turnSignature(-1)"
|
||||||
>
|
>
|
||||||
@@ -211,9 +203,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<button
|
<button
|
||||||
:disabled="
|
:disabled="isLastSignatureZone"
|
||||||
userSignatureZone?.index >= signature.zones.length - 1
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(1)"
|
@click="turnSignature(1)"
|
||||||
>
|
>
|
||||||
@@ -225,10 +215,7 @@
|
|||||||
class="col-4 d-none d-xl-flex p-0 text-center turnSignature"
|
class="col-4 d-none d-xl-flex p-0 text-center turnSignature"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
:disabled="
|
:disabled="isFirstSignatureZone"
|
||||||
userSignatureZone === null ||
|
|
||||||
userSignatureZone?.index < 1
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(-1)"
|
@click="turnSignature(-1)"
|
||||||
>
|
>
|
||||||
@@ -236,9 +223,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<button
|
<button
|
||||||
:disabled="
|
:disabled="isLastSignatureZone"
|
||||||
userSignatureZone?.index >= signature.zones.length - 1
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(1)"
|
@click="turnSignature(1)"
|
||||||
>
|
>
|
||||||
@@ -333,7 +318,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, Ref, reactive } from "vue";
|
import { ref, Ref, computed } from "vue";
|
||||||
import { useToast } from "vue-toast-notification";
|
import { useToast } from "vue-toast-notification";
|
||||||
import "vue-toast-notification/dist/theme-sugar.css";
|
import "vue-toast-notification/dist/theme-sugar.css";
|
||||||
import {
|
import {
|
||||||
@@ -351,18 +336,15 @@ import {
|
|||||||
PDFPageProxy,
|
PDFPageProxy,
|
||||||
} from "pdfjs-dist/types/src/display/api";
|
} from "pdfjs-dist/types/src/display/api";
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore incredible but the console.log is needed
|
||||||
import * as PdfWorker from "pdfjs-dist/build/pdf.worker.mjs";
|
import * as PdfWorker from "pdfjs-dist/build/pdf.worker.mjs";
|
||||||
console.log(PdfWorker); // incredible but this is needed
|
console.log(PdfWorker);
|
||||||
|
|
||||||
// import { PdfWorker } from 'pdfjs-dist/build/pdf.worker.mjs'
|
// import { PdfWorker } from 'pdfjs-dist/build/pdf.worker.mjs'
|
||||||
// pdfjsLib.GlobalWorkerOptions.workerSrc = PdfWorker;
|
// pdfjsLib.GlobalWorkerOptions.workerSrc = PdfWorker;
|
||||||
|
|
||||||
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
||||||
import {
|
import { download_doc_as_pdf } from "../StoredObjectButton/helpers";
|
||||||
download_and_decrypt_doc,
|
|
||||||
download_doc_as_pdf,
|
|
||||||
} from "../StoredObjectButton/helpers";
|
|
||||||
|
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc = "pdfjs-dist/build/pdf.worker.mjs";
|
pdfjsLib.GlobalWorkerOptions.workerSrc = "pdfjs-dist/build/pdf.worker.mjs";
|
||||||
|
|
||||||
@@ -433,6 +415,20 @@ const $toast = useToast();
|
|||||||
|
|
||||||
const signature = window.signature;
|
const signature = window.signature;
|
||||||
|
|
||||||
|
const isFirstSignatureZone = () =>
|
||||||
|
userSignatureZone.value?.index ? userSignatureZone.value.index < 1 : false;
|
||||||
|
const isLastSignatureZone = () =>
|
||||||
|
userSignatureZone.value?.index
|
||||||
|
? userSignatureZone.value.index >= signature.zones.length - 1
|
||||||
|
: false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the user has selected a user zone (existing on the doc or created by the user)
|
||||||
|
*/
|
||||||
|
const hasSignatureZoneSelected = computed<boolean>(
|
||||||
|
() => userSignatureZone.value !== null,
|
||||||
|
);
|
||||||
|
|
||||||
const setZoomLevel = async (zoomLevel: string) => {
|
const setZoomLevel = async (zoomLevel: string) => {
|
||||||
zoom.value = Number.parseFloat(zoomLevel);
|
zoom.value = Number.parseFloat(zoomLevel);
|
||||||
await resetPages();
|
await resetPages();
|
||||||
@@ -754,7 +750,7 @@ const confirmSign = () => {
|
|||||||
zone: userSignatureZone.value,
|
zone: userSignatureZone.value,
|
||||||
};
|
};
|
||||||
makeFetch("POST", url, body)
|
makeFetch("POST", url, body)
|
||||||
.then((r) => {
|
.then(() => {
|
||||||
checkForReady();
|
checkForReady();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -776,9 +772,7 @@ const undoSign = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleAddZone = () => {
|
const toggleAddZone = () => {
|
||||||
canvasEvent.value === "select"
|
canvasEvent.value = canvasEvent.value === "select" ? "add" : "select";
|
||||||
? (canvasEvent.value = "add")
|
|
||||||
: (canvasEvent.value = "select");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const addZoneEvent = async (e: PointerEvent, canvas: HTMLCanvasElement) => {
|
const addZoneEvent = async (e: PointerEvent, canvas: HTMLCanvasElement) => {
|
||||||
|
@@ -28,6 +28,10 @@ const open = () => {
|
|||||||
state.opened = true;
|
state.opened = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onRestoreVersion = (payload: {
|
||||||
|
newVersion: StoredObjectVersionWithPointInTime;
|
||||||
|
}) => emit("restoreVersion", payload);
|
||||||
|
|
||||||
defineExpose({ open });
|
defineExpose({ open });
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
@@ -42,9 +46,7 @@ defineExpose({ open });
|
|||||||
:versions="props.versions"
|
:versions="props.versions"
|
||||||
:can-edit="canEdit"
|
:can-edit="canEdit"
|
||||||
:stored-object="storedObject"
|
:stored-object="storedObject"
|
||||||
@restore-version="
|
@restore-version="onRestoreVersion"
|
||||||
(payload) => emit('restoreVersion', payload)
|
|
||||||
"
|
|
||||||
></history-button-list>
|
></history-button-list>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</modal>
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
#events
|
#events
|
||||||
Name: Nom
|
|
||||||
Label: Nom
|
|
||||||
Date: Date
|
|
||||||
Event type : Type d'événement
|
Event type : Type d'événement
|
||||||
See: Voir
|
|
||||||
Event: Événement
|
Event: Événement
|
||||||
Events: Événements
|
Events: Événements
|
||||||
'Event : %label%': Événement "%label%"
|
'Event : %label%': Événement "%label%"
|
||||||
@@ -123,7 +119,6 @@ Role: Rôles
|
|||||||
Role creation: Nouveau rôle
|
Role creation: Nouveau rôle
|
||||||
Role edit: Modifier un rôle
|
Role edit: Modifier un rôle
|
||||||
|
|
||||||
'': ''
|
|
||||||
xlsx: xlsx
|
xlsx: xlsx
|
||||||
ods: ods
|
ods: ods
|
||||||
csv: csv
|
csv: csv
|
||||||
|
@@ -63,7 +63,6 @@ abstract class AbstractCRUDController extends AbstractController
|
|||||||
parent::getSubscribedServices(),
|
parent::getSubscribedServices(),
|
||||||
[
|
[
|
||||||
'chill_main.paginator_factory' => PaginatorFactory::class,
|
'chill_main.paginator_factory' => PaginatorFactory::class,
|
||||||
ManagerRegistry::class => ManagerRegistry::class,
|
|
||||||
'translator' => TranslatorInterface::class,
|
'translator' => TranslatorInterface::class,
|
||||||
AuthorizationHelper::class => AuthorizationHelper::class,
|
AuthorizationHelper::class => AuthorizationHelper::class,
|
||||||
EventDispatcherInterface::class => EventDispatcherInterface::class,
|
EventDispatcherInterface::class => EventDispatcherInterface::class,
|
||||||
@@ -213,7 +212,7 @@ abstract class AbstractCRUDController extends AbstractController
|
|||||||
|
|
||||||
protected function getManagerRegistry(): ManagerRegistry
|
protected function getManagerRegistry(): ManagerRegistry
|
||||||
{
|
{
|
||||||
return $this->container->get(ManagerRegistry::class);
|
return $this->container->get('doctrine');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,7 +225,7 @@ abstract class AbstractCRUDController extends AbstractController
|
|||||||
|
|
||||||
protected function getValidator(): ValidatorInterface
|
protected function getValidator(): ValidatorInterface
|
||||||
{
|
{
|
||||||
return $this->get('validator');
|
return $this->container->get('validator');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -18,6 +18,7 @@ use Symfony\Component\Form\AbstractType;
|
|||||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
|
|
||||||
class ExportType extends AbstractType
|
class ExportType extends AbstractType
|
||||||
{
|
{
|
||||||
@@ -29,7 +30,15 @@ class ExportType extends AbstractType
|
|||||||
|
|
||||||
final public const PICK_FORMATTER_KEY = 'pick_formatter';
|
final public const PICK_FORMATTER_KEY = 'pick_formatter';
|
||||||
|
|
||||||
public function __construct(private readonly ExportManager $exportManager, private readonly SortExportElement $sortExportElement) {}
|
private array $personFieldsConfig;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private readonly ExportManager $exportManager,
|
||||||
|
private readonly SortExportElement $sortExportElement,
|
||||||
|
protected ParameterBagInterface $parameterBag,
|
||||||
|
) {
|
||||||
|
$this->personFieldsConfig = $parameterBag->get('chill_person.person_fields');
|
||||||
|
}
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
@@ -77,6 +86,17 @@ class ExportType extends AbstractType
|
|||||||
);
|
);
|
||||||
|
|
||||||
foreach ($aggregators as $alias => $aggregator) {
|
foreach ($aggregators as $alias => $aggregator) {
|
||||||
|
/*
|
||||||
|
* eventually mask aggregator
|
||||||
|
*/
|
||||||
|
if (str_starts_with((string) $alias, 'person_') and str_ends_with((string) $alias, '_aggregator')) {
|
||||||
|
$field = preg_replace(['/person_/', '/_aggregator/'], '', (string) $alias);
|
||||||
|
if (array_key_exists($field, $this->personFieldsConfig) and 'visible' !== $this->personFieldsConfig[$field]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$aggregatorBuilder->add($alias, AggregatorType::class, [
|
$aggregatorBuilder->add($alias, AggregatorType::class, [
|
||||||
'aggregator_alias' => $alias,
|
'aggregator_alias' => $alias,
|
||||||
'export_manager' => $this->exportManager,
|
'export_manager' => $this->exportManager,
|
||||||
|
@@ -75,8 +75,8 @@ final class UserGroupRepository implements UserGroupRepositoryInterface, LocaleA
|
|||||||
->setWhereClauses('
|
->setWhereClauses('
|
||||||
ug.active AND (
|
ug.active AND (
|
||||||
SIMILARITY(LOWER(UNACCENT(?)), ug.label->>?) > 0.15
|
SIMILARITY(LOWER(UNACCENT(?)), ug.label->>?) > 0.15
|
||||||
OR ug.label->>? LIKE \'%\' || LOWER(UNACCENT(?)) || \'%\')
|
OR LOWER(UNACCENT(ug.label->>?)) LIKE \'%\' || LOWER(UNACCENT(?)) || \'%\')
|
||||||
', [$pattern, $lang, $pattern, $lang]);
|
', [$pattern, $lang, $lang, $pattern]);
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
@@ -1,30 +1,32 @@
|
|||||||
import ClassicEditorBase from "@ckeditor/ckeditor5-editor-classic/src/classiceditor";
|
import {
|
||||||
import EssentialsPlugin from "@ckeditor/ckeditor5-essentials/src/essentials";
|
Essentials,
|
||||||
import MarkdownPlugin from "@ckeditor/ckeditor5-markdown-gfm/src/markdown";
|
Bold,
|
||||||
import BoldPlugin from "@ckeditor/ckeditor5-basic-styles/src/bold";
|
Italic,
|
||||||
import ItalicPlugin from "@ckeditor/ckeditor5-basic-styles/src/italic";
|
Paragraph,
|
||||||
import BlockQuotePlugin from "@ckeditor/ckeditor5-block-quote/src/blockquote";
|
Markdown,
|
||||||
import HeadingPlugin from "@ckeditor/ckeditor5-heading/src/heading";
|
BlockQuote,
|
||||||
import LinkPlugin from "@ckeditor/ckeditor5-link/src/link";
|
Heading,
|
||||||
import ListPlugin from "@ckeditor/ckeditor5-list/src/list";
|
Link,
|
||||||
import ParagraphPlugin from "@ckeditor/ckeditor5-paragraph/src/paragraph";
|
List,
|
||||||
|
} from "ckeditor5";
|
||||||
|
import coreTranslations from "ckeditor5/translations/fr.js";
|
||||||
|
|
||||||
|
import "ckeditor5/ckeditor5.css";
|
||||||
|
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
|
|
||||||
export default class ClassicEditor extends ClassicEditorBase {}
|
export default {
|
||||||
|
plugins: [
|
||||||
ClassicEditor.builtinPlugins = [
|
Essentials,
|
||||||
EssentialsPlugin,
|
Markdown,
|
||||||
MarkdownPlugin,
|
Bold,
|
||||||
BoldPlugin,
|
Italic,
|
||||||
ItalicPlugin,
|
BlockQuote,
|
||||||
BlockQuotePlugin,
|
Heading,
|
||||||
HeadingPlugin,
|
Link,
|
||||||
LinkPlugin,
|
List,
|
||||||
ListPlugin,
|
Paragraph,
|
||||||
ParagraphPlugin,
|
],
|
||||||
];
|
|
||||||
|
|
||||||
ClassicEditor.defaultConfig = {
|
|
||||||
toolbar: {
|
toolbar: {
|
||||||
items: [
|
items: [
|
||||||
"heading",
|
"heading",
|
||||||
@@ -39,5 +41,6 @@ ClassicEditor.defaultConfig = {
|
|||||||
"redo",
|
"redo",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
language: "fr",
|
translations: [coreTranslations],
|
||||||
|
licenseKey: "GPL",
|
||||||
};
|
};
|
||||||
|
@@ -1,14 +1,12 @@
|
|||||||
import ClassicEditor from "./editor_config";
|
import config from "./editor_config";
|
||||||
|
import { ClassicEditor } from "ckeditor5";
|
||||||
|
|
||||||
const ckeditorFields: NodeListOf<HTMLTextAreaElement> =
|
const ckeditorFields: NodeListOf<HTMLTextAreaElement> =
|
||||||
document.querySelectorAll("textarea[ckeditor]");
|
document.querySelectorAll("textarea[ckeditor]");
|
||||||
ckeditorFields.forEach((field: HTMLTextAreaElement): void => {
|
ckeditorFields.forEach((field: HTMLTextAreaElement): void => {
|
||||||
ClassicEditor.create(field)
|
ClassicEditor.create(field, config).catch((error) => {
|
||||||
.then((editor) => {
|
console.error(error.stack);
|
||||||
//console.log( 'CkEditor was initialized', editor );
|
throw error;
|
||||||
})
|
});
|
||||||
.catch((error) => {
|
|
||||||
console.error(error.stack);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
//Fields.push.apply(Fields, document.querySelectorAll('.cf-fields textarea'));
|
//Fields.push.apply(Fields, document.querySelectorAll('.cf-fields textarea'));
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
import NotificationReadToggle from "ChillMainAssets/vuejs/_components/Notification/NotificationReadToggle.vue";
|
import NotificationReadToggle from "ChillMainAssets/vuejs/_components/Notification/NotificationReadToggle.vue";
|
||||||
import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n";
|
import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n";
|
||||||
import NotificationReadAllToggle from "ChillMainAssets/vuejs/_components/Notification/NotificationReadAllToggle.vue";
|
|
||||||
|
|
||||||
const i18n = _createI18n({});
|
const i18n = _createI18n({});
|
||||||
|
|
||||||
window.addEventListener("DOMContentLoaded", function (e) {
|
window.addEventListener("DOMContentLoaded", function () {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".notification_toggle_read_status")
|
.querySelectorAll(".notification_toggle_read_status")
|
||||||
.forEach(function (el, i) {
|
.forEach(function (el, i) {
|
||||||
|
@@ -22,12 +22,12 @@ function loadDynamicPicker(element) {
|
|||||||
? JSON.parse(input.value)
|
? JSON.parse(input.value)
|
||||||
: input.value === "[]" || input.value === ""
|
: input.value === "[]" || input.value === ""
|
||||||
? null
|
? null
|
||||||
: [JSON.parse(input.value)];
|
: [JSON.parse(input.value)],
|
||||||
(suggested = JSON.parse(el.dataset.suggested)),
|
suggested = JSON.parse(el.dataset.suggested),
|
||||||
(as_id = parseInt(el.dataset.asId) === 1),
|
as_id = parseInt(el.dataset.asId) === 1,
|
||||||
(submit_on_adding_new_entity =
|
submit_on_adding_new_entity =
|
||||||
parseInt(el.dataset.submitOnAddingNewEntity) === 1);
|
parseInt(el.dataset.submitOnAddingNewEntity) === 1,
|
||||||
label = el.dataset.label;
|
label = el.dataset.label;
|
||||||
|
|
||||||
if (!isMultiple) {
|
if (!isMultiple) {
|
||||||
if (input.value === "[]") {
|
if (input.value === "[]") {
|
||||||
@@ -173,7 +173,7 @@ document.addEventListener("pick-entity-type-action", function (e) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
loadDynamicPicker(document);
|
loadDynamicPicker(document);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -45,6 +45,10 @@ const onPickGenericDoc = ({
|
|||||||
}) => {
|
}) => {
|
||||||
emit("pickGenericDoc", { genericDoc });
|
emit("pickGenericDoc", { genericDoc });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onRemoveAttachment = (payload: { attachment: WorkflowAttachment }) => {
|
||||||
|
emit("removeAttachment", payload);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -56,7 +60,7 @@ const onPickGenericDoc = ({
|
|||||||
></pick-generic-doc-modal>
|
></pick-generic-doc-modal>
|
||||||
<attachment-list
|
<attachment-list
|
||||||
:attachments="props.attachments"
|
:attachments="props.attachments"
|
||||||
@removeAttachment="(payload) => emit('removeAttachment', payload)"
|
@removeAttachment="onRemoveAttachment"
|
||||||
></attachment-list>
|
></attachment-list>
|
||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li>
|
<li>
|
||||||
|
@@ -72,6 +72,14 @@ const placeTrans = (str: string): string => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onPickDocument = (payload: {
|
||||||
|
genericDoc: GenericDocForAccompanyingPeriod;
|
||||||
|
}) => emit("pickGenericDoc", payload);
|
||||||
|
|
||||||
|
const onRemoveGenericDoc = (payload: {
|
||||||
|
genericDoc: GenericDocForAccompanyingPeriod;
|
||||||
|
}) => emit("removeGenericDoc", payload);
|
||||||
|
|
||||||
const filteredDocuments = computed<GenericDocForAccompanyingPeriod[]>(() => {
|
const filteredDocuments = computed<GenericDocForAccompanyingPeriod[]>(() => {
|
||||||
if (false === loaded.value) {
|
if (false === loaded.value) {
|
||||||
return [];
|
return [];
|
||||||
@@ -232,19 +240,8 @@ const filteredDocuments = computed<GenericDocForAccompanyingPeriod[]>(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row my-2">
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
class="btn btn-sm btn-misc"
|
|
||||||
>
|
|
||||||
<i class="fa fa-fw fa-filter"></i>Filtrer
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div></div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -256,10 +253,8 @@ const filteredDocuments = computed<GenericDocForAccompanyingPeriod[]>(() => {
|
|||||||
:accompanying-period-id="accompanyingPeriodId"
|
:accompanying-period-id="accompanyingPeriodId"
|
||||||
:genericDoc="g"
|
:genericDoc="g"
|
||||||
:is-picked="isPicked(g)"
|
:is-picked="isPicked(g)"
|
||||||
@pickGenericDoc="(payload) => emit('pickGenericDoc', payload)"
|
@pickGenericDoc="onPickDocument"
|
||||||
@removeGenericDoc="
|
@removeGenericDoc="onRemoveGenericDoc"
|
||||||
(payload) => emit('removeGenericDoc', payload)
|
|
||||||
"
|
|
||||||
></pick-generic-doc-item>
|
></pick-generic-doc-item>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="text-center chill-no-data-statement">
|
<div v-else class="text-center chill-no-data-statement">
|
||||||
|
@@ -70,7 +70,8 @@ const clickOnAddButton = () => {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.item-bloc {
|
.item-bloc {
|
||||||
&.isPicked {
|
&.isPicked {
|
||||||
background: linear-gradient(
|
background:
|
||||||
|
linear-gradient(
|
||||||
180deg,
|
180deg,
|
||||||
rgba(25, 135, 84, 1) 0px,
|
rgba(25, 135, 84, 1) 0px,
|
||||||
rgba(25, 135, 84, 0) 9px
|
rgba(25, 135, 84, 0) 9px
|
||||||
|
@@ -1,61 +1,65 @@
|
|||||||
<template>
|
<template>
|
||||||
<span v-if="entity.type === 'person'" class="badge rounded-pill bg-person">
|
<span
|
||||||
{{ $t("person") }}
|
v-if="props.entity.type === 'person'"
|
||||||
|
class="badge rounded-pill bg-person"
|
||||||
|
>
|
||||||
|
{{ trans(PERSON) }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
v-if="entity.type === 'thirdparty'"
|
v-if="props.entity.type === 'thirdparty'"
|
||||||
class="badge rounded-pill bg-thirdparty"
|
class="badge rounded-pill bg-thirdparty"
|
||||||
>
|
>
|
||||||
<template v-if="options.displayLong !== true">
|
<template v-if="props.options.displayLong !== true">
|
||||||
{{ $t("thirdparty.thirdparty") }}
|
{{ trans(THIRDPARTY) }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i class="fa fa-fw fa-user" v-if="entity.kind === 'child'" />
|
<i class="fa fa-fw fa-user" v-if="props.entity.kind === 'child'" />
|
||||||
<i
|
<i
|
||||||
class="fa fa-fw fa-hospital-o"
|
class="fa fa-fw fa-hospital-o"
|
||||||
v-else-if="entity.kind === 'company'"
|
v-else-if="props.entity.kind === 'company'"
|
||||||
/>
|
/>
|
||||||
<i class="fa fa-fw fa-user-md" v-else />
|
<i class="fa fa-fw fa-user-md" v-else />
|
||||||
|
|
||||||
<template v-if="options.displayLong === true">
|
<template v-if="props.options.displayLong === true">
|
||||||
<span v-if="entity.kind === 'child'">{{
|
<span v-if="props.entity.kind === 'child'">{{
|
||||||
$t("thirdparty.child")
|
trans(THIRDPARTY_CONTACT_OF)
|
||||||
}}</span>
|
}}</span>
|
||||||
<span v-else-if="entity.kind === 'company'">{{
|
<span v-else-if="props.entity.kind === 'company'">{{
|
||||||
$t("thirdparty.company")
|
trans(THIRDPARTY_A_CONTACT)
|
||||||
}}</span>
|
}}</span>
|
||||||
<span v-else>{{ $t("thirdparty.contact") }}</span>
|
<span v-else>{{ $t("thirdparty.contact") }}</span>
|
||||||
</template>
|
</template>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-if="entity.type === 'user'" class="badge rounded-pill bg-user">
|
<span
|
||||||
{{ $t("user") }}
|
v-if="props.entity.type === 'user'"
|
||||||
|
class="badge rounded-pill bg-user"
|
||||||
|
>
|
||||||
|
{{ trans(ACCEPTED_USERS) }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-if="entity.type === 'household'" class="badge rounded-pill bg-user">
|
<span
|
||||||
{{ $t("household") }}
|
v-if="props.entity.type === 'household'"
|
||||||
|
class="badge rounded-pill bg-user"
|
||||||
|
>
|
||||||
|
{{ trans(HOUSEHOLD) }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
import {
|
||||||
name: "BadgeEntity",
|
trans,
|
||||||
props: ["options", "entity"],
|
HOUSEHOLD,
|
||||||
i18n: {
|
ACCEPTED_USERS,
|
||||||
messages: {
|
THIRDPARTY_A_CONTACT,
|
||||||
fr: {
|
THIRDPARTY_CONTACT_OF,
|
||||||
person: "Usager",
|
PERSON,
|
||||||
thirdparty: {
|
THIRDPARTY,
|
||||||
thirdparty: "Tiers",
|
} from "translator";
|
||||||
child: "Personne de contact",
|
|
||||||
company: "Personne morale",
|
const props = defineProps({
|
||||||
contact: "Personne physique",
|
options: Object,
|
||||||
},
|
entity: Object,
|
||||||
user: "TMS",
|
});
|
||||||
household: "Ménage",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
@@ -66,13 +66,13 @@
|
|||||||
<div v-if="useDatePane === true" class="address-more">
|
<div v-if="useDatePane === true" class="address-more">
|
||||||
<div v-if="address.validFrom">
|
<div v-if="address.validFrom">
|
||||||
<span class="validFrom">
|
<span class="validFrom">
|
||||||
<b>{{ $t("validFrom") }}</b
|
<b>{{ trans(ADDRESS_VALID_FROM) }}</b
|
||||||
>: {{ $d(address.validFrom.date) }}
|
>: {{ $d(address.validFrom.date) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="address.validTo">
|
<div v-if="address.validTo">
|
||||||
<span class="validTo">
|
<span class="validTo">
|
||||||
<b>{{ $t("validTo") }}</b
|
<b>{{ trans(ADDRESS_VALID_TO) }}</b
|
||||||
>: {{ $d(address.validTo.date) }}
|
>: {{ $d(address.validTo.date) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,6 +83,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import Confidential from "ChillMainAssets/vuejs/_components/Confidential.vue";
|
import Confidential from "ChillMainAssets/vuejs/_components/Confidential.vue";
|
||||||
import AddressDetailsButton from "ChillMainAssets/vuejs/_components/AddressDetails/AddressDetailsButton.vue";
|
import AddressDetailsButton from "ChillMainAssets/vuejs/_components/AddressDetails/AddressDetailsButton.vue";
|
||||||
|
import { trans, ADDRESS_VALID_FROM, ADDRESS_VALID_TO } from "translator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "AddressRenderBox",
|
name: "AddressRenderBox",
|
||||||
@@ -107,6 +108,9 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { trans, ADDRESS_VALID_FROM, ADDRESS_VALID_TO };
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
component() {
|
component() {
|
||||||
return this.isMultiline === true ? "div" : "span";
|
return this.isMultiline === true ? "div" : "span";
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
v-if="!subscriberFinal"
|
v-if="!subscriberFinal"
|
||||||
@click="subscribeTo('subscribe', 'final')"
|
@click="subscribeTo('subscribe', 'final')"
|
||||||
>
|
>
|
||||||
<i class="fa fa-check fa-fw" />
|
<i class="fa fa-check fa-fw"></i>
|
||||||
{{ $t("subscribe_final") }}
|
{{ trans(WORKFLOW_SUBSCRIBE_FINAL) }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-misc"
|
class="btn btn-misc"
|
||||||
@@ -15,8 +15,8 @@
|
|||||||
v-if="subscriberFinal"
|
v-if="subscriberFinal"
|
||||||
@click="subscribeTo('unsubscribe', 'final')"
|
@click="subscribeTo('unsubscribe', 'final')"
|
||||||
>
|
>
|
||||||
<i class="fa fa-times fa-fw" />
|
<i class="fa fa-times fa-fw"></i>
|
||||||
{{ $t("unsubscribe_final") }}
|
{{ trans(WORKFLOW_UNSUBSCRIBE_FINAL) }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-misc"
|
class="btn btn-misc"
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
v-if="!subscriberStep"
|
v-if="!subscriberStep"
|
||||||
@click="subscribeTo('subscribe', 'step')"
|
@click="subscribeTo('subscribe', 'step')"
|
||||||
>
|
>
|
||||||
<i class="fa fa-check fa-fw" />
|
<i class="fa fa-check fa-fw"></i>
|
||||||
{{ $t("subscribe_all_steps") }}
|
{{ trans(WORKFLOW_SUBSCRIBE_ALL_STEPS) }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-misc"
|
class="btn btn-misc"
|
||||||
@@ -33,94 +33,55 @@
|
|||||||
v-if="subscriberStep"
|
v-if="subscriberStep"
|
||||||
@click="subscribeTo('unsubscribe', 'step')"
|
@click="subscribeTo('unsubscribe', 'step')"
|
||||||
>
|
>
|
||||||
<i class="fa fa-times fa-fw" />
|
<i class="fa fa-times fa-fw"></i>
|
||||||
{{ $t("unsubscribe_all_steps") }}
|
{{ trans(WORKFLOW_UNSUBSCRIBE_ALL_STEPS) }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts";
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts";
|
||||||
|
import { defineProps, defineEmits } from "vue";
|
||||||
|
import {
|
||||||
|
trans,
|
||||||
|
WORKFLOW_SUBSCRIBE_FINAL,
|
||||||
|
WORKFLOW_UNSUBSCRIBE_FINAL,
|
||||||
|
WORKFLOW_SUBSCRIBE_ALL_STEPS,
|
||||||
|
WORKFLOW_UNSUBSCRIBE_ALL_STEPS,
|
||||||
|
} from "translator";
|
||||||
|
|
||||||
export default {
|
// props
|
||||||
name: "EntityWorkflowVueSubscriber",
|
const props = defineProps({
|
||||||
i18n: {
|
entityWorkflowId: {
|
||||||
messages: {
|
type: Number,
|
||||||
fr: {
|
required: true,
|
||||||
subscribe_final: "Recevoir une notification à l'étape finale",
|
|
||||||
unsubscribe_final:
|
|
||||||
"Ne plus recevoir de notification à l'étape finale",
|
|
||||||
subscribe_all_steps:
|
|
||||||
"Recevoir une notification à chaque étape du suivi",
|
|
||||||
unsubscribe_all_steps:
|
|
||||||
"Ne plus recevoir de notification à chaque étape du suivi",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
props: {
|
subscriberStep: {
|
||||||
entityWorkflowId: {
|
type: Boolean,
|
||||||
type: Number,
|
required: true,
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
subscriberStep: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
subscriberFinal: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
emits: ["subscriptionUpdated"],
|
subscriberFinal: {
|
||||||
methods: {
|
type: Boolean,
|
||||||
subscribeTo(step, to) {
|
required: true,
|
||||||
let params = new URLSearchParams();
|
},
|
||||||
params.set("subscribe", to);
|
});
|
||||||
|
|
||||||
const url =
|
//methods
|
||||||
`/api/1.0/main/workflow/${this.entityWorkflowId}/${step}?` +
|
const subscribeTo = (step, to) => {
|
||||||
params.toString();
|
let params = new URLSearchParams();
|
||||||
|
params.set("subscribe", to);
|
||||||
|
|
||||||
makeFetch("POST", url).then((response) => {
|
const url =
|
||||||
this.$emit("subscriptionUpdated", response);
|
`/api/1.0/main/workflow/${props.entityWorkflowId}/${step}?` +
|
||||||
});
|
params.toString();
|
||||||
},
|
|
||||||
},
|
makeFetch("POST", url).then((response) => {
|
||||||
|
emit("subscriptionUpdated", response);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
* ALTERNATIVES
|
|
||||||
*
|
|
||||||
<div class="form-check form-switch">
|
|
||||||
<input class="form-check-input" type="checkbox" role="switch" id="laststep">
|
|
||||||
<label class="form-check-label" for="laststep">{{ $t('subscribe_final') }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-switch">
|
|
||||||
<input class="form-check-input" type="checkbox" role="switch" id="allsteps">
|
|
||||||
<label class="form-check-label" for="allsteps">{{ $t('subscribe_all_steps') }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="list-group my-3">
|
// emit
|
||||||
<label class="list-group-item">
|
const emit = defineEmits(["subscriptionUpdated"]);
|
||||||
<input class="form-check-input me-1" type="checkbox" value="">
|
|
||||||
{{ $t('subscribe_final') }}
|
|
||||||
</label>
|
|
||||||
<label class="list-group-item">
|
|
||||||
<input class="form-check-input me-1" type="checkbox" value="">
|
|
||||||
{{ $t('subscribe_all_steps') }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btn-group-vertical my-3" role="group">
|
|
||||||
<button type="button" class="btn btn-outline-primary">
|
|
||||||
<i class="fa fa-check fa-fw"></i>
|
|
||||||
{{ $t('subscribe_final') }}
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-outline-primary">
|
|
||||||
<i class="fa fa-check fa-fw"></i>
|
|
||||||
{{ $t('subscribe_all_steps') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
*/
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex-table workflow" id="workflow-list">
|
<div class="flex-table workflow" id="workflow-list">
|
||||||
<div
|
<div
|
||||||
v-for="(w, i) in workflows"
|
v-for="(w, i) in props.workflows"
|
||||||
:key="`workflow-${i}`"
|
:key="`workflow-${i}`"
|
||||||
class="item-bloc"
|
class="item-bloc"
|
||||||
>
|
>
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
<span
|
<span
|
||||||
v-if="w.isOnHoldAtCurrentStep"
|
v-if="w.isOnHoldAtCurrentStep"
|
||||||
class="badge bg-success rounded-pill"
|
class="badge bg-success rounded-pill"
|
||||||
>{{ $t("on_hold") }}</span
|
>{{ trans(WORKFLOW_ON_HOLD) }}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
<div class="item-col flex-grow-1">
|
<div class="item-col flex-grow-1">
|
||||||
<p v-if="isUserSubscribedToStep(w)">
|
<p v-if="isUserSubscribedToStep(w)">
|
||||||
<i class="fa fa-check fa-fw"></i>
|
<i class="fa fa-check fa-fw"></i>
|
||||||
{{ $t("you_subscribed_to_all_steps") }}
|
{{ trans(WORKFLOW_YOU_SUBSCRIBED_TO_ALL_STEPS) }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="isUserSubscribedToFinal(w)">
|
<p v-if="isUserSubscribedToFinal(w)">
|
||||||
<i class="fa fa-check fa-fw"></i>
|
<i class="fa fa-check fa-fw"></i>
|
||||||
{{ $t("you_subscribed_to_final_step") }}
|
{{ trans(WORKFLOW_YOU_SUBSCRIBED_TO_FINAL_STEP) }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-col">
|
<div class="item-col">
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
<a
|
<a
|
||||||
:href="goToUrl(w)"
|
:href="goToUrl(w)"
|
||||||
class="btn btn-sm btn-show"
|
class="btn btn-sm btn-show"
|
||||||
:title="$t('action.show')"
|
:title="trans(SEE)"
|
||||||
></a>
|
></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -79,85 +79,65 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import Popover from "bootstrap/js/src/popover";
|
import Popover from "bootstrap/js/src/popover";
|
||||||
|
import { onMounted } from "vue";
|
||||||
|
import {
|
||||||
|
trans,
|
||||||
|
BY_USER,
|
||||||
|
SEE,
|
||||||
|
WORKFLOW_YOU_SUBSCRIBED_TO_ALL_STEPS,
|
||||||
|
WORKFLOW_YOU_SUBSCRIBED_TO_FINAL_STEP,
|
||||||
|
WORKFLOW_ON_HOLD,
|
||||||
|
WORKFLOW_AT,
|
||||||
|
} from "translator";
|
||||||
|
|
||||||
const i18n = {
|
// props
|
||||||
messages: {
|
const props = defineProps({
|
||||||
fr: {
|
workflows: {
|
||||||
you_subscribed_to_all_steps:
|
type: Array,
|
||||||
"Vous recevrez une notification à chaque étape",
|
required: true,
|
||||||
you_subscribed_to_final_step:
|
|
||||||
"Vous recevrez une notification à l'étape finale",
|
|
||||||
by: "Par",
|
|
||||||
at: "Le",
|
|
||||||
on_hold: "En attente",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// methods
|
||||||
|
const goToUrl = (w) => `/fr/main/workflow/${w.id}/show`;
|
||||||
|
const getPopTitle = (step) => {
|
||||||
|
if (step.transitionPrevious != null) {
|
||||||
|
//console.log(step.transitionPrevious.text);
|
||||||
|
let freezed = step.isFreezed
|
||||||
|
? `<i class="fa fa-snowflake-o fa-sm me-1"></i>`
|
||||||
|
: ``;
|
||||||
|
return `${freezed}${step.transitionPrevious.text}`;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
const getPopContent = (step) => {
|
||||||
|
if (step.transitionPrevious != null) {
|
||||||
|
if (step.transitionPreviousBy !== null) {
|
||||||
|
return `<ul class="small_in_title">
|
||||||
|
<li><span class="item-key">${trans(BY_USER)} : </span><b>${step.transitionPreviousBy.text}</b></li>
|
||||||
|
<li><span class="item-key">${trans(WORKFLOW_AT)} : </span><b>${formatDate(step.transitionPreviousAt.datetime)}</b></li>
|
||||||
|
</ul>`;
|
||||||
|
} else {
|
||||||
|
return `<ul class="small_in_title">
|
||||||
|
<li><span class="item-key">${trans(WORKFLOW_AT)} : </span><b>${formatDate(step.transitionPreviousAt.datetime)}</b></li>
|
||||||
|
</ul>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const formatDate = (datetime) =>
|
||||||
|
datetime.split("T")[0] + " " + datetime.split("T")[1].substring(0, 5);
|
||||||
|
const isUserSubscribedToStep = () => false;
|
||||||
|
const isUserSubscribedToFinal = () => false;
|
||||||
|
|
||||||
export default {
|
onMounted(() => {
|
||||||
name: "ListWorkflow",
|
const triggerList = [].slice.call(
|
||||||
i18n: i18n,
|
document.querySelectorAll('[data-bs-toggle="popover"]'),
|
||||||
props: {
|
);
|
||||||
workflows: {
|
triggerList.map(function (el) {
|
||||||
type: Array,
|
return new Popover(el, {
|
||||||
required: true,
|
html: true,
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
goToUrl(w) {
|
|
||||||
return `/fr/main/workflow/${w.id}/show`;
|
|
||||||
},
|
|
||||||
getPopTitle(step) {
|
|
||||||
if (step.transitionPrevious != null) {
|
|
||||||
//console.log(step.transitionPrevious.text);
|
|
||||||
let freezed = step.isFreezed
|
|
||||||
? `<i class="fa fa-snowflake-o fa-sm me-1"></i>`
|
|
||||||
: ``;
|
|
||||||
return `${freezed}${step.transitionPrevious.text}`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getPopContent(step) {
|
|
||||||
if (step.transitionPrevious != null) {
|
|
||||||
if (step.transitionPreviousBy !== null) {
|
|
||||||
return `<ul class="small_in_title">
|
|
||||||
<li><span class="item-key">${i18n.messages.fr.by} : </span><b>${step.transitionPreviousBy.text}</b></li>
|
|
||||||
<li><span class="item-key">${i18n.messages.fr.at} : </span><b>${this.formatDate(step.transitionPreviousAt.datetime)}</b></li>
|
|
||||||
</ul>`;
|
|
||||||
} else {
|
|
||||||
return `<ul class="small_in_title">
|
|
||||||
<li><span class="item-key">${i18n.messages.fr.at} : </span><b>${this.formatDate(step.transitionPreviousAt.datetime)}</b></li>
|
|
||||||
</ul>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formatDate(datetime) {
|
|
||||||
return (
|
|
||||||
datetime.split("T")[0] +
|
|
||||||
" " +
|
|
||||||
datetime.split("T")[1].substring(0, 5)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
isUserSubscribedToStep(w) {
|
|
||||||
// todo
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
isUserSubscribedToFinal(w) {
|
|
||||||
// todo
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
const triggerList = [].slice.call(
|
|
||||||
document.querySelectorAll('[data-bs-toggle="popover"]'),
|
|
||||||
);
|
|
||||||
const popoverList = triggerList.map(function (el) {
|
|
||||||
//console.log('popover', el)
|
|
||||||
return new Popover(el, {
|
|
||||||
html: true,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
};
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,23 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<pick-workflow
|
<Pick-workflow
|
||||||
:relatedEntityClass="this.relatedEntityClass"
|
:relatedEntityClass="props.relatedEntityClass"
|
||||||
:relatedEntityId="this.relatedEntityId"
|
:relatedEntityId="props.relatedEntityId"
|
||||||
:workflowsAvailables="workflowsAvailables"
|
:workflowsAvailables="props.workflowsAvailables"
|
||||||
:preventDefaultMoveToGenerate="this.$props.preventDefaultMoveToGenerate"
|
:preventDefaultMoveToGenerate="props.preventDefaultMoveToGenerate"
|
||||||
:goToGenerateWorkflowPayload="this.goToGenerateWorkflowPayload"
|
:goToGenerateWorkflowPayload="props.goToGenerateWorkflowPayload"
|
||||||
:countExistingWorkflows="countWorkflows"
|
:countExistingWorkflows="countWorkflows"
|
||||||
|
:embedded-within-list-modal="false"
|
||||||
@go-to-generate-workflow="goToGenerateWorkflow"
|
@go-to-generate-workflow="goToGenerateWorkflow"
|
||||||
@click-open-list="openModal"
|
@click-open-list="openModal"
|
||||||
></pick-workflow>
|
></Pick-workflow>
|
||||||
|
|
||||||
<teleport to="body">
|
<teleport to="body">
|
||||||
<modal
|
<Modal
|
||||||
v-if="modal.showModal"
|
v-if="modal.showModal"
|
||||||
:modalDialogClass="modal.modalDialogClass"
|
:modalDialogClass="modal.modalDialogClass"
|
||||||
@close="modal.showModal = false"
|
@close="modal.showModal = false"
|
||||||
>
|
>
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<h2 class="modal-title">{{ $t("workflow_list") }}</h2>
|
<h2 class="modal-title">{{ trans(WORKFLOW_LIST) }}</h2>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:body>
|
<template v-slot:body>
|
||||||
@@ -27,103 +28,80 @@
|
|||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<pick-workflow
|
<pick-workflow
|
||||||
v-if="allowCreate"
|
v-if="allowCreate"
|
||||||
:relatedEntityClass="this.relatedEntityClass"
|
:relatedEntityClass="props.relatedEntityClass"
|
||||||
:relatedEntityId="this.relatedEntityId"
|
:relatedEntityId="props.relatedEntityId"
|
||||||
:workflowsAvailables="workflowsAvailables"
|
:workflowsAvailables="props.workflowsAvailables"
|
||||||
:preventDefaultMoveToGenerate="
|
:preventDefaultMoveToGenerate="
|
||||||
this.$props.preventDefaultMoveToGenerate
|
props.preventDefaultMoveToGenerate
|
||||||
"
|
"
|
||||||
:goToGenerateWorkflowPayload="
|
:goToGenerateWorkflowPayload="
|
||||||
this.goToGenerateWorkflowPayload
|
props.goToGenerateWorkflowPayload
|
||||||
"
|
"
|
||||||
:countExistingWorkflows="countWorkflows"
|
:countExistingWorkflows="countWorkflows"
|
||||||
:embedded-within-list-modal="true"
|
:embedded-within-list-modal="true"
|
||||||
@go-to-generate-workflow="this.goToGenerateWorkflow"
|
@go-to-generate-workflow="goToGenerateWorkflow"
|
||||||
></pick-workflow>
|
></pick-workflow>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</Modal>
|
||||||
</teleport>
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
|
import { ref, computed, defineProps, defineEmits } from "vue";
|
||||||
import Modal from "ChillMainAssets/vuejs/_components/Modal";
|
import Modal from "ChillMainAssets/vuejs/_components/Modal";
|
||||||
import PickWorkflow from "ChillMainAssets/vuejs/_components/EntityWorkflow/PickWorkflow.vue";
|
import PickWorkflow from "ChillMainAssets/vuejs/_components/EntityWorkflow/PickWorkflow.vue";
|
||||||
import ListWorkflowVue from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflow.vue";
|
import ListWorkflowVue from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflow.vue";
|
||||||
|
import { trans, WORKFLOW_LIST } from "translator";
|
||||||
|
|
||||||
export default {
|
// Define props
|
||||||
name: "ListWorkflowModal",
|
const props = defineProps({
|
||||||
components: {
|
workflows: {
|
||||||
Modal,
|
type: Array,
|
||||||
PickWorkflow,
|
required: true,
|
||||||
ListWorkflowVue,
|
|
||||||
},
|
},
|
||||||
emits: ["goToGenerateWorkflow"],
|
allowCreate: {
|
||||||
props: {
|
type: Boolean,
|
||||||
workflows: {
|
required: true,
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
allowCreate: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
relatedEntityClass: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
relatedEntityId: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
workflowsAvailables: {
|
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
preventDefaultMoveToGenerate: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
goToGenerateWorkflowPayload: {
|
|
||||||
required: false,
|
|
||||||
default: {},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data() {
|
relatedEntityClass: {
|
||||||
return {
|
type: String,
|
||||||
modal: {
|
required: true,
|
||||||
showModal: false,
|
|
||||||
modalDialogClass: "modal-dialog-scrollable modal-xl",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
computed: {
|
relatedEntityId: {
|
||||||
countWorkflows() {
|
type: Number,
|
||||||
return this.workflows.length;
|
required: false,
|
||||||
},
|
|
||||||
hasWorkflow() {
|
|
||||||
return this.countWorkflows > 0;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
workflowsAvailables: {
|
||||||
openModal() {
|
type: Array,
|
||||||
this.modal.showModal = true;
|
required: true,
|
||||||
},
|
|
||||||
goToGenerateWorkflow(data) {
|
|
||||||
console.log("go to generate workflow intercepted", data);
|
|
||||||
this.$emit("goToGenerateWorkflow", data);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
i18n: {
|
preventDefaultMoveToGenerate: {
|
||||||
messages: {
|
type: Boolean,
|
||||||
fr: {
|
required: false,
|
||||||
workflow_list: "Liste des workflows associés",
|
default: false,
|
||||||
workflow: " workflow associé",
|
|
||||||
workflows: " workflows associés",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
goToGenerateWorkflowPayload: {
|
||||||
|
required: false,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Define emits
|
||||||
|
const emit = defineEmits(["goToGenerateWorkflow"]);
|
||||||
|
|
||||||
|
// Reactive data
|
||||||
|
const modal = ref({
|
||||||
|
showModal: false,
|
||||||
|
modalDialogClass: "modal-dialog-scrollable modal-xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Computed properties
|
||||||
|
const countWorkflows = computed(() => props.workflows.length);
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
const openModal = () => (modal.value.showModal = true);
|
||||||
|
|
||||||
|
const goToGenerateWorkflow = (data) => emit("goToGenerateWorkflow", data);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@@ -8,28 +8,28 @@
|
|||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
>
|
>
|
||||||
<div class="modal-dialog" :class="modalDialogClass">
|
<div class="modal-dialog" :class="props.modalDialogClass || {}">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<slot name="header" />
|
<slot name="header"></slot>
|
||||||
<button class="close btn" @click="$emit('close')">
|
<button class="close btn" @click="emits('close')">
|
||||||
<i class="fa fa-times" aria-hidden="true" />
|
<i class="fa fa-times" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="body-head">
|
<div class="body-head">
|
||||||
<slot name="body-head" />
|
<slot name="body-head"></slot>
|
||||||
</div>
|
</div>
|
||||||
<slot name="body" />
|
<slot name="body"></slot>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer" v-if="!hideFooter">
|
<div class="modal-footer" v-if="!hideFooter">
|
||||||
<button
|
<button
|
||||||
class="btn btn-cancel"
|
class="btn btn-cancel"
|
||||||
@click="$emit('close')"
|
@click="emits('close')"
|
||||||
>
|
>
|
||||||
{{ $t("action.close") }}
|
{{ trans(MODAL_ACTION_CLOSE) }}
|
||||||
</button>
|
</button>
|
||||||
<slot name="footer" />
|
<slot name="footer"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,8 +39,7 @@
|
|||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent } from "vue";
|
|
||||||
/*
|
/*
|
||||||
* This Modal component is a mix between Vue3 modal implementation
|
* This Modal component is a mix between Vue3 modal implementation
|
||||||
* [+] with 'v-if:showModal' directive:parameter, html scope is added/removed not just shown/hidden
|
* [+] with 'v-if:showModal' directive:parameter, html scope is added/removed not just shown/hidden
|
||||||
@@ -50,22 +49,23 @@ import { defineComponent } from "vue";
|
|||||||
* [+] using bootstrap css classes, the modal have a responsive behaviour,
|
* [+] using bootstrap css classes, the modal have a responsive behaviour,
|
||||||
* [+] modal design can be configured using css classes (size, scroll)
|
* [+] modal design can be configured using css classes (size, scroll)
|
||||||
*/
|
*/
|
||||||
export default defineComponent({
|
import { trans, MODAL_ACTION_CLOSE } from "translator";
|
||||||
name: "Modal",
|
import { defineProps } from "vue";
|
||||||
props: {
|
|
||||||
modalDialogClass: {
|
export interface ModalProps {
|
||||||
type: Object,
|
modalDialogClass: object | null;
|
||||||
required: false,
|
hideFooter: boolean;
|
||||||
default: {},
|
}
|
||||||
},
|
|
||||||
hideFooter: {
|
// Define the props
|
||||||
type: Boolean,
|
const props = withDefaults(defineProps<ModalProps>(), {
|
||||||
required: false,
|
hideFooter: false,
|
||||||
default: false,
|
modalDialogClass: null,
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["close"],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
close: [];
|
||||||
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@@ -9,12 +9,12 @@
|
|||||||
class="btn"
|
class="btn"
|
||||||
:class="overrideClass"
|
:class="overrideClass"
|
||||||
type="button"
|
type="button"
|
||||||
:title="$t('markAsUnread')"
|
:title="trans(NOTIFICATION_MARK_AS_UNREAD)"
|
||||||
@click="markAsUnread"
|
@click="markAsUnread"
|
||||||
>
|
>
|
||||||
<i class="fa fa-sm fa-envelope-o" />
|
<i class="fa fa-sm fa-envelope-o"></i>
|
||||||
<span v-if="!buttonNoText" class="ps-2">
|
<span v-if="!props.buttonNoText" class="ps-2">
|
||||||
{{ $t("markAsUnread") }}
|
{{ trans(NOTIFICATION_MARK_AS_UNREAD) }}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -23,12 +23,12 @@
|
|||||||
class="btn"
|
class="btn"
|
||||||
:class="overrideClass"
|
:class="overrideClass"
|
||||||
type="button"
|
type="button"
|
||||||
:title="$t('markAsRead')"
|
:title="trans(NOTIFICATION_MARK_AS_READ)"
|
||||||
@click="markAsRead"
|
@click="markAsRead"
|
||||||
>
|
>
|
||||||
<i class="fa fa-sm fa-envelope-open-o" />
|
<i class="fa fa-sm fa-envelope-open-o"></i>
|
||||||
<span v-if="!buttonNoText" class="ps-2">
|
<span v-if="!buttonNoText" class="ps-2">
|
||||||
{{ $t("markAsRead") }}
|
{{ trans(NOTIFICATION_MARK_AS_READ) }}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -37,9 +37,9 @@
|
|||||||
type="button"
|
type="button"
|
||||||
class="btn btn-outline-primary"
|
class="btn btn-outline-primary"
|
||||||
:href="showUrl"
|
:href="showUrl"
|
||||||
:title="$t('action.show')"
|
:title="trans(SEE)"
|
||||||
>
|
>
|
||||||
<i class="fa fa-sm fa-comment-o" />
|
<i class="fa fa-sm fa-comment-o"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<!-- "Mark All Read" button -->
|
<!-- "Mark All Read" button -->
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
:title="$t('markAllRead')"
|
:title="$t('markAllRead')"
|
||||||
@click="markAllRead"
|
@click="markAllRead"
|
||||||
>
|
>
|
||||||
<i class="fa fa-sm fa-envelope-o" />
|
<i class="fa fa-sm fa-envelope-o"></i>
|
||||||
<span v-if="!buttonNoText" class="ps-2">
|
<span v-if="!buttonNoText" class="ps-2">
|
||||||
{{ $t("markAllRead") }}
|
{{ $t("markAllRead") }}
|
||||||
</span>
|
</span>
|
||||||
@@ -59,89 +59,66 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
|
import { computed } from "vue";
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts";
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts";
|
||||||
|
import {
|
||||||
|
trans,
|
||||||
|
NOTIFICATION_MARK_AS_READ,
|
||||||
|
NOTIFICATION_MARK_AS_UNREAD,
|
||||||
|
SEE,
|
||||||
|
} from "translator";
|
||||||
|
|
||||||
export default {
|
// Props
|
||||||
name: "NotificationReadToggle",
|
const props = defineProps({
|
||||||
props: {
|
isRead: {
|
||||||
isRead: {
|
type: Boolean,
|
||||||
required: true,
|
required: true,
|
||||||
type: Boolean,
|
|
||||||
},
|
|
||||||
notificationId: {
|
|
||||||
required: true,
|
|
||||||
type: Number,
|
|
||||||
},
|
|
||||||
// Optional
|
|
||||||
buttonClass: {
|
|
||||||
required: false,
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
buttonNoText: {
|
|
||||||
required: false,
|
|
||||||
type: Boolean,
|
|
||||||
},
|
|
||||||
showUrl: {
|
|
||||||
required: false,
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
emits: ["markRead", "markUnread"],
|
notificationId: {
|
||||||
computed: {
|
type: Number,
|
||||||
/// [Option] override default button appearance (btn-misc)
|
required: true,
|
||||||
overrideClass() {
|
|
||||||
return this.buttonClass ? this.buttonClass : "btn-misc";
|
|
||||||
},
|
|
||||||
/// [Option] don't display text on button
|
|
||||||
buttonHideText() {
|
|
||||||
return this.buttonNoText;
|
|
||||||
},
|
|
||||||
/// [Option] showUrl is href for show page second button.
|
|
||||||
// When passed, the component return a button-group with 2 buttons.
|
|
||||||
isButtonGroup() {
|
|
||||||
return this.showUrl;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
buttonClass: {
|
||||||
markAsUnread() {
|
type: String,
|
||||||
makeFetch(
|
required: false,
|
||||||
"POST",
|
|
||||||
`/api/1.0/main/notification/${this.notificationId}/mark/unread`,
|
|
||||||
[],
|
|
||||||
).then(() => {
|
|
||||||
this.$emit("markRead", { notificationId: this.notificationId });
|
|
||||||
});
|
|
||||||
},
|
|
||||||
markAsRead() {
|
|
||||||
makeFetch(
|
|
||||||
"POST",
|
|
||||||
`/api/1.0/main/notification/${this.notificationId}/mark/read`,
|
|
||||||
[],
|
|
||||||
).then(() => {
|
|
||||||
this.$emit("markUnread", {
|
|
||||||
notificationId: this.notificationId,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
markAllRead() {
|
|
||||||
makeFetch(
|
|
||||||
"POST",
|
|
||||||
`/api/1.0/main/notification/markallread`,
|
|
||||||
[],
|
|
||||||
).then(() => {
|
|
||||||
this.$emit("markAllRead");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
i18n: {
|
buttonNoText: {
|
||||||
messages: {
|
type: Boolean,
|
||||||
fr: {
|
required: false,
|
||||||
markAsUnread: "Marquer comme non-lu",
|
|
||||||
markAsRead: "Marquer comme lu",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
showUrl: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Emits
|
||||||
|
const emit = defineEmits(["markRead", "markUnread"]);
|
||||||
|
|
||||||
|
// Computed
|
||||||
|
const overrideClass = computed(() => props.buttonClass || "btn-misc");
|
||||||
|
const isButtonGroup = computed(() => props.showUrl);
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
const markAsUnread = () => {
|
||||||
|
makeFetch(
|
||||||
|
"POST",
|
||||||
|
`/api/1.0/main/notification/${props.notificationId}/mark/unread`,
|
||||||
|
[],
|
||||||
|
).then(() => {
|
||||||
|
emit("markRead", { notificationId: props.notificationId });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const markAsRead = () => {
|
||||||
|
makeFetch(
|
||||||
|
"POST",
|
||||||
|
`/api/1.0/main/notification/${props.notificationId}/mark/read`,
|
||||||
|
[],
|
||||||
|
).then(() => {
|
||||||
|
emit("markUnread", { notificationId: props.notificationId });
|
||||||
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -8,10 +8,10 @@
|
|||||||
]"
|
]"
|
||||||
@click="openModal"
|
@click="openModal"
|
||||||
>
|
>
|
||||||
<i v-if="isChangeIcon" class="fa me-2" :class="options.changeIcon" />
|
<i v-if="isChangeIcon" class="fa me-2" :class="options.changeIcon"></i>
|
||||||
|
|
||||||
<span v-if="!noText">
|
<span v-if="!noText">
|
||||||
{{ $t("online_edit_document") }}
|
{{ trans(WOPI_ONLINE_EDIT_DOCUMENT) }}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@
|
|||||||
<div class="wopi-frame" v-if="isOpenDocument">
|
<div class="wopi-frame" v-if="isOpenDocument">
|
||||||
<modal
|
<modal
|
||||||
v-if="modal.showModal"
|
v-if="modal.showModal"
|
||||||
:modal-dialog-class="modal.modalDialogClass"
|
:modalDialogClass="modal.modalDialogClass"
|
||||||
:hide-footer="true"
|
:hideFooter="true"
|
||||||
@close="modal.showModal = false"
|
@close="modal.showModal = false"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
@@ -28,203 +28,164 @@
|
|||||||
<span class="ms-auto me-3">
|
<span class="ms-auto me-3">
|
||||||
<span v-if="options.title">{{ options.title }}</span>
|
<span v-if="options.title">{{ options.title }}</span>
|
||||||
</span>
|
</span>
|
||||||
<!--
|
|
||||||
<a class="btn btn-outline-light">
|
|
||||||
<i class="fa fa-save fa-fw"></i>
|
|
||||||
{{ $t('save_and_quit') }}
|
|
||||||
</a>
|
|
||||||
-->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #body>
|
<template #body>
|
||||||
<div v-if="loading" class="loading">
|
<div v-if="loading" class="loading">
|
||||||
<i
|
<i
|
||||||
class="fa fa-circle-o-notch fa-spin fa-3x"
|
class="fa fa-circle-o-notch fa-spin fa-3x"
|
||||||
:title="$t('loading')"
|
:title="trans(WOPI_LOADING)"
|
||||||
/>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
<iframe :src="this.wopiUrl" @load="loaded" />
|
<iframe :src="this.wopiUrl" @load="loaded"></iframe>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</modal>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<modal
|
<Modal
|
||||||
v-if="modal.showModal"
|
v-if="modal.showModal"
|
||||||
modal-dialog-class="modal-sm"
|
modalDialogClass="modal-sm"
|
||||||
@close="modal.showModal = false"
|
@close="modal.showModal = false"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template v-slot:header>
|
||||||
<h3>{{ $t("invalid_title") }}</h3>
|
<h3>{{ trans(WOPI_INVALID_TITLE) }}</h3>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template v-slot:body>
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
{{ $t("invalid_message") }}
|
{{ trans(WOPI_ONLINE_EDIT_DOCUMENT) }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</teleport>
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
|
import { ref, computed } from "vue";
|
||||||
|
import {
|
||||||
|
trans,
|
||||||
|
WOPI_ONLINE_EDIT_DOCUMENT,
|
||||||
|
WOPI_INVALID_TITLE,
|
||||||
|
WOPI_LOADING,
|
||||||
|
} from "translator";
|
||||||
import Modal from "ChillMainAssets/vuejs/_components/Modal";
|
import Modal from "ChillMainAssets/vuejs/_components/Modal";
|
||||||
import logo from "ChillMainAssets/chill/img/logo-chill-sans-slogan_white.png";
|
import logo from "ChillMainAssets/chill/img/logo-chill-sans-slogan_white.png";
|
||||||
|
|
||||||
export default {
|
// Props
|
||||||
name: "OpenWopiLink",
|
const props = defineProps({
|
||||||
components: {
|
wopiUrl: {
|
||||||
Modal,
|
type: String,
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
props: {
|
type: {
|
||||||
wopiUrl: {
|
type: String,
|
||||||
type: String,
|
required: true,
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data() {
|
options: {
|
||||||
return {
|
type: Object,
|
||||||
modal: {
|
required: false,
|
||||||
showModal: false,
|
|
||||||
modalDialogClass: "modal-fullscreen", //modal-dialog-scrollable
|
|
||||||
},
|
|
||||||
logo: logo,
|
|
||||||
loading: false,
|
|
||||||
mime: [
|
|
||||||
// TODO temporary hardcoded. to be replaced by twig extension or a collabora server query
|
|
||||||
"application/clarisworks",
|
|
||||||
"application/coreldraw",
|
|
||||||
"application/macwriteii",
|
|
||||||
"application/msword",
|
|
||||||
"application/pdf",
|
|
||||||
"application/vnd.lotus-1-2-3",
|
|
||||||
"application/vnd.ms-excel",
|
|
||||||
"application/vnd.ms-excel.sheet.binary.macroEnabled.12",
|
|
||||||
"application/vnd.ms-excel.sheet.macroEnabled.12",
|
|
||||||
"application/vnd.ms-excel.template.macroEnabled.12",
|
|
||||||
"application/vnd.ms-powerpoint",
|
|
||||||
"application/vnd.ms-powerpoint.presentation.macroEnabled.12",
|
|
||||||
"application/vnd.ms-powerpoint.template.macroEnabled.12",
|
|
||||||
"application/vnd.ms-visio.drawing",
|
|
||||||
"application/vnd.ms-word.document.macroEnabled.12",
|
|
||||||
"application/vnd.ms-word.template.macroEnabled.12",
|
|
||||||
"application/vnd.ms-works",
|
|
||||||
"application/vnd.oasis.opendocument.chart",
|
|
||||||
"application/vnd.oasis.opendocument.formula",
|
|
||||||
"application/vnd.oasis.opendocument.graphics",
|
|
||||||
"application/vnd.oasis.opendocument.graphics-flat-xml",
|
|
||||||
"application/vnd.oasis.opendocument.graphics-template",
|
|
||||||
"application/vnd.oasis.opendocument.presentation",
|
|
||||||
"application/vnd.oasis.opendocument.presentation-flat-xml",
|
|
||||||
"application/vnd.oasis.opendocument.presentation-template",
|
|
||||||
"application/vnd.oasis.opendocument.spreadsheet",
|
|
||||||
"application/vnd.oasis.opendocument.spreadsheet-flat-xml",
|
|
||||||
"application/vnd.oasis.opendocument.spreadsheet-template",
|
|
||||||
"application/vnd.oasis.opendocument.text",
|
|
||||||
"application/vnd.oasis.opendocument.text-flat-xml",
|
|
||||||
"application/vnd.oasis.opendocument.text-master",
|
|
||||||
"application/vnd.oasis.opendocument.text-master-template",
|
|
||||||
"application/vnd.oasis.opendocument.text-template",
|
|
||||||
"application/vnd.oasis.opendocument.text-web",
|
|
||||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
||||||
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
|
||||||
"application/vnd.openxmlformats-officedocument.presentationml.template",
|
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
|
||||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
||||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
|
||||||
"application/vnd.sun.xml.calc",
|
|
||||||
"application/vnd.sun.xml.calc.template",
|
|
||||||
"application/vnd.sun.xml.chart",
|
|
||||||
"application/vnd.sun.xml.draw",
|
|
||||||
"application/vnd.sun.xml.draw.template",
|
|
||||||
"application/vnd.sun.xml.impress",
|
|
||||||
"application/vnd.sun.xml.impress.template",
|
|
||||||
"application/vnd.sun.xml.math",
|
|
||||||
"application/vnd.sun.xml.writer",
|
|
||||||
"application/vnd.sun.xml.writer.global",
|
|
||||||
"application/vnd.sun.xml.writer.template",
|
|
||||||
"application/vnd.visio",
|
|
||||||
"application/vnd.visio2013",
|
|
||||||
"application/vnd.wordperfect",
|
|
||||||
"application/x-abiword",
|
|
||||||
"application/x-aportisdoc",
|
|
||||||
"application/x-dbase",
|
|
||||||
"application/x-dif-document",
|
|
||||||
"application/x-fictionbook+xml",
|
|
||||||
"application/x-gnumeric",
|
|
||||||
"application/x-hwp",
|
|
||||||
"application/x-iwork-keynote-sffkey",
|
|
||||||
"application/x-iwork-numbers-sffnumbers",
|
|
||||||
"application/x-iwork-pages-sffpages",
|
|
||||||
"application/x-mspublisher",
|
|
||||||
"application/x-mswrite",
|
|
||||||
"application/x-pagemaker",
|
|
||||||
"application/x-sony-bbeb",
|
|
||||||
"application/x-t602",
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
isOpenDocument() {
|
|
||||||
if (this.mime.indexOf(this.type) !== -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
noText() {
|
|
||||||
if (typeof this.options.noText !== "undefined") {
|
|
||||||
return this.options.noText === true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
isChangeIcon() {
|
|
||||||
if (typeof this.options.changeIcon !== "undefined") {
|
|
||||||
return !(
|
|
||||||
this.options.changeIcon === null ||
|
|
||||||
this.options.changeIcon === ""
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
isChangeClass() {
|
|
||||||
if (typeof this.options.changeClass !== "undefined") {
|
|
||||||
return !(
|
|
||||||
this.options.changeClass === null ||
|
|
||||||
this.options.changeClass === ""
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openModal() {
|
|
||||||
this.loading = true;
|
|
||||||
this.modal.showModal = true;
|
|
||||||
},
|
|
||||||
loaded() {
|
|
||||||
this.loading = false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
i18n: {
|
|
||||||
messages: {
|
|
||||||
fr: {
|
|
||||||
online_edit_document: "Éditer en ligne",
|
|
||||||
save_and_quit: "Enregistrer et quitter",
|
|
||||||
loading: "Chargement de l'éditeur en ligne",
|
|
||||||
invalid_title: "Format incompatible",
|
|
||||||
invalid_message:
|
|
||||||
"Désolé, ce format de document n'est pas éditable en ligne.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// data
|
||||||
|
const modal = ref({
|
||||||
|
showModal: false,
|
||||||
|
modalDialogClass: "modal-fullscreen",
|
||||||
|
});
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// MIME types
|
||||||
|
const mime = [
|
||||||
|
// TODO temporary hardcoded. to be replaced by twig extension or a collabora server query
|
||||||
|
"application/clarisworks",
|
||||||
|
"application/coreldraw",
|
||||||
|
"application/macwriteii",
|
||||||
|
"application/msword",
|
||||||
|
"application/pdf",
|
||||||
|
"application/vnd.lotus-1-2-3",
|
||||||
|
"application/vnd.ms-excel",
|
||||||
|
"application/vnd.ms-excel.sheet.binary.macroEnabled.12",
|
||||||
|
"application/vnd.ms-excel.sheet.macroEnabled.12",
|
||||||
|
"application/vnd.ms-excel.template.macroEnabled.12",
|
||||||
|
"application/vnd.ms-powerpoint",
|
||||||
|
"application/vnd.ms-powerpoint.presentation.macroEnabled.12",
|
||||||
|
"application/vnd.ms-powerpoint.template.macroEnabled.12",
|
||||||
|
"application/vnd.ms-visio.drawing",
|
||||||
|
"application/vnd.ms-word.document.macroEnabled.12",
|
||||||
|
"application/vnd.ms-word.template.macroEnabled.12",
|
||||||
|
"application/vnd.ms-works",
|
||||||
|
"application/vnd.oasis.opendocument.chart",
|
||||||
|
"application/vnd.oasis.opendocument.formula",
|
||||||
|
"application/vnd.oasis.opendocument.graphics",
|
||||||
|
"application/vnd.oasis.opendocument.graphics-flat-xml",
|
||||||
|
"application/vnd.oasis.opendocument.graphics-template",
|
||||||
|
"application/vnd.oasis.opendocument.presentation",
|
||||||
|
"application/vnd.oasis.opendocument.presentation-flat-xml",
|
||||||
|
"application/vnd.oasis.opendocument.presentation-template",
|
||||||
|
"application/vnd.oasis.opendocument.spreadsheet",
|
||||||
|
"application/vnd.oasis.opendocument.spreadsheet-flat-xml",
|
||||||
|
"application/vnd.oasis.opendocument.spreadsheet-template",
|
||||||
|
"application/vnd.oasis.opendocument.text",
|
||||||
|
"application/vnd.oasis.opendocument.text-flat-xml",
|
||||||
|
"application/vnd.oasis.opendocument.text-master",
|
||||||
|
"application/vnd.oasis.opendocument.text-master-template",
|
||||||
|
"application/vnd.oasis.opendocument.text-template",
|
||||||
|
"application/vnd.oasis.opendocument.text-web",
|
||||||
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||||
|
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
||||||
|
"application/vnd.openxmlformats-officedocument.presentationml.template",
|
||||||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
||||||
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
||||||
|
"application/vnd.sun.xml.calc",
|
||||||
|
"application/vnd.sun.xml.calc.template",
|
||||||
|
"application/vnd.sun.xml.chart",
|
||||||
|
"application/vnd.sun.xml.draw",
|
||||||
|
"application/vnd.sun.xml.draw.template",
|
||||||
|
"application/vnd.sun.xml.impress",
|
||||||
|
"application/vnd.sun.xml.impress.template",
|
||||||
|
"application/vnd.sun.xml.math",
|
||||||
|
"application/vnd.sun.xml.writer",
|
||||||
|
"application/vnd.sun.xml.writer.global",
|
||||||
|
"application/vnd.sun.xml.writer.template",
|
||||||
|
"application/vnd.visio",
|
||||||
|
"application/vnd.visio2013",
|
||||||
|
"application/vnd.wordperfect",
|
||||||
|
"application/x-abiword",
|
||||||
|
"application/x-aportisdoc",
|
||||||
|
"application/x-dbase",
|
||||||
|
"application/x-dif-document",
|
||||||
|
"application/x-fictionbook+xml",
|
||||||
|
"application/x-gnumeric",
|
||||||
|
"application/x-hwp",
|
||||||
|
"application/x-iwork-keynote-sffkey",
|
||||||
|
"application/x-iwork-numbers-sffnumbers",
|
||||||
|
"application/x-iwork-pages-sffpages",
|
||||||
|
"application/x-mspublisher",
|
||||||
|
"application/x-mswrite",
|
||||||
|
"application/x-pagemaker",
|
||||||
|
"application/x-sony-bbeb",
|
||||||
|
"application/x-t602",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Computed
|
||||||
|
const isOpenDocument = computed(() => mime.includes(props.type));
|
||||||
|
|
||||||
|
const noText = computed(() => props.options?.noText === true);
|
||||||
|
|
||||||
|
const isChangeIcon = computed(() => !!props.options?.changeIcon);
|
||||||
|
|
||||||
|
const isChangeClass = computed(() => !!props.options?.changeClass);
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
const openModal = () => {
|
||||||
|
loading.value = true;
|
||||||
|
modal.value.showModal = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const loaded = () => {
|
||||||
|
loading.value = false;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -34,6 +34,7 @@ class GenderDocGenNormalizer implements ContextAwareNormalizerInterface, Normali
|
|||||||
'id' => $gender->getId(),
|
'id' => $gender->getId(),
|
||||||
'label' => $this->translatableStringHelper->localize($gender->getLabel()),
|
'label' => $this->translatableStringHelper->localize($gender->getLabel()),
|
||||||
'genderTranslation' => $gender->getGenderTranslation(),
|
'genderTranslation' => $gender->getGenderTranslation(),
|
||||||
|
'type' => 'chill_main_gender',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -68,8 +68,8 @@ class AddressReferenceBEFromBestAddress
|
|||||||
$csv->setDelimiter(',');
|
$csv->setDelimiter(',');
|
||||||
$csv->setHeaderOffset(0);
|
$csv->setHeaderOffset(0);
|
||||||
|
|
||||||
$stmt = Statement::create()
|
$stmt = new Statement();
|
||||||
->process($csv);
|
$stmt = $stmt->process($csv);
|
||||||
|
|
||||||
foreach ($stmt as $record) {
|
foreach ($stmt as $record) {
|
||||||
$this->baseImporter->importAddress(
|
$this->baseImporter->importAddress(
|
||||||
|
@@ -55,32 +55,32 @@ class AddressReferenceFromBAN
|
|||||||
|
|
||||||
$csv = Reader::createFromStream($csvDecompressed);
|
$csv = Reader::createFromStream($csvDecompressed);
|
||||||
$csv->setDelimiter(';')->setHeaderOffset(0);
|
$csv->setDelimiter(';')->setHeaderOffset(0);
|
||||||
$stmt = Statement::create()
|
$stmt = new Statement();
|
||||||
->process($csv, [
|
$stmt = $stmt->process($csv, [
|
||||||
'id',
|
'id',
|
||||||
'id_fantoir',
|
'id_fantoir',
|
||||||
'numero',
|
'numero',
|
||||||
'rep',
|
'rep',
|
||||||
'nom_voie',
|
'nom_voie',
|
||||||
'code_postal',
|
'code_postal',
|
||||||
'code_insee',
|
'code_insee',
|
||||||
'nom_commune',
|
'nom_commune',
|
||||||
'code_insee_ancienne_commune',
|
'code_insee_ancienne_commune',
|
||||||
'nom_ancienne_commune',
|
'nom_ancienne_commune',
|
||||||
'x',
|
'x',
|
||||||
'y',
|
'y',
|
||||||
'lon',
|
'lon',
|
||||||
'lat',
|
'lat',
|
||||||
'type_position',
|
'type_position',
|
||||||
'alias',
|
'alias',
|
||||||
'nom_ld',
|
'nom_ld',
|
||||||
'libelle_acheminement',
|
'libelle_acheminement',
|
||||||
'nom_afnor',
|
'nom_afnor',
|
||||||
'source_position',
|
'source_position',
|
||||||
'source_nom_voie',
|
'source_nom_voie',
|
||||||
'certification_commune',
|
'certification_commune',
|
||||||
'cad_parcelles',
|
'cad_parcelles',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($stmt as $record) {
|
foreach ($stmt as $record) {
|
||||||
$this->baseImporter->importAddress(
|
$this->baseImporter->importAddress(
|
||||||
|
@@ -43,17 +43,17 @@ class AddressReferenceFromBano
|
|||||||
|
|
||||||
$csv = Reader::createFromStream($file);
|
$csv = Reader::createFromStream($file);
|
||||||
$csv->setDelimiter(',');
|
$csv->setDelimiter(',');
|
||||||
$stmt = Statement::create()
|
$stmt = new Statement();
|
||||||
->process($csv, [
|
$stmt = $stmt->process($csv, [
|
||||||
'refId',
|
'refId',
|
||||||
'streetNumber',
|
'streetNumber',
|
||||||
'street',
|
'street',
|
||||||
'postcode',
|
'postcode',
|
||||||
'city',
|
'city',
|
||||||
'_o',
|
'_o',
|
||||||
'lat',
|
'lat',
|
||||||
'lon',
|
'lon',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($stmt as $record) {
|
foreach ($stmt as $record) {
|
||||||
$this->baseImporter->importAddress(
|
$this->baseImporter->importAddress(
|
||||||
|
@@ -54,7 +54,8 @@ class AddressReferenceLU
|
|||||||
|
|
||||||
private function process_address(Reader $csv, ?string $sendAddressReportToEmail = null): void
|
private function process_address(Reader $csv, ?string $sendAddressReportToEmail = null): void
|
||||||
{
|
{
|
||||||
$stmt = Statement::create()->process($csv);
|
$stmt = new Statement();
|
||||||
|
$stmt = $stmt->process($csv);
|
||||||
foreach ($stmt as $record) {
|
foreach ($stmt as $record) {
|
||||||
$this->addressBaseImporter->importAddress(
|
$this->addressBaseImporter->importAddress(
|
||||||
$record['id_geoportail'],
|
$record['id_geoportail'],
|
||||||
@@ -74,7 +75,8 @@ class AddressReferenceLU
|
|||||||
|
|
||||||
private function process_postal_code(Reader $csv): void
|
private function process_postal_code(Reader $csv): void
|
||||||
{
|
{
|
||||||
$stmt = Statement::create()->process($csv);
|
$stmt = new Statement();
|
||||||
|
$stmt = $stmt->process($csv);
|
||||||
$arr_postal_codes = [];
|
$arr_postal_codes = [];
|
||||||
foreach ($stmt as $record) {
|
foreach ($stmt as $record) {
|
||||||
if (false === \array_key_exists($record['code_postal'], $arr_postal_codes)) {
|
if (false === \array_key_exists($record['code_postal'], $arr_postal_codes)) {
|
||||||
|
@@ -61,6 +61,7 @@ final class GenderDocGenNormalizerTest extends TestCase
|
|||||||
'id' => 1,
|
'id' => 1,
|
||||||
'label' => 'homme',
|
'label' => 'homme',
|
||||||
'genderTranslation' => GenderEnum::MALE,
|
'genderTranslation' => GenderEnum::MALE,
|
||||||
|
'type' => 'chill_main_gender',
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->assertEquals($expected, $this->normalizer->normalize($gender));
|
$this->assertEquals($expected, $this->normalizer->normalize($gender));
|
||||||
|
@@ -0,0 +1,156 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Tests\Workflow\EventSubscriber;
|
||||||
|
|
||||||
|
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||||
|
use Chill\DocStoreBundle\Entity\StoredObjectPointInTime;
|
||||||
|
use Chill\DocStoreBundle\Entity\StoredObjectPointInTimeReasonEnum;
|
||||||
|
use Chill\DocStoreBundle\Service\StoredObjectRestoreInterface;
|
||||||
|
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||||
|
use Chill\MainBundle\Workflow\EntityWorkflowManager;
|
||||||
|
use Chill\MainBundle\Workflow\EntityWorkflowMarkingStore;
|
||||||
|
use Chill\MainBundle\Workflow\EventSubscriber\OnCancelRestoreDocumentToEditableEventSubscriber;
|
||||||
|
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
|
use Symfony\Component\Workflow\DefinitionBuilder;
|
||||||
|
use Symfony\Component\Workflow\Metadata\InMemoryMetadataStore;
|
||||||
|
use Symfony\Component\Workflow\Registry;
|
||||||
|
use Symfony\Component\Workflow\SupportStrategy\WorkflowSupportStrategyInterface;
|
||||||
|
use Symfony\Component\Workflow\Transition;
|
||||||
|
use Symfony\Component\Workflow\Workflow;
|
||||||
|
use Symfony\Component\Workflow\WorkflowInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class OnCancelRestoreDocumentToEditableEventSubscriberTest extends TestCase
|
||||||
|
{
|
||||||
|
private function buildRegistry(StoredObjectRestoreInterface $storedObjectRestore, ?StoredObject $storedObject): Registry
|
||||||
|
{
|
||||||
|
$builder = new DefinitionBuilder(
|
||||||
|
['initial', 'intermediate', 'final', 'cancel'],
|
||||||
|
[
|
||||||
|
new Transition('to_intermediate', ['initial'], ['intermediate']),
|
||||||
|
new Transition('intermediate_to_final', ['intermediate'], ['final']),
|
||||||
|
new Transition('to_final', ['initial'], ['final']),
|
||||||
|
new Transition('to_cancel', ['initial'], ['cancel']),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$builder->setMetadataStore(
|
||||||
|
new InMemoryMetadataStore(
|
||||||
|
placesMetadata: [
|
||||||
|
'final' => ['isFinal' => true],
|
||||||
|
'cancel' => ['isFinal' => true, 'isFinalPositive' => false],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$registry = new Registry();
|
||||||
|
$workflow = new Workflow($builder->build(), new EntityWorkflowMarkingStore(), $eventDispatcher = new EventDispatcher(), 'dummy');
|
||||||
|
|
||||||
|
$manager = $this->createMock(EntityWorkflowManager::class);
|
||||||
|
$manager->method('getAssociatedStoredObject')->willReturn($storedObject);
|
||||||
|
|
||||||
|
$eventSubscriber = new OnCancelRestoreDocumentToEditableEventSubscriber(
|
||||||
|
$registry,
|
||||||
|
$manager,
|
||||||
|
$storedObjectRestore
|
||||||
|
);
|
||||||
|
$eventDispatcher->addSubscriber($eventSubscriber);
|
||||||
|
|
||||||
|
$registry->addWorkflow($workflow, new class () implements WorkflowSupportStrategyInterface {
|
||||||
|
public function supports(WorkflowInterface $workflow, object $subject): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return $registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOnCancelRestoreDocumentToEditableExpectsRestoring(): void
|
||||||
|
{
|
||||||
|
$storedObject = new StoredObject();
|
||||||
|
$version = $storedObject->registerVersion();
|
||||||
|
new StoredObjectPointInTime($version, StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION);
|
||||||
|
$storedObject->registerVersion();
|
||||||
|
|
||||||
|
$restore = $this->createMock(StoredObjectRestoreInterface::class);
|
||||||
|
$restore->expects($this->once())->method('restore')->with($version);
|
||||||
|
|
||||||
|
$registry = $this->buildRegistry($restore, $storedObject);
|
||||||
|
$entityWorkflow = (new EntityWorkflow())->setWorkflowName('dummy');
|
||||||
|
|
||||||
|
$workflow = $registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
|
||||||
|
$context = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||||
|
|
||||||
|
$workflow->apply($entityWorkflow, 'to_cancel', [
|
||||||
|
'context' => $context,
|
||||||
|
'transition' => 'to_cancel',
|
||||||
|
'transitionAt' => new \DateTimeImmutable('now'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOnCancelRestoreDocumentDoNotExpectRestoring(): void
|
||||||
|
{
|
||||||
|
$storedObject = new StoredObject();
|
||||||
|
$version = $storedObject->registerVersion();
|
||||||
|
new StoredObjectPointInTime($version, StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION);
|
||||||
|
$storedObject->registerVersion();
|
||||||
|
|
||||||
|
$restore = $this->createMock(StoredObjectRestoreInterface::class);
|
||||||
|
$restore->expects($this->never())->method('restore')->withAnyParameters();
|
||||||
|
|
||||||
|
$registry = $this->buildRegistry($restore, $storedObject);
|
||||||
|
$entityWorkflow = (new EntityWorkflow())->setWorkflowName('dummy');
|
||||||
|
|
||||||
|
$workflow = $registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
|
||||||
|
$context = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||||
|
|
||||||
|
$workflow->apply($entityWorkflow, 'to_intermediate', [
|
||||||
|
'context' => $context,
|
||||||
|
'transition' => 'to_intermediate',
|
||||||
|
'transitionAt' => new \DateTimeImmutable('now'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$workflow->apply($entityWorkflow, 'intermediate_to_final', [
|
||||||
|
'context' => $context,
|
||||||
|
'transition' => 'intermediate_to_final',
|
||||||
|
'transitionAt' => new \DateTimeImmutable('now'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOnCancelRestoreDocumentToEditableToCancelStoredObjectWithoutKepts(): void
|
||||||
|
{
|
||||||
|
$storedObject = new StoredObject();
|
||||||
|
$storedObject->registerVersion();
|
||||||
|
|
||||||
|
$restore = $this->createMock(StoredObjectRestoreInterface::class);
|
||||||
|
$restore->expects($this->never())->method('restore')->withAnyParameters();
|
||||||
|
|
||||||
|
$registry = $this->buildRegistry($restore, $storedObject);
|
||||||
|
$entityWorkflow = (new EntityWorkflow())->setWorkflowName('dummy');
|
||||||
|
|
||||||
|
$workflow = $registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
|
||||||
|
$context = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||||
|
|
||||||
|
$workflow->apply($entityWorkflow, 'to_cancel', [
|
||||||
|
'context' => $context,
|
||||||
|
'transition' => 'to_cancel',
|
||||||
|
'transitionAt' => new \DateTimeImmutable('now'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Workflow\EventSubscriber;
|
||||||
|
|
||||||
|
use Chill\DocStoreBundle\Service\StoredObjectRestoreInterface;
|
||||||
|
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||||
|
use Chill\MainBundle\Workflow\EntityWorkflowManager;
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\Workflow\Event\TransitionEvent;
|
||||||
|
use Symfony\Component\Workflow\Registry;
|
||||||
|
|
||||||
|
final readonly class OnCancelRestoreDocumentToEditableEventSubscriber implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private Registry $registry,
|
||||||
|
private EntityWorkflowManager $manager,
|
||||||
|
private StoredObjectRestoreInterface $storedObjectRestore,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public static function getSubscribedEvents(): array
|
||||||
|
{
|
||||||
|
return ['workflow.transition' => ['onCancelRestoreDocumentToEditable', 0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onCancelRestoreDocumentToEditable(TransitionEvent $event): void
|
||||||
|
{
|
||||||
|
$entityWorkflow = $event->getSubject();
|
||||||
|
|
||||||
|
if (!$entityWorkflow instanceof EntityWorkflow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
|
||||||
|
|
||||||
|
foreach ($event->getTransition()->getTos() as $place) {
|
||||||
|
$metadata = $workflow->getMetadataStore()->getPlaceMetadata($place);
|
||||||
|
|
||||||
|
if (($metadata['isFinal'] ?? false) && !($metadata['isFinalPositive'] ?? true)) {
|
||||||
|
$this->restoreDocument($entityWorkflow);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function restoreDocument(EntityWorkflow $entityWorkflow): void
|
||||||
|
{
|
||||||
|
$storedObject = $this->manager->getAssociatedStoredObject($entityWorkflow);
|
||||||
|
|
||||||
|
if (null === $storedObject) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$version = $storedObject->getLastKeptBeforeConversionVersion();
|
||||||
|
|
||||||
|
if (null === $version) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->storedObjectRestore->restore($storedObject->getLastKeptBeforeConversionVersion());
|
||||||
|
}
|
||||||
|
}
|
@@ -943,6 +943,16 @@ paths:
|
|||||||
description: "ok"
|
description: "ok"
|
||||||
401:
|
401:
|
||||||
description: "Unauthorized"
|
description: "Unauthorized"
|
||||||
|
/1.0/main/gender.json:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- gender
|
||||||
|
summary: Return all gender types
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: "ok"
|
||||||
|
401:
|
||||||
|
description: "Unauthorized"
|
||||||
/1.0/main/user-job.json:
|
/1.0/main/user-job.json:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
|
@@ -1,45 +1,3 @@
|
|||||||
const { styles } = require("@ckeditor/ckeditor5-dev-utils");
|
|
||||||
const {
|
|
||||||
CKEditorTranslationsPlugin,
|
|
||||||
} = require("@ckeditor/ckeditor5-dev-translations");
|
|
||||||
|
|
||||||
buildCKEditor = function (encore) {
|
|
||||||
encore
|
|
||||||
.addPlugin(
|
|
||||||
new CKEditorTranslationsPlugin({
|
|
||||||
language: "fr",
|
|
||||||
addMainLanguageTranslationsToAllAssets: true,
|
|
||||||
verbose: !encore.isProduction(),
|
|
||||||
strict: true,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Use raw-loader for CKEditor 5 SVG files.
|
|
||||||
.addRule({
|
|
||||||
test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
|
|
||||||
loader: "raw-loader",
|
|
||||||
})
|
|
||||||
|
|
||||||
// Configure other image loaders to exclude CKEditor 5 SVG files.
|
|
||||||
.configureLoaderRule("images", (loader) => {
|
|
||||||
loader.exclude =
|
|
||||||
/ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/;
|
|
||||||
})
|
|
||||||
|
|
||||||
// Configure PostCSS loader.
|
|
||||||
.addLoader({
|
|
||||||
test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css$/,
|
|
||||||
loader: "postcss-loader",
|
|
||||||
options: {
|
|
||||||
postcssOptions: styles.getPostCssConfig({
|
|
||||||
themeImporter: {
|
|
||||||
themePath: require.resolve("@ckeditor/ckeditor5-theme-lark"),
|
|
||||||
},
|
|
||||||
minify: true,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Compile and loads all assets from the Chill Main Bundle
|
// Compile and loads all assets from the Chill Main Bundle
|
||||||
module.exports = function (encore, entries) {
|
module.exports = function (encore, entries) {
|
||||||
@@ -79,8 +37,6 @@ module.exports = function (encore, entries) {
|
|||||||
__dirname + "/Resources/public/page/export/download-export.js",
|
__dirname + "/Resources/public/page/export/download-export.js",
|
||||||
);
|
);
|
||||||
|
|
||||||
buildCKEditor(encore);
|
|
||||||
|
|
||||||
// Modules entrypoints
|
// Modules entrypoints
|
||||||
encore.addEntry(
|
encore.addEntry(
|
||||||
"mod_collection",
|
"mod_collection",
|
||||||
|
@@ -44,6 +44,9 @@ address_fields: Données liées à l'adresse
|
|||||||
Datas: Données
|
Datas: Données
|
||||||
No title: Aucun titre
|
No title: Aucun titre
|
||||||
icon: icône
|
icon: icône
|
||||||
|
See: Voir
|
||||||
|
Name: Nom
|
||||||
|
Label: Nom
|
||||||
|
|
||||||
user:
|
user:
|
||||||
profile:
|
profile:
|
||||||
@@ -124,6 +127,49 @@ address:
|
|||||||
address_homeless: L'adresse est-elle celle d'un domicile fixe ?
|
address_homeless: L'adresse est-elle celle d'un domicile fixe ?
|
||||||
real address: Adresse d'un domicile
|
real address: Adresse d'un domicile
|
||||||
consider homeless: Cette adresse est incomplète
|
consider homeless: Cette adresse est incomplète
|
||||||
|
add_an_address_title: Créer une adresse
|
||||||
|
edit_an_address_title: Modifier une adresse
|
||||||
|
create_a_new_address: Créer une nouvelle adresse
|
||||||
|
edit_address: Modifier l'adresse
|
||||||
|
select_an_address_title: Sélectionner une adresse
|
||||||
|
fill_an_address: Compléter l'adresse
|
||||||
|
select_country: Choisir le pays
|
||||||
|
country: Pays
|
||||||
|
select_city: Choisir une localité
|
||||||
|
city: Localité
|
||||||
|
other_city: Autre localité
|
||||||
|
select_address: Choisir une adresse
|
||||||
|
address: Adresse
|
||||||
|
other_address: Autre adresse
|
||||||
|
create_address: Adresse inconnue. Cliquez ici pour créer une nouvelle adresse
|
||||||
|
isNoAddress: Pas d'adresse complète
|
||||||
|
isConfidential: Adresse confidentielle
|
||||||
|
street: Nom de rue
|
||||||
|
streetNumber: Numéro
|
||||||
|
floor: Étage
|
||||||
|
corridor: Couloir
|
||||||
|
steps: Escalier
|
||||||
|
flat: Appartement
|
||||||
|
buildingName: Résidence
|
||||||
|
extra: Complément d'adresse
|
||||||
|
distribution: Cedex
|
||||||
|
create_postal_code: Localité inconnue. Cliquez ici pour créer une nouvelle localité
|
||||||
|
postalCode_name: Nom
|
||||||
|
postalCode_code: Code postal
|
||||||
|
date: Date de la nouvelle adresse
|
||||||
|
valid_from: L'adresse est valable à partir du
|
||||||
|
valid_to: L'adresse est valable jusqu'au
|
||||||
|
back_to_the_list: Retour à la liste
|
||||||
|
loading: chargement en cours...
|
||||||
|
address_suggestions: Suggestion d'adresses
|
||||||
|
address_new_success: La nouvelle adresse est enregistrée.
|
||||||
|
address_edit_success: L'adresse a été mise à jour.
|
||||||
|
wait_redirection: La page est redirigée.
|
||||||
|
not_yet_address: Il n'y a pas encore d'adresse. Cliquez sur '+ Créer une adresse'
|
||||||
|
use_this_address: Utiliser cette adresse
|
||||||
|
household:
|
||||||
|
move_date: Date du déménagement
|
||||||
|
|
||||||
address more:
|
address more:
|
||||||
floor: ét
|
floor: ét
|
||||||
corridor: coul
|
corridor: coul
|
||||||
@@ -508,6 +554,8 @@ Follow workflow: Suivre la décision
|
|||||||
Workflow history: Historique de la décision
|
Workflow history: Historique de la décision
|
||||||
|
|
||||||
workflow:
|
workflow:
|
||||||
|
list: Liste des workflows associés
|
||||||
|
associated: workflow associé
|
||||||
deleted: Workflow supprimé
|
deleted: Workflow supprimé
|
||||||
Created by: Créé par
|
Created by: Créé par
|
||||||
My decision: Ma décision
|
My decision: Ma décision
|
||||||
@@ -553,6 +601,7 @@ workflow:
|
|||||||
Previous workflow transitionned help: Workflows où vous avez exécuté une action.
|
Previous workflow transitionned help: Workflows où vous avez exécuté une action.
|
||||||
For: Pour
|
For: Pour
|
||||||
Cc: Cc
|
Cc: Cc
|
||||||
|
At: Le
|
||||||
You must select a next step, pick another decision if no next steps are available: Il faut une prochaine étape. Choissisez une autre décision si nécessaire.
|
You must select a next step, pick another decision if no next steps are available: Il faut une prochaine étape. Choissisez une autre décision si nécessaire.
|
||||||
An access key was also sent to those addresses: Un lien d'accès a été envoyé à ces adresses
|
An access key was also sent to those addresses: Un lien d'accès a été envoyé à ces adresses
|
||||||
Those users are also granted to apply a transition by using an access key: Ces utilisateurs ont obtenu l'accès grâce au lien reçu par email
|
Those users are also granted to apply a transition by using an access key: Ces utilisateurs ont obtenu l'accès grâce au lien reçu par email
|
||||||
@@ -575,6 +624,12 @@ workflow:
|
|||||||
public_views_by_ip: Visualisation par adresse IP
|
public_views_by_ip: Visualisation par adresse IP
|
||||||
May not associate a document: Le workflow ne concerne pas un document
|
May not associate a document: Le workflow ne concerne pas un document
|
||||||
|
|
||||||
|
subscribe_final: Recevoir une notification à l'étape finale
|
||||||
|
unsubscribe_final: Ne plus recevoir de notification à l'étape finale
|
||||||
|
subscribe_all_steps: Recevoir une notification à chaque étape du suivi
|
||||||
|
unsubscribe_all_steps: Ne plus recevoir de notification à chaque étape du suivi
|
||||||
|
|
||||||
|
|
||||||
public_link:
|
public_link:
|
||||||
expired_link_title: Lien expiré
|
expired_link_title: Lien expiré
|
||||||
expired_link_explanation: Le lien a expiré, vous ne pouvez plus visualiser ce document.
|
expired_link_explanation: Le lien a expiré, vous ne pouvez plus visualiser ce document.
|
||||||
@@ -656,6 +711,10 @@ notification:
|
|||||||
Remove an email: Supprimer l'adresse email
|
Remove an email: Supprimer l'adresse email
|
||||||
Email with access link: Adresse email ayant reçu un lien d'accès
|
Email with access link: Adresse email ayant reçu un lien d'accès
|
||||||
|
|
||||||
|
mark_as_read: Marquer comme lu
|
||||||
|
mark_as_unread: Marquer comme non-lu
|
||||||
|
|
||||||
|
|
||||||
export:
|
export:
|
||||||
address_helper:
|
address_helper:
|
||||||
id: Identifiant de l'adresse
|
id: Identifiant de l'adresse
|
||||||
@@ -676,6 +735,25 @@ export:
|
|||||||
steps: Escaliers
|
steps: Escaliers
|
||||||
_lat: Latitude
|
_lat: Latitude
|
||||||
_lon: Longitude
|
_lon: Longitude
|
||||||
|
social_action_list:
|
||||||
|
id: Identifiant de l'action
|
||||||
|
social_issue_id: Identifiant de la problématique sociale
|
||||||
|
social_issue: Problématique sociale
|
||||||
|
social_issue_ordering: Ordre de la problématique sociale
|
||||||
|
action_label: Action d'accompagnement
|
||||||
|
action_ordering: Ordre
|
||||||
|
goal_label: Objectif
|
||||||
|
goal_id: Identifiant de l'objectif
|
||||||
|
goal_result_label: Résultat
|
||||||
|
goal_result_id: Identifiant du résultat
|
||||||
|
result_without_goal_label: Résultat (sans objectif)
|
||||||
|
result_without_goal_id: Identifiant du résultat (sans objectif)
|
||||||
|
evaluation_title: Évaluation
|
||||||
|
evaluation_id: Identifiant de l'évaluation
|
||||||
|
evaluation_url: Adresse URL externe (évaluation)
|
||||||
|
evaluation_delay_month: Délai de notification (mois)
|
||||||
|
evaluation_delay_week: Délai de notification (semaine)
|
||||||
|
evaluation_delay_day: Délai de notification (jours)
|
||||||
|
|
||||||
rolling_date:
|
rolling_date:
|
||||||
year_previous_start: Début de l'année précédente
|
year_previous_start: Début de l'année précédente
|
||||||
@@ -795,4 +873,43 @@ gender:
|
|||||||
Select gender translation: Traduction grammaticale
|
Select gender translation: Traduction grammaticale
|
||||||
Select gender icon: Icône à utiliser
|
Select gender icon: Icône à utiliser
|
||||||
|
|
||||||
|
wopi:
|
||||||
|
online_edit_document: Éditer en ligne
|
||||||
|
save_and_quit: Enregistrer et quitter
|
||||||
|
loading: Chargement de l'éditeur en ligne
|
||||||
|
invalid_title: Format incompatible
|
||||||
|
invalid_message: Désolé, ce format de document n'est pas éditable en ligne.
|
||||||
|
|
||||||
|
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:
|
||||||
|
default: Création d'un nouvel usager ou d'un tiers professionnel
|
||||||
|
person: Création d'un nouvel usager
|
||||||
|
thirdparty: Création d'un nouveau tiers professionnel
|
||||||
|
person: un nouvel usager
|
||||||
|
thirdparty: un nouveau tiers professionnel
|
||||||
|
addContact:
|
||||||
|
title: Créer un contact pour {q}
|
||||||
|
resource_comment_title: Un commentaire est associé à cet interlocuteur
|
||||||
|
|
||||||
|
modal:
|
||||||
|
action:
|
||||||
|
close: Fermer
|
||||||
|
|
||||||
|
multiselect:
|
||||||
|
placeholder: Choisir
|
||||||
|
tag_placeholder: Créer un nouvel élément
|
||||||
|
select_label: Entrée ou cliquez pour sélectionner
|
||||||
|
deselect_label: Entrée ou cliquez pour désélectionner
|
||||||
|
select_group_label: Appuyer sur "Entrée" pour sélectionner ce groupe
|
||||||
|
deselect_group_label: Appuyer sur "Entrée" pour désélectionner ce groupe
|
||||||
|
selected_label: Sélectionné'
|
||||||
|
@@ -25,7 +25,7 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource;
|
|||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||||
use Chill\PersonBundle\Privacy\AccompanyingPeriodPrivacyEvent;
|
use Chill\PersonBundle\Privacy\AccompanyingPeriodPrivacyEvent;
|
||||||
use Chill\PersonBundle\Repository\AccompanyingPeriodACLAwareRepository;
|
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
|
||||||
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
|
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
|
||||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||||
@@ -46,7 +46,7 @@ use Symfony\Component\Workflow\Registry;
|
|||||||
|
|
||||||
final class AccompanyingCourseApiController extends ApiController
|
final class AccompanyingCourseApiController extends ApiController
|
||||||
{
|
{
|
||||||
public function __construct(private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository, private readonly AccompanyingPeriodACLAwareRepository $accompanyingPeriodACLAwareRepository, private readonly EventDispatcherInterface $eventDispatcher, private readonly ReferralsSuggestionInterface $referralAvailable, private readonly Registry $registry, private readonly ValidatorInterface $validator, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {}
|
public function __construct(private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository, private readonly EventDispatcherInterface $eventDispatcher, private readonly ReferralsSuggestionInterface $referralAvailable, private readonly Registry $registry, private readonly ValidatorInterface $validator, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, private readonly AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository) {}
|
||||||
|
|
||||||
public function commentApi($id, Request $request, string $_format): Response
|
public function commentApi($id, Request $request, string $_format): Response
|
||||||
{
|
{
|
||||||
@@ -305,6 +305,20 @@ final class AccompanyingCourseApiController extends ApiController
|
|||||||
return $this->json($accompanyingCourse->getIntensity(), Response::HTTP_OK, [], ['groups' => ['read']]);
|
return $this->json($accompanyingCourse->getIntensity(), Response::HTTP_OK, [], ['groups' => ['read']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ParamConverter("accompanyingPeriod", options={"id": "id"})
|
||||||
|
*/
|
||||||
|
#[Route(path: '/api/1.0/person/accompanying-course/{id}/works.json', name: 'chill_api_person_accompanying_period_works')]
|
||||||
|
public function worksByAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): JsonResponse
|
||||||
|
{
|
||||||
|
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingPeriod);
|
||||||
|
|
||||||
|
$works = $this->accompanyingPeriodWorkRepository->findBy(['accompanyingPeriod' => $accompanyingPeriod]);
|
||||||
|
dump($works);
|
||||||
|
|
||||||
|
return $this->json($works, Response::HTTP_OK, [], ['groups' => ['read']]);
|
||||||
|
}
|
||||||
|
|
||||||
public function workApi($id, Request $request, string $_format): Response
|
public function workApi($id, Request $request, string $_format): Response
|
||||||
{
|
{
|
||||||
return $this->addRemoveSomething(
|
return $this->addRemoveSomething(
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||||
|
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
|
class AdministrativeStatusController extends CRUDController
|
||||||
|
{
|
||||||
|
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||||
|
{
|
||||||
|
$query->addOrderBy('e.order', 'ASC');
|
||||||
|
|
||||||
|
return parent::orderQuery($action, $query, $request, $paginator);
|
||||||
|
}
|
||||||
|
}
|
@@ -33,9 +33,12 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
|||||||
use Symfony\Component\Security\Core\Security;
|
use Symfony\Component\Security\Core\Security;
|
||||||
use Symfony\Component\Serializer\Exception;
|
use Symfony\Component\Serializer\Exception;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
|
|
||||||
class HouseholdMemberController extends ApiController
|
class HouseholdMemberController extends ApiController
|
||||||
{
|
{
|
||||||
|
private array $household_fields_visibility;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly UrlGeneratorInterface $generator,
|
private readonly UrlGeneratorInterface $generator,
|
||||||
private readonly TranslatorInterface $translator,
|
private readonly TranslatorInterface $translator,
|
||||||
@@ -45,7 +48,10 @@ class HouseholdMemberController extends ApiController
|
|||||||
private readonly Security $security,
|
private readonly Security $security,
|
||||||
private readonly PositionRepository $positionRepository,
|
private readonly PositionRepository $positionRepository,
|
||||||
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
|
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
|
||||||
) {}
|
protected ParameterBagInterface $parameterBag,
|
||||||
|
) {
|
||||||
|
$this->household_fields_visibility = $parameterBag->get('chill_person.household_fields');
|
||||||
|
}
|
||||||
|
|
||||||
#[Route(path: '/{_locale}/person/household/member/{id}/edit', name: 'chill_person_household_member_edit')]
|
#[Route(path: '/{_locale}/person/household/member/{id}/edit', name: 'chill_person_household_member_edit')]
|
||||||
public function editMembership(Request $request, HouseholdMember $member): Response
|
public function editMembership(Request $request, HouseholdMember $member): Response
|
||||||
@@ -144,6 +150,7 @@ class HouseholdMemberController extends ApiController
|
|||||||
'allowHouseholdCreate' => $allowHouseholdCreate ?? true,
|
'allowHouseholdCreate' => $allowHouseholdCreate ?? true,
|
||||||
'allowHouseholdSearch' => $allowHouseholdSearch ?? true,
|
'allowHouseholdSearch' => $allowHouseholdSearch ?? true,
|
||||||
'allowLeaveWithoutHousehold' => $allowLeaveWithoutHousehold ?? $request->query->has('allow_leave_without_household'),
|
'allowLeaveWithoutHousehold' => $allowLeaveWithoutHousehold ?? $request->query->has('allow_leave_without_household'),
|
||||||
|
'displayDependents' => ('visible' == $this->household_fields_visibility['number_of_dependents']) ? true : false,
|
||||||
];
|
];
|
||||||
|
|
||||||
// context
|
// context
|
||||||
|
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
|
||||||
|
use Chill\PersonBundle\Service\SocialWork\SocialActionCSVExportService;
|
||||||
|
use League\Csv\CannotInsertRecord;
|
||||||
|
use League\Csv\Exception;
|
||||||
|
use League\Csv\UnavailableStream;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
|
class SocialActionCSVExportController extends AbstractController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly SocialActionRepository $socialActionRepository,
|
||||||
|
private readonly Security $security,
|
||||||
|
private readonly SocialActionCSVExportService $socialActionCSVExportService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws UnavailableStream
|
||||||
|
* @throws CannotInsertRecord
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
#[Route(path: '/{_locale}/admin/social-work/social-action/export/list.{_format}', name: 'chill_person_social_action_export_list', requirements: ['_format' => 'csv'])]
|
||||||
|
public function socialActionList(Request $request, string $_format = 'csv'): StreamedResponse
|
||||||
|
{
|
||||||
|
if (!$this->security->isGranted('ROLE_ADMIN')) {
|
||||||
|
throw new AccessDeniedHttpException('Only ROLE_ADMIN can export this list');
|
||||||
|
}
|
||||||
|
|
||||||
|
$actions = $this->socialActionRepository->findAllOrdered();
|
||||||
|
|
||||||
|
$csv = $this->socialActionCSVExportService->generateCsv($actions);
|
||||||
|
|
||||||
|
return new StreamedResponse(
|
||||||
|
function () use ($csv) {
|
||||||
|
foreach ($csv->chunk(1024) as $chunk) {
|
||||||
|
echo $chunk;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Response::HTTP_OK,
|
||||||
|
[
|
||||||
|
'Content-Encoding' => 'none',
|
||||||
|
'Content-Type' => 'text/csv; charset=UTF-8',
|
||||||
|
'Content-Disposition' => 'attachment; filename=results.csv',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
|
||||||
|
use Chill\PersonBundle\Service\SocialWork\SocialIssueCSVExportService;
|
||||||
|
use League\Csv\CannotInsertRecord;
|
||||||
|
use League\Csv\Exception;
|
||||||
|
use League\Csv\UnavailableStream;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
|
class SocialIssueCSVExportController extends AbstractController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly SocialIssueRepository $socialIssueRepository,
|
||||||
|
private readonly Security $security,
|
||||||
|
private readonly SocialIssueCSVExportService $socialIssueCSVExportService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws UnavailableStream
|
||||||
|
* @throws CannotInsertRecord
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
#[Route(path: '/{_locale}/admin/social-work/social-issue/export/list.{_format}', name: 'chill_person_social_issue_export_list', requirements: ['_format' => 'csv'])]
|
||||||
|
public function socialIssueList(Request $request, string $_format = 'csv'): StreamedResponse
|
||||||
|
{
|
||||||
|
if (!$this->security->isGranted('ROLE_ADMIN')) {
|
||||||
|
throw new AccessDeniedHttpException('Only ROLE_ADMIN can export this list');
|
||||||
|
}
|
||||||
|
|
||||||
|
$socialIssues = $this->socialIssueRepository->findAllOrdered();
|
||||||
|
|
||||||
|
$csv = $this->socialIssueCSVExportService->generateCsv($socialIssues);
|
||||||
|
|
||||||
|
return new StreamedResponse(
|
||||||
|
function () use ($csv) {
|
||||||
|
foreach ($csv->chunk(1024) as $chunk) {
|
||||||
|
echo $chunk;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Response::HTTP_OK,
|
||||||
|
[
|
||||||
|
'Content-Encoding' => 'none',
|
||||||
|
'Content-Type' => 'text/csv; charset=UTF-8',
|
||||||
|
'Content-Disposition' => 'attachment; users.csv',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,149 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Chill\PersonBundle\Controller;
|
|
||||||
|
|
||||||
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
|
|
||||||
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
|
|
||||||
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
|
|
||||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
|
|
||||||
use League\Csv\CannotInsertRecord;
|
|
||||||
use League\Csv\Exception;
|
|
||||||
use League\Csv\UnavailableStream;
|
|
||||||
use League\Csv\Writer;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
||||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
|
||||||
use Symfony\Component\Security\Core\Security;
|
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
|
||||||
|
|
||||||
class SocialWorkExportController extends AbstractController
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private readonly SocialIssueRepository $socialIssueRepository,
|
|
||||||
private readonly SocialActionRepository $socialActionRepository,
|
|
||||||
private readonly Security $security,
|
|
||||||
private readonly TranslatorInterface $translator,
|
|
||||||
private readonly SocialIssueRender $socialIssueRender,
|
|
||||||
private readonly SocialActionRender $socialActionRender,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws UnavailableStream
|
|
||||||
* @throws CannotInsertRecord
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
#[Route(path: '/{_locale}/admin/social-work/social-issue/export/list.{_format}', name: 'chill_person_social_issue_export_list', requirements: ['_format' => 'csv'])]
|
|
||||||
public function socialIssueList(Request $request, string $_format = 'csv'): StreamedResponse
|
|
||||||
{
|
|
||||||
if (!$this->security->isGranted('ROLE_ADMIN')) {
|
|
||||||
throw new AccessDeniedHttpException('Only ROLE_ADMIN can export this list');
|
|
||||||
}
|
|
||||||
|
|
||||||
$socialIssues = $this->socialIssueRepository->findAll();
|
|
||||||
|
|
||||||
$socialIssues = array_map(fn ($issue) => [
|
|
||||||
'id' => $issue->getId(),
|
|
||||||
'title' => $this->socialIssueRender->renderString($issue, []),
|
|
||||||
'ordering' => $issue->getOrdering(),
|
|
||||||
'desactivationDate' => $issue->getDesactivationDate(),
|
|
||||||
], $socialIssues);
|
|
||||||
|
|
||||||
$csv = Writer::createFromPath('php://temp', 'r+');
|
|
||||||
$csv->insertOne(
|
|
||||||
array_map(
|
|
||||||
fn (string $e) => $this->translator->trans($e),
|
|
||||||
[
|
|
||||||
'Id',
|
|
||||||
'Title',
|
|
||||||
'Ordering',
|
|
||||||
'goal.desactivationDate',
|
|
||||||
]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$csv->addFormatter(fn (array $row) => null !== ($row['desactivationDate'] ?? null) ? array_merge($row, ['desactivationDate' => $row['desactivationDate']->format('Y-m-d')]) : $row);
|
|
||||||
$csv->insertAll($socialIssues);
|
|
||||||
|
|
||||||
return new StreamedResponse(
|
|
||||||
function () use ($csv) {
|
|
||||||
foreach ($csv->chunk(1024) as $chunk) {
|
|
||||||
echo $chunk;
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Response::HTTP_OK,
|
|
||||||
[
|
|
||||||
'Content-Encoding' => 'none',
|
|
||||||
'Content-Type' => 'text/csv; charset=UTF-8',
|
|
||||||
'Content-Disposition' => 'attachment; users.csv',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws UnavailableStream
|
|
||||||
* @throws CannotInsertRecord
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
#[Route(path: '/{_locale}/admin/social-work/social-action/export/list.{_format}', name: 'chill_person_social_action_export_list', requirements: ['_format' => 'csv'])]
|
|
||||||
public function socialActionList(Request $request, string $_format = 'csv'): StreamedResponse
|
|
||||||
{
|
|
||||||
if (!$this->security->isGranted('ROLE_ADMIN')) {
|
|
||||||
throw new AccessDeniedHttpException('Only ROLE_ADMIN can export this list');
|
|
||||||
}
|
|
||||||
|
|
||||||
$socialActions = $this->socialActionRepository->findAll();
|
|
||||||
|
|
||||||
$socialActions = array_map(fn ($action) => [
|
|
||||||
'id' => $action->getId(),
|
|
||||||
'title' => $this->socialActionRender->renderString($action, []),
|
|
||||||
'desactivationDate' => $action->getDesactivationDate(),
|
|
||||||
'socialIssue' => $this->socialIssueRender->renderString($action->getIssue(), []),
|
|
||||||
'ordering' => $action->getOrdering(),
|
|
||||||
], $socialActions);
|
|
||||||
|
|
||||||
$csv = Writer::createFromPath('php://temp', 'r+');
|
|
||||||
$csv->insertOne(
|
|
||||||
array_map(
|
|
||||||
fn (string $e) => $this->translator->trans($e),
|
|
||||||
[
|
|
||||||
'Id',
|
|
||||||
'Title',
|
|
||||||
'goal.desactivationDate',
|
|
||||||
'Social issue',
|
|
||||||
'Ordering',
|
|
||||||
]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$csv->addFormatter(fn (array $row) => null !== ($row['desactivationDate'] ?? null) ? array_merge($row, ['desactivationDate' => $row['desactivationDate']->format('Y-m-d')]) : $row);
|
|
||||||
$csv->insertAll($socialActions);
|
|
||||||
|
|
||||||
return new StreamedResponse(
|
|
||||||
function () use ($csv) {
|
|
||||||
foreach ($csv->chunk(1024) as $chunk) {
|
|
||||||
echo $chunk;
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Response::HTTP_OK,
|
|
||||||
[
|
|
||||||
'Content-Encoding' => 'none',
|
|
||||||
'Content-Type' => 'text/csv; charset=UTF-8',
|
|
||||||
'Content-Disposition' => 'attachment; users.csv',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\DataFixtures\ORM;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\AdministrativeStatus;
|
||||||
|
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||||
|
use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface;
|
||||||
|
use Doctrine\Persistence\ObjectManager;
|
||||||
|
|
||||||
|
class LoadAdministrativeStatus extends Fixture implements FixtureGroupInterface
|
||||||
|
{
|
||||||
|
public static function getGroups(): array
|
||||||
|
{
|
||||||
|
return ['administrative_status'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load(ObjectManager $manager): void
|
||||||
|
{
|
||||||
|
$status = [
|
||||||
|
['name' => ['fr' => 'situation administrative régulière']],
|
||||||
|
['name' => ['fr' => 'sans papier']],
|
||||||
|
['name' => ['fr' => 'séjour provisoire']],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($status as $val) {
|
||||||
|
$administrativeStatus = (new AdministrativeStatus())
|
||||||
|
->setName($val['name'])
|
||||||
|
->setActive(true);
|
||||||
|
$manager->persist($administrativeStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
$manager->flush();
|
||||||
|
}
|
||||||
|
}
|
@@ -15,12 +15,15 @@ use Chill\MainBundle\DependencyInjection\MissingBundleException;
|
|||||||
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
|
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
|
||||||
use Chill\PersonBundle\Controller\AccompanyingPeriodCommentApiController;
|
use Chill\PersonBundle\Controller\AccompanyingPeriodCommentApiController;
|
||||||
use Chill\PersonBundle\Controller\AccompanyingPeriodResourceApiController;
|
use Chill\PersonBundle\Controller\AccompanyingPeriodResourceApiController;
|
||||||
|
use Chill\PersonBundle\Controller\AdministrativeStatusController;
|
||||||
use Chill\PersonBundle\Controller\EmploymentStatusController;
|
use Chill\PersonBundle\Controller\EmploymentStatusController;
|
||||||
use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController;
|
use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController;
|
||||||
use Chill\PersonBundle\Controller\RelationApiController;
|
use Chill\PersonBundle\Controller\RelationApiController;
|
||||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
|
use Chill\PersonBundle\Entity\AdministrativeStatus;
|
||||||
use Chill\PersonBundle\Entity\EmploymentStatus;
|
use Chill\PersonBundle\Entity\EmploymentStatus;
|
||||||
|
use Chill\PersonBundle\Form\AdministrativeStatusType;
|
||||||
use Chill\PersonBundle\Form\EmploymentStatusType;
|
use Chill\PersonBundle\Form\EmploymentStatusType;
|
||||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter;
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter;
|
||||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodResourceVoter;
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodResourceVoter;
|
||||||
@@ -57,6 +60,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
|
|
||||||
$this->handlePersonFieldsParameters($container, $config['person_fields']);
|
$this->handlePersonFieldsParameters($container, $config['person_fields']);
|
||||||
$this->handleAccompanyingPeriodsFieldsParameters($container, $config['accompanying_periods_fields']);
|
$this->handleAccompanyingPeriodsFieldsParameters($container, $config['accompanying_periods_fields']);
|
||||||
|
$this->handleHouseholdFieldsParameters($container, $config['household_fields']);
|
||||||
|
|
||||||
$container->setParameter(
|
$container->setParameter(
|
||||||
'chill_person.allow_multiple_simultaneous_accompanying_periods',
|
'chill_person.allow_multiple_simultaneous_accompanying_periods',
|
||||||
@@ -132,6 +136,9 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
'chill_accompanying_periods' => [
|
'chill_accompanying_periods' => [
|
||||||
'fields' => $config['accompanying_periods_fields'],
|
'fields' => $config['accompanying_periods_fields'],
|
||||||
],
|
],
|
||||||
|
'chill_household' => [
|
||||||
|
'fields' => $config['household_fields'],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'form_themes' => ['@ChillPerson/Export/ListPersonFormFields.html.twig'],
|
'form_themes' => ['@ChillPerson/Export/ListPersonFormFields.html.twig'],
|
||||||
];
|
];
|
||||||
@@ -195,6 +202,28 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'class' => AdministrativeStatus::class,
|
||||||
|
'name' => 'administrative_status',
|
||||||
|
'base_path' => '/admin/administrative',
|
||||||
|
'base_role' => 'ROLE_ADMIN',
|
||||||
|
'form_class' => AdministrativeStatusType::class,
|
||||||
|
'controller' => AdministrativeStatusController::class,
|
||||||
|
'actions' => [
|
||||||
|
'index' => [
|
||||||
|
'role' => 'ROLE_ADMIN',
|
||||||
|
'template' => '@ChillPerson/AdministrativeStatus/index.html.twig',
|
||||||
|
],
|
||||||
|
'new' => [
|
||||||
|
'role' => 'ROLE_ADMIN',
|
||||||
|
'template' => '@ChillPerson/AdministrativeStatus/new.html.twig',
|
||||||
|
],
|
||||||
|
'edit' => [
|
||||||
|
'role' => 'ROLE_ADMIN',
|
||||||
|
'template' => '@ChillPerson/AdministrativeStatus/edit.html.twig',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'class' => EmploymentStatus::class,
|
'class' => EmploymentStatus::class,
|
||||||
'name' => 'employment_status',
|
'name' => 'employment_status',
|
||||||
@@ -1117,6 +1146,23 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function handleHouseholdFieldsParameters(ContainerBuilder $container, $config)
|
||||||
|
{
|
||||||
|
$container->setParameter('chill_person.household_fields', $config);
|
||||||
|
|
||||||
|
foreach ($config as $key => $value) {
|
||||||
|
switch ($key) {
|
||||||
|
case 'enabled':
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$container->setParameter('chill_person.household_fields.'.$key, $value);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function handlePersonFieldsParameters(ContainerBuilder $container, $config)
|
private function handlePersonFieldsParameters(ContainerBuilder $container, $config)
|
||||||
{
|
{
|
||||||
if (\array_key_exists('enabled', $config)) {
|
if (\array_key_exists('enabled', $config)) {
|
||||||
|
@@ -83,9 +83,11 @@ class Configuration implements ConfigurationInterface
|
|||||||
->append($this->addFieldNode('accompanying_period'))
|
->append($this->addFieldNode('accompanying_period'))
|
||||||
->append($this->addFieldNode('memo'))
|
->append($this->addFieldNode('memo'))
|
||||||
->append($this->addFieldNode('number_of_children'))
|
->append($this->addFieldNode('number_of_children'))
|
||||||
|
->append($this->addFieldNode('number_of_dependents', 'hidden'))
|
||||||
->append($this->addFieldNode('acceptEmail'))
|
->append($this->addFieldNode('acceptEmail'))
|
||||||
->append($this->addFieldNode('deathdate'))
|
->append($this->addFieldNode('deathdate'))
|
||||||
->append($this->addFieldNode('employment_status', 'hidden'))
|
->append($this->addFieldNode('employment_status', 'hidden'))
|
||||||
|
->append($this->addFieldNode('administrative_status', 'hidden'))
|
||||||
->arrayNode('alt_names')
|
->arrayNode('alt_names')
|
||||||
->defaultValue([])
|
->defaultValue([])
|
||||||
->arrayPrototype()
|
->arrayPrototype()
|
||||||
@@ -108,6 +110,12 @@ class Configuration implements ConfigurationInterface
|
|||||||
->end()
|
->end()
|
||||||
->end() // children for 'person_fields', parent = array 'person_fields'
|
->end() // children for 'person_fields', parent = array 'person_fields'
|
||||||
->end() // person_fields, parent = children of root
|
->end() // person_fields, parent = children of root
|
||||||
|
->arrayNode('household_fields')
|
||||||
|
->canBeDisabled()
|
||||||
|
->children()
|
||||||
|
->append($this->addFieldNode('number_of_dependents', 'hidden'))
|
||||||
|
->end()
|
||||||
|
->end()
|
||||||
->arrayNode('accompanying_periods_fields')
|
->arrayNode('accompanying_periods_fields')
|
||||||
->canBeDisabled()
|
->canBeDisabled()
|
||||||
->children()
|
->children()
|
||||||
|
81
src/Bundle/ChillPersonBundle/Entity/AdministrativeStatus.php
Normal file
81
src/Bundle/ChillPersonBundle/Entity/AdministrativeStatus.php
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Entity;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Repository\AdministrativeStatusRepository;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
|
|
||||||
|
#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['chill_person_administrative_status' => AdministrativeStatus::class])]
|
||||||
|
#[ORM\Entity(repositoryClass: AdministrativeStatusRepository::class)]
|
||||||
|
#[ORM\Table(name: 'chill_person_administrative_status')]
|
||||||
|
class AdministrativeStatus
|
||||||
|
{
|
||||||
|
#[Serializer\Groups(['read', 'docgen:read'])]
|
||||||
|
#[ORM\Id]
|
||||||
|
#[ORM\GeneratedValue]
|
||||||
|
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)]
|
||||||
|
private ?int $id = null;
|
||||||
|
|
||||||
|
#[Serializer\Groups(['read', 'docgen:read'])]
|
||||||
|
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)]
|
||||||
|
#[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])]
|
||||||
|
private array $name = [];
|
||||||
|
|
||||||
|
#[Serializer\Groups(['read'])]
|
||||||
|
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)]
|
||||||
|
private bool $active = true;
|
||||||
|
|
||||||
|
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, name: 'ordering', nullable: true, options: ['default' => '0.0'])]
|
||||||
|
private float $order = 0;
|
||||||
|
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getActive(): ?bool
|
||||||
|
{
|
||||||
|
return $this->active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(): ?array
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOrder(): ?float
|
||||||
|
{
|
||||||
|
return $this->order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setActive(bool $active): self
|
||||||
|
{
|
||||||
|
$this->active = $active;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName(array $name): self
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOrder(float $order): self
|
||||||
|
{
|
||||||
|
$this->order = $order;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
@@ -11,11 +11,12 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\PersonBundle\Entity;
|
namespace Chill\PersonBundle\Entity;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Repository\EmploymentStatusRepository;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
|
|
||||||
#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['chill_person_employment_status' => EmploymentStatus::class])]
|
#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['chill_person_employment_status' => EmploymentStatus::class])]
|
||||||
#[ORM\Entity]
|
#[ORM\Entity(repositoryClass: EmploymentStatusRepository::class)]
|
||||||
#[ORM\Table(name: 'chill_person_employment_status')]
|
#[ORM\Table(name: 'chill_person_employment_status')]
|
||||||
class EmploymentStatus
|
class EmploymentStatus
|
||||||
{
|
{
|
||||||
|
@@ -58,6 +58,18 @@ class HouseholdComposition implements TrackCreationInterface, TrackUpdateInterfa
|
|||||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true, options: ['default' => null])]
|
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true, options: ['default' => null])]
|
||||||
private ?int $numberOfChildren = null;
|
private ?int $numberOfChildren = null;
|
||||||
|
|
||||||
|
#[Assert\NotNull]
|
||||||
|
#[Assert\GreaterThanOrEqual(0, groups: ['Default', 'household_composition'])]
|
||||||
|
#[Serializer\Groups(['docgen:read'])]
|
||||||
|
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true, options: ['default' => null])]
|
||||||
|
private ?int $numberOfDependents = null;
|
||||||
|
|
||||||
|
#[Assert\NotNull]
|
||||||
|
#[Assert\GreaterThanOrEqual(0, groups: ['Default', 'household_composition'])]
|
||||||
|
#[Serializer\Groups(['docgen:read'])]
|
||||||
|
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true, options: ['default' => null])]
|
||||||
|
private ?int $numberOfDependentsWithDisabilities = null;
|
||||||
|
|
||||||
#[Assert\NotNull(groups: ['Default', 'household_composition'])]
|
#[Assert\NotNull(groups: ['Default', 'household_composition'])]
|
||||||
#[Serializer\Groups(['docgen:read'])]
|
#[Serializer\Groups(['docgen:read'])]
|
||||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: false)]
|
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATE_IMMUTABLE, nullable: false)]
|
||||||
@@ -98,6 +110,16 @@ class HouseholdComposition implements TrackCreationInterface, TrackUpdateInterfa
|
|||||||
return $this->numberOfChildren;
|
return $this->numberOfChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getNumberOfDependents(): ?int
|
||||||
|
{
|
||||||
|
return $this->numberOfDependents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNumberOfDependentsWithDisabilities(): ?int
|
||||||
|
{
|
||||||
|
return $this->numberOfDependentsWithDisabilities;
|
||||||
|
}
|
||||||
|
|
||||||
public function getStartDate(): ?\DateTimeImmutable
|
public function getStartDate(): ?\DateTimeImmutable
|
||||||
{
|
{
|
||||||
return $this->startDate;
|
return $this->startDate;
|
||||||
@@ -142,6 +164,20 @@ class HouseholdComposition implements TrackCreationInterface, TrackUpdateInterfa
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setNumberOfDependents(?int $numberOfDependents): HouseholdComposition
|
||||||
|
{
|
||||||
|
$this->numberOfDependents = $numberOfDependents;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setNumberOfDependentsWithDisabilities(?int $numberOfDependentsWithDisabilities): HouseholdComposition
|
||||||
|
{
|
||||||
|
$this->numberOfDependentsWithDisabilities = $numberOfDependentsWithDisabilities;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setStartDate(?\DateTimeImmutable $startDate): HouseholdComposition
|
public function setStartDate(?\DateTimeImmutable $startDate): HouseholdComposition
|
||||||
{
|
{
|
||||||
$this->startDate = $startDate;
|
$this->startDate = $startDate;
|
||||||
|
@@ -304,6 +304,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)]
|
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)]
|
||||||
private string $memo = '';
|
private string $memo = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The person's administrative status.
|
||||||
|
*/
|
||||||
|
#[ORM\ManyToOne(targetEntity: AdministrativeStatus::class)]
|
||||||
|
#[ORM\JoinColumn(nullable: true)]
|
||||||
|
private ?AdministrativeStatus $administrativeStatus = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The person's mobile phone number.
|
* The person's mobile phone number.
|
||||||
*/
|
*/
|
||||||
@@ -777,6 +784,11 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
return $this->addresses;
|
return $this->addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAdministrativeStatus(): ?AdministrativeStatus
|
||||||
|
{
|
||||||
|
return $this->administrativeStatus;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the age of a person, calculated at the date 'now'.
|
* Return the age of a person, calculated at the date 'now'.
|
||||||
*
|
*
|
||||||
@@ -1420,6 +1432,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setAdministrativeStatus(?AdministrativeStatus $administrativeStatus): self
|
||||||
|
{
|
||||||
|
$this->administrativeStatus = $administrativeStatus;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setAcceptSMS(bool $acceptSMS): self
|
public function setAcceptSMS(bool $acceptSMS): self
|
||||||
{
|
{
|
||||||
$this->acceptSMS = $acceptSMS;
|
$this->acceptSMS = $acceptSMS;
|
||||||
|
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Export\Aggregator\PersonAggregators;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Export\AggregatorInterface;
|
||||||
|
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||||
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Chill\PersonBundle\Repository\AdministrativeStatusRepository;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
final readonly class AdministrativeStatusAggregator implements AggregatorInterface
|
||||||
|
{
|
||||||
|
public function __construct(private AdministrativeStatusRepository $administrativeStatusRepository, private TranslatableStringHelper $translatableStringHelper) {}
|
||||||
|
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
|
{
|
||||||
|
$qb->leftJoin('person.administrativeStatus', 'admin_status');
|
||||||
|
$qb->addSelect('admin_status.id as administrative_status_aggregator');
|
||||||
|
|
||||||
|
$qb->addGroupBy('administrative_status_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::PERSON_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder) {}
|
||||||
|
|
||||||
|
public function getFormDefaultData(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLabels($key, array $values, $data)
|
||||||
|
{
|
||||||
|
return function ($value): string {
|
||||||
|
if ('_header' === $value) {
|
||||||
|
return 'Administrative status';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $value || '' === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$g = $this->administrativeStatusRepository->find($value);
|
||||||
|
|
||||||
|
return $this->translatableStringHelper->localize($g->getName());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryKeys($data)
|
||||||
|
{
|
||||||
|
return ['administrative_status_aggregator'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return 'Group people by administrative status';
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Export\Aggregator\PersonAggregators;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Export\AggregatorInterface;
|
||||||
|
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||||
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Chill\PersonBundle\Repository\EmploymentStatusRepository;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
final readonly class EmploymentStatusAggregator implements AggregatorInterface
|
||||||
|
{
|
||||||
|
public function __construct(private EmploymentStatusRepository $employmentStatusRepository, private TranslatableStringHelper $translatableStringHelper) {}
|
||||||
|
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
|
{
|
||||||
|
$qb->leftJoin('person.employmentStatus', 'es');
|
||||||
|
$qb->addSelect('es.id as employment_status_aggregator');
|
||||||
|
|
||||||
|
$qb->addGroupBy('employment_status_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::PERSON_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder) {}
|
||||||
|
|
||||||
|
public function getFormDefaultData(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLabels($key, array $values, $data)
|
||||||
|
{
|
||||||
|
return function ($value): string {
|
||||||
|
if ('_header' === $value) {
|
||||||
|
return 'Employment status';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $value || '' === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$g = $this->employmentStatusRepository->find($value);
|
||||||
|
|
||||||
|
return $this->translatableStringHelper->localize($g->getName());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryKeys($data)
|
||||||
|
{
|
||||||
|
return ['employment_status_aggregator'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return 'Group people by employment status';
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Form;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||||
|
use Chill\PersonBundle\Entity\AdministrativeStatus;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
class AdministrativeStatusType extends \Symfony\Component\Form\AbstractType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('name', TranslatableStringFormType::class, [
|
||||||
|
'required' => true,
|
||||||
|
])
|
||||||
|
->add('active', ChoiceType::class, [
|
||||||
|
'choices' => [
|
||||||
|
'Active' => true,
|
||||||
|
'Inactive' => false,
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->add('order', NumberType::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => AdministrativeStatus::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@@ -19,10 +19,19 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
|||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
|
|
||||||
class HouseholdCompositionType extends AbstractType
|
class HouseholdCompositionType extends AbstractType
|
||||||
{
|
{
|
||||||
public function __construct(private readonly HouseholdCompositionTypeRepository $householdCompositionTypeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {}
|
private array $household_fields_visibility;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private readonly HouseholdCompositionTypeRepository $householdCompositionTypeRepository,
|
||||||
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
|
protected ParameterBagInterface $parameterBag,
|
||||||
|
) {
|
||||||
|
$this->household_fields_visibility = $parameterBag->get('chill_person.household_fields');
|
||||||
|
}
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
@@ -42,7 +51,19 @@ class HouseholdCompositionType extends AbstractType
|
|||||||
->add('numberOfChildren', IntegerType::class, [
|
->add('numberOfChildren', IntegerType::class, [
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => 'household_composition.numberOfChildren',
|
'label' => 'household_composition.numberOfChildren',
|
||||||
])
|
]);
|
||||||
|
if ('visible' == $this->household_fields_visibility['number_of_dependents']) {
|
||||||
|
$builder
|
||||||
|
->add('numberOfDependents', IntegerType::class, [
|
||||||
|
'required' => true,
|
||||||
|
'label' => 'household_composition.numberOfDependents',
|
||||||
|
])
|
||||||
|
->add('numberOfDependentsWithDisabilities', IntegerType::class, [
|
||||||
|
'required' => true,
|
||||||
|
'label' => 'household_composition.numberOfDependentsWithDisabilities',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$builder
|
||||||
->add('comment', CommentType::class, [
|
->add('comment', CommentType::class, [
|
||||||
'required' => false,
|
'required' => false,
|
||||||
]);
|
]);
|
||||||
|
@@ -26,6 +26,7 @@ use Chill\PersonBundle\Entity\Person;
|
|||||||
use Chill\PersonBundle\Entity\PersonPhone;
|
use Chill\PersonBundle\Entity\PersonPhone;
|
||||||
use Chill\PersonBundle\Form\Type\PersonAltNameType;
|
use Chill\PersonBundle\Form\Type\PersonAltNameType;
|
||||||
use Chill\PersonBundle\Form\Type\PersonPhoneType;
|
use Chill\PersonBundle\Form\Type\PersonPhoneType;
|
||||||
|
use Chill\PersonBundle\Form\Type\PickAdministrativeStatusType;
|
||||||
use Chill\PersonBundle\Form\Type\PickEmploymentStatusType;
|
use Chill\PersonBundle\Form\Type\PickEmploymentStatusType;
|
||||||
use Chill\PersonBundle\Form\Type\PickGenderType;
|
use Chill\PersonBundle\Form\Type\PickGenderType;
|
||||||
use Chill\PersonBundle\Form\Type\Select2MaritalStatusType;
|
use Chill\PersonBundle\Form\Type\Select2MaritalStatusType;
|
||||||
@@ -108,6 +109,11 @@ class PersonType extends AbstractType
|
|||||||
->add('employmentStatus', PickEmploymentStatusType::class, ['required' => false]);
|
->add('employmentStatus', PickEmploymentStatusType::class, ['required' => false]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('visible' === $this->config['administrative_status']) {
|
||||||
|
$builder
|
||||||
|
->add('administrativeStatus', PickAdministrativeStatusType::class, ['required' => false]);
|
||||||
|
}
|
||||||
|
|
||||||
if ('visible' === $this->config['place_of_birth']) {
|
if ('visible' === $this->config['place_of_birth']) {
|
||||||
$builder->add('placeOfBirth', TextType::class, [
|
$builder->add('placeOfBirth', TextType::class, [
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Form\Type;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
|
use Chill\PersonBundle\Entity\AdministrativeStatus;
|
||||||
|
|
||||||
|
class PickAdministrativeStatusType extends AbstractType
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver
|
||||||
|
->setDefault('label', 'Administrative Status')
|
||||||
|
->setDefault(
|
||||||
|
'choice_label',
|
||||||
|
fn (AdministrativeStatus $administrativeStatus): string => $this->translatableStringHelper->localize($administrativeStatus->getName())
|
||||||
|
)
|
||||||
|
->setDefault(
|
||||||
|
'query_builder',
|
||||||
|
static fn (EntityRepository $er): QueryBuilder => $er->createQueryBuilder('c')
|
||||||
|
->where('c.active = true')
|
||||||
|
->orderBy('c.order'),
|
||||||
|
)
|
||||||
|
->setDefault('placeholder', $this->translatableStringHelper->localize(['Select an option…']))
|
||||||
|
->setDefault('class', AdministrativeStatus::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent()
|
||||||
|
{
|
||||||
|
return EntityType::class;
|
||||||
|
}
|
||||||
|
}
|
@@ -65,6 +65,12 @@ class AdminPersonMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
])->setExtras(['order' => 2035]);
|
])->setExtras(['order' => 2035]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('visible' == $this->fields_visibility['administrative_status']) {
|
||||||
|
$menu->addChild('Administrative status', [
|
||||||
|
'route' => 'chill_crud_administrative_status_index',
|
||||||
|
])->setExtras(['order' => 2036]);
|
||||||
|
}
|
||||||
|
|
||||||
$menu->addChild('person_admin.person_resource_kind', [
|
$menu->addChild('person_admin.person_resource_kind', [
|
||||||
'route' => 'chill_crud_person_resource-kind_index',
|
'route' => 'chill_crud_person_resource-kind_index',
|
||||||
])->setExtras(['order' => 2040]);
|
])->setExtras(['order' => 2040]);
|
||||||
|
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\AdministrativeStatus;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
class AdministrativeStatusRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, AdministrativeStatus::class);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\EmploymentStatus;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
class EmploymentStatusRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, EmploymentStatus::class);
|
||||||
|
}
|
||||||
|
}
|
@@ -44,6 +44,14 @@ final readonly class SocialActionRepository implements ObjectRepository
|
|||||||
return $this->repository->findAll();
|
return $this->repository->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function findAllOrdered(): array
|
||||||
|
{
|
||||||
|
return $this->repository->createQueryBuilder('si')
|
||||||
|
->orderBy('si.ordering', 'ASC')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array|SocialAction[]
|
* @return array|SocialAction[]
|
||||||
*/
|
*/
|
||||||
|
@@ -39,6 +39,14 @@ final readonly class SocialIssueRepository implements ObjectRepository
|
|||||||
return $this->repository->findAll();
|
return $this->repository->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function findAllOrdered(): array
|
||||||
|
{
|
||||||
|
return $this->repository->createQueryBuilder('si')
|
||||||
|
->orderBy('si.ordering', 'ASC')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array|SocialIssue[]
|
* @return array|SocialIssue[]
|
||||||
*/
|
*/
|
||||||
|
@@ -33,18 +33,7 @@ const getUserJobs = () => fetchResults("/api/1.0/main/user-job.json");
|
|||||||
|
|
||||||
const getSocialIssues = () => {
|
const getSocialIssues = () => {
|
||||||
const url = `/api/1.0/person/social-work/social-issue.json`;
|
const url = `/api/1.0/person/social-work/social-issue.json`;
|
||||||
return fetch(url).then((response) => {
|
return fetchResults(url);
|
||||||
if (response.ok) {
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
throw {
|
|
||||||
msg: "Error while retriving Social Issues.",
|
|
||||||
sta: response.status,
|
|
||||||
txt: response.statusText,
|
|
||||||
err: new Error(),
|
|
||||||
body: response.body,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const whoami = () => {
|
const whoami = () => {
|
||||||
|
@@ -16,7 +16,8 @@
|
|||||||
<ckeditor
|
<ckeditor
|
||||||
name="content"
|
name="content"
|
||||||
:placeholder="$t('comment.content')"
|
:placeholder="$t('comment.content')"
|
||||||
:editor="editor"
|
:editor="classicEditor"
|
||||||
|
:config="editorConfig"
|
||||||
v-model="content"
|
v-model="content"
|
||||||
tag-name="textarea"
|
tag-name="textarea"
|
||||||
/>
|
/>
|
||||||
@@ -60,18 +61,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CKEditor from "@ckeditor/ckeditor5-vue";
|
import { ClassicEditor } from "ckeditor5";
|
||||||
import ClassicEditor from "../../../../../../ChillMainBundle/Resources/public/module/ckeditor5/editor_config";
|
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
|
||||||
|
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
|
||||||
import { mapState } from "vuex";
|
import { mapState } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Comment",
|
name: "Comment",
|
||||||
components: {
|
components: {
|
||||||
ckeditor: CKEditor.component,
|
ckeditor: Ckeditor,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
editor: ClassicEditor,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
lastRecordedContent: null,
|
lastRecordedContent: null,
|
||||||
};
|
};
|
||||||
@@ -80,6 +81,8 @@ export default {
|
|||||||
...mapState({
|
...mapState({
|
||||||
pinnedComment: (state) => state.accompanyingCourse.pinnedComment,
|
pinnedComment: (state) => state.accompanyingCourse.pinnedComment,
|
||||||
}),
|
}),
|
||||||
|
classicEditor: () => ClassicEditor,
|
||||||
|
editorConfig: () => classicEditorConfig,
|
||||||
content: {
|
content: {
|
||||||
set(value) {
|
set(value) {
|
||||||
console.log("new comment value", value);
|
console.log("new comment value", value);
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
name="content"
|
name="content"
|
||||||
:placeholder="$t('comment_placeholder')"
|
:placeholder="$t('comment_placeholder')"
|
||||||
:editor="editor"
|
:editor="editor"
|
||||||
|
:config="editorConfig"
|
||||||
v-model="content"
|
v-model="content"
|
||||||
tag-name="textarea"
|
tag-name="textarea"
|
||||||
/>
|
/>
|
||||||
@@ -38,14 +39,15 @@
|
|||||||
<script>
|
<script>
|
||||||
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
import CKEditor from "@ckeditor/ckeditor5-vue";
|
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
|
||||||
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
|
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
|
||||||
|
import { ClassicEditor } from "ckeditor5";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "WriteComment",
|
name: "WriteComment",
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
ckeditor: CKEditor.component,
|
ckeditor: Ckeditor,
|
||||||
},
|
},
|
||||||
props: ["resource"],
|
props: ["resource"],
|
||||||
emits: ["updateComment"],
|
emits: ["updateComment"],
|
||||||
@@ -55,7 +57,6 @@ export default {
|
|||||||
showModal: false,
|
showModal: false,
|
||||||
modalDialogClass: "modal-dialog-scrollable modal-xl",
|
modalDialogClass: "modal-dialog-scrollable modal-xl",
|
||||||
},
|
},
|
||||||
editor: ClassicEditor,
|
|
||||||
formdata: {
|
formdata: {
|
||||||
content: this.resource.comment,
|
content: this.resource.comment,
|
||||||
},
|
},
|
||||||
@@ -71,6 +72,8 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
editor: () => ClassicEditor,
|
||||||
|
editorConfig: () => classicEditorConfig,
|
||||||
content: {
|
content: {
|
||||||
set(value) {
|
set(value) {
|
||||||
this.formdata.content = value;
|
this.formdata.content = value;
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import VueMultiselect from "vue-multiselect";
|
import VueMultiselect from "vue-multiselect";
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
import { fetchResults } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
import { mapGetters, mapState } from "vuex";
|
import { mapGetters, mapState } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -51,16 +51,11 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getOptions() {
|
getOptions() {
|
||||||
const url = `/api/1.0/person/social-work/social-issue.json`;
|
fetchResults(`/api/1.0/person/social-work/social-issue.json`).then(
|
||||||
makeFetch("GET", url)
|
(response) => {
|
||||||
.then((response) => {
|
this.options = response;
|
||||||
this.options = response.results;
|
},
|
||||||
return response;
|
);
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
commit("catchError", error);
|
|
||||||
this.$toast.open({ message: error.txt });
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
updateSocialIssues(value) {
|
updateSocialIssues(value) {
|
||||||
this.$store
|
this.$store
|
||||||
|
@@ -6,7 +6,7 @@ import {
|
|||||||
} from "ChillMainAssets/chill/js/date";
|
} from "ChillMainAssets/chill/js/date";
|
||||||
import { findSocialActionsBySocialIssue } from "ChillPersonAssets/vuejs/_api/SocialWorkSocialAction.js";
|
import { findSocialActionsBySocialIssue } from "ChillPersonAssets/vuejs/_api/SocialWorkSocialAction.js";
|
||||||
// import { create } from 'ChillPersonAssets/vuejs/_api/AccompanyingCourseWork.js';
|
// import { create } from 'ChillPersonAssets/vuejs/_api/AccompanyingCourseWork.js';
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
import { fetchResults, makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
|
|
||||||
const debug = process.env.NODE_ENV !== "production";
|
const debug = process.env.NODE_ENV !== "production";
|
||||||
|
|
||||||
@@ -168,9 +168,9 @@ const store = createStore({
|
|||||||
},
|
},
|
||||||
fetchOtherSocialIssues({ commit }) {
|
fetchOtherSocialIssues({ commit }) {
|
||||||
const url = `/api/1.0/person/social-work/social-issue.json`;
|
const url = `/api/1.0/person/social-work/social-issue.json`;
|
||||||
return makeFetch("GET", url)
|
return fetchResults(url)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
commit("updateIssuesOther", response.results);
|
commit("updateIssuesOther", response); // Directly commit the array of issues
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error;
|
throw error;
|
||||||
|
@@ -36,14 +36,20 @@
|
|||||||
<label class="col-form-label">{{ $t("private_comment") }}</label>
|
<label class="col-form-label">{{ $t("private_comment") }}</label>
|
||||||
<ckeditor
|
<ckeditor
|
||||||
v-model="privateComment"
|
v-model="privateComment"
|
||||||
:editor="editor"
|
:editor="classicEditor"
|
||||||
|
:config="editorConfig"
|
||||||
tag-name="textarea"
|
tag-name="textarea"
|
||||||
></ckeditor>
|
></ckeditor>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="comment" class="action-row">
|
<div id="comment" class="action-row">
|
||||||
<label class="col-form-label">{{ $t("comments") }}</label>
|
<label class="col-form-label">{{ $t("comments") }}</label>
|
||||||
<ckeditor v-model="note" :editor="editor" tag-name="textarea"></ckeditor>
|
<ckeditor
|
||||||
|
v-model="note"
|
||||||
|
:editor="classicEditor"
|
||||||
|
:config="editorConfig"
|
||||||
|
tag-name="textarea"
|
||||||
|
></ckeditor>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="objectives" class="action-row">
|
<div id="objectives" class="action-row">
|
||||||
@@ -432,23 +438,16 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState, mapGetters } from "vuex";
|
import { mapState, mapGetters } from "vuex";
|
||||||
import {
|
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
|
||||||
dateToISO,
|
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
|
||||||
ISOToDate,
|
import { ClassicEditor } from "ckeditor5";
|
||||||
ISOToDatetime,
|
|
||||||
} from "ChillMainAssets/chill/js/date";
|
|
||||||
import CKEditor from "@ckeditor/ckeditor5-vue";
|
|
||||||
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
|
|
||||||
import AddResult from "./components/AddResult.vue";
|
import AddResult from "./components/AddResult.vue";
|
||||||
import AddEvaluation from "./components/AddEvaluation.vue";
|
import AddEvaluation from "./components/AddEvaluation.vue";
|
||||||
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
||||||
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
|
|
||||||
import ThirdPartyRenderBox from "ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyRenderBox.vue";
|
import ThirdPartyRenderBox from "ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyRenderBox.vue";
|
||||||
import PickTemplate from "ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue";
|
|
||||||
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
|
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
|
||||||
import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue";
|
import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue";
|
||||||
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
||||||
import { buildLinkCreate } from "ChillMainAssets/lib/entity-workflow/api";
|
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
|
|
||||||
const i18n = {
|
const i18n = {
|
||||||
@@ -505,13 +504,11 @@ const i18n = {
|
|||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: "App",
|
||||||
components: {
|
components: {
|
||||||
ckeditor: CKEditor.component,
|
ckeditor: Ckeditor,
|
||||||
AddResult,
|
AddResult,
|
||||||
AddEvaluation,
|
AddEvaluation,
|
||||||
AddPersons,
|
AddPersons,
|
||||||
AddressRenderBox,
|
|
||||||
ThirdPartyRenderBox,
|
ThirdPartyRenderBox,
|
||||||
PickTemplate,
|
|
||||||
ListWorkflowModal,
|
ListWorkflowModal,
|
||||||
OnTheFly,
|
OnTheFly,
|
||||||
PersonText,
|
PersonText,
|
||||||
@@ -521,7 +518,6 @@ export default {
|
|||||||
return {
|
return {
|
||||||
docAnchorId: null,
|
docAnchorId: null,
|
||||||
isExpanded: false,
|
isExpanded: false,
|
||||||
editor: ClassicEditor,
|
|
||||||
showAddObjective: false,
|
showAddObjective: false,
|
||||||
showAddEvaluation: false,
|
showAddEvaluation: false,
|
||||||
handlingThirdPartyPicker: {
|
handlingThirdPartyPicker: {
|
||||||
@@ -588,6 +584,8 @@ export default {
|
|||||||
"hasThirdParties",
|
"hasThirdParties",
|
||||||
"hasReferrers",
|
"hasReferrers",
|
||||||
]),
|
]),
|
||||||
|
classicEditor: () => ClassicEditor,
|
||||||
|
editorConfig: () => classicEditorConfig,
|
||||||
startDate: {
|
startDate: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.state.startDate;
|
return this.$store.state.startDate;
|
||||||
@@ -696,7 +694,7 @@ export default {
|
|||||||
},
|
},
|
||||||
goToGenerateWorkflow({ link }) {
|
goToGenerateWorkflow({ link }) {
|
||||||
// console.log('save before leave to generate workflow')
|
// console.log('save before leave to generate workflow')
|
||||||
const callback = (data) => {
|
const callback = () => {
|
||||||
window.location.assign(link);
|
window.location.assign(link);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -707,7 +705,7 @@ export default {
|
|||||||
},
|
},
|
||||||
goToGenerateNotification(tos) {
|
goToGenerateNotification(tos) {
|
||||||
console.log("save before leave to notification");
|
console.log("save before leave to notification");
|
||||||
const callback = (data) => {
|
const callback = () => {
|
||||||
if (tos === true) {
|
if (tos === true) {
|
||||||
window.location.assign(
|
window.location.assign(
|
||||||
`/fr/notification/create?entityClass=Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork&entityId=${this.work.id}&tos[0]=${this.work.accompanyingPeriod.user.id}&returnPath=/fr/person/accompanying-period/${this.work.accompanyingPeriod.id}/work`,
|
`/fr/notification/create?entityClass=Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork&entityId=${this.work.id}&tos[0]=${this.work.accompanyingPeriod.user.id}&returnPath=/fr/person/accompanying-period/${this.work.accompanyingPeriod.id}/work`,
|
||||||
|
@@ -89,7 +89,8 @@
|
|||||||
}}</label>
|
}}</label>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<ckeditor
|
<ckeditor
|
||||||
:editor="editor"
|
:editor="classicEditor"
|
||||||
|
:config="editorConfig"
|
||||||
:placeholder="$t('evaluation_comment_placeholder')"
|
:placeholder="$t('evaluation_comment_placeholder')"
|
||||||
v-model="comment"
|
v-model="comment"
|
||||||
tag-name="textarea"
|
tag-name="textarea"
|
||||||
@@ -271,14 +272,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import { ISOToDatetime } from "ChillMainAssets/chill/js/date";
|
||||||
dateToISO,
|
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
|
||||||
ISOToDate,
|
import { ClassicEditor } from "ckeditor5";
|
||||||
ISOToDatetime,
|
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
|
||||||
} from "ChillMainAssets/chill/js/date";
|
import { mapState } from "vuex";
|
||||||
import CKEditor from "@ckeditor/ckeditor5-vue";
|
|
||||||
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
|
|
||||||
import { mapGetters, mapState } from "vuex";
|
|
||||||
import PickTemplate from "ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue";
|
import PickTemplate from "ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue";
|
||||||
import { buildLink } from "ChillDocGeneratorAssets/lib/document-generator";
|
import { buildLink } from "ChillDocGeneratorAssets/lib/document-generator";
|
||||||
import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue";
|
import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue";
|
||||||
@@ -325,7 +323,7 @@ export default {
|
|||||||
props: ["evaluation", "docAnchorId"],
|
props: ["evaluation", "docAnchorId"],
|
||||||
components: {
|
components: {
|
||||||
DropFileModal,
|
DropFileModal,
|
||||||
ckeditor: CKEditor.component,
|
ckeditor: Ckeditor,
|
||||||
PickTemplate,
|
PickTemplate,
|
||||||
ListWorkflowModal,
|
ListWorkflowModal,
|
||||||
DocumentActionButtonsGroup,
|
DocumentActionButtonsGroup,
|
||||||
@@ -333,7 +331,6 @@ export default {
|
|||||||
i18n,
|
i18n,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
editor: ClassicEditor,
|
|
||||||
template: null,
|
template: null,
|
||||||
asyncUploadOptions: {
|
asyncUploadOptions: {
|
||||||
maxFiles: 1,
|
maxFiles: 1,
|
||||||
@@ -374,6 +371,8 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["isPosting", "work", "me"]),
|
...mapState(["isPosting", "work", "me"]),
|
||||||
|
classicEditor: () => ClassicEditor,
|
||||||
|
editorConfig: () => classicEditorConfig,
|
||||||
AmIRefferer() {
|
AmIRefferer() {
|
||||||
return !(
|
return !(
|
||||||
this.$store.state.work.accompanyingPeriod.user &&
|
this.$store.state.work.accompanyingPeriod.user &&
|
||||||
@@ -596,12 +595,7 @@ export default {
|
|||||||
newStatus: newStatus,
|
newStatus: newStatus,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
goToGenerateWorkflowEvaluationDocument({
|
goToGenerateWorkflowEvaluationDocument({ workflowName, payload }) {
|
||||||
event,
|
|
||||||
link,
|
|
||||||
workflowName,
|
|
||||||
payload,
|
|
||||||
}) {
|
|
||||||
const callback = (data) => {
|
const callback = (data) => {
|
||||||
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
||||||
(e) => e.key === this.evaluation.key,
|
(e) => e.key === this.evaluation.key,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user