mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-26 08:35:00 +00:00
Compare commits
18 Commits
v3.10.0
...
366-pick-u
Author | SHA1 | Date | |
---|---|---|---|
1af3e4c7ec | |||
5d0fc7a189 | |||
483d50e776 | |||
b4c6ccf309 | |||
ac6a81cbd8 | |||
9503cb89b6 | |||
b130dbdcdc | |||
b2b1865837 | |||
ec5c4d51b3 | |||
fe6949ea26 | |||
8a444a12f4 | |||
8b7b5ceed7
|
|||
b0e826d05a
|
|||
6fb9c3af3f
|
|||
7f101ba616
|
|||
cea82fac10 | |||
1344fc33e1 | |||
c8e09a28e6 |
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
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,6 +13,7 @@ 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/translator.ts
|
||||||
|
!assets/ux-translator
|
||||||
migrations/*
|
migrations/*
|
||||||
templates/*
|
templates/*
|
||||||
translations/*
|
translations/*
|
||||||
|
12
CHANGELOG.md
12
CHANGELOG.md
@@ -6,6 +6,18 @@ 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
|
## v3.10.0 - 2025-03-17
|
||||||
### Feature
|
### Feature
|
||||||
* ([#363](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/363)) Display social actions grouped per social issue within activity form
|
* ([#363](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/363)) Display social actions grouped per social issue within activity form
|
||||||
|
@@ -1,9 +1,7 @@
|
|||||||
// @ts-ignore Cannot find module (when used within an app)
|
import { trans, setLocale, setLocaleFallbacks } from "./ux-translator";
|
||||||
import { trans, setLocale, setLocaleFallbacks } from "@symfony/ux-translator";
|
|
||||||
|
|
||||||
setLocaleFallbacks({"en": "fr", "nl": "fr", "fr": "en"});
|
setLocaleFallbacks({"en": "fr", "nl": "fr", "fr": "en"});
|
||||||
setLocale('fr');
|
setLocale('fr');
|
||||||
|
|
||||||
export { trans };
|
export { trans };
|
||||||
// @ts-ignore Cannot find module (when used within an app)
|
|
||||||
export * from '../var/translations';
|
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"
|
||||||
|
}
|
||||||
|
}
|
@@ -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"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
"@hotwired/stimulus": "^3.0.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/stimulus-bridge": "^3.2.0",
|
||||||
"@symfony/ux-translator": "file:vendor/symfony/ux-translator/assets",
|
|
||||||
"@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",
|
||||||
@@ -59,6 +58,7 @@
|
|||||||
"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",
|
||||||
|
@@ -96,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<FullCalendar :options="calendarOptions" ref="calendarRef">
|
<FullCalendar :options="calendarOptions" ref="calendarRef">
|
||||||
<template v-slot:eventContent="{ arg }: {arg: { event: 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
|
||||||
|
@@ -91,9 +91,7 @@
|
|||||||
class="col-5 p-0 text-center turnSignature"
|
class="col-5 p-0 text-center turnSignature"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
:disabled="
|
:disabled="isFirstSignatureZone"
|
||||||
isFirstSignatureZone
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(-1)"
|
@click="turnSignature(-1)"
|
||||||
>
|
>
|
||||||
@@ -101,9 +99,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<button
|
<button
|
||||||
:disabled="
|
:disabled="isLastSignatureZone"
|
||||||
isLastSignatureZone
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(1)"
|
@click="turnSignature(1)"
|
||||||
>
|
>
|
||||||
@@ -207,9 +203,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<button
|
<button
|
||||||
:disabled="
|
:disabled="isLastSignatureZone"
|
||||||
isLastSignatureZone
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(1)"
|
@click="turnSignature(1)"
|
||||||
>
|
>
|
||||||
@@ -221,9 +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"
|
||||||
isFirstSignatureZone
|
|
||||||
"
|
|
||||||
class="btn btn-light btn-sm"
|
class="btn btn-light btn-sm"
|
||||||
@click="turnSignature(-1)"
|
@click="turnSignature(-1)"
|
||||||
>
|
>
|
||||||
@@ -326,7 +318,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, Ref, reactive, computed} 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 {
|
||||||
@@ -344,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";
|
||||||
|
|
||||||
@@ -426,13 +415,19 @@ const $toast = useToast();
|
|||||||
|
|
||||||
const signature = window.signature;
|
const signature = window.signature;
|
||||||
|
|
||||||
const isFirstSignatureZone = () => userSignatureZone.value?.index ? userSignatureZone.value.index < 1 : false
|
const isFirstSignatureZone = () =>
|
||||||
const isLastSignatureZone = () => userSignatureZone.value?.index ? userSignatureZone.value.index >= signature.zones.length - 1 : false
|
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)
|
* 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 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);
|
||||||
@@ -755,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) => {
|
||||||
@@ -777,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) => {
|
||||||
|
@@ -3,9 +3,8 @@ import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
|||||||
import { reactive } from "vue";
|
import { reactive } from "vue";
|
||||||
import HistoryButtonList from "ChillDocStoreAssets/vuejs/StoredObjectButton/HistoryButton/HistoryButtonList.vue";
|
import HistoryButtonList from "ChillDocStoreAssets/vuejs/StoredObjectButton/HistoryButton/HistoryButtonList.vue";
|
||||||
import {
|
import {
|
||||||
StoredObject, StoredObjectVersion,
|
StoredObject,
|
||||||
StoredObjectVersionWithPointInTime,
|
StoredObjectVersionWithPointInTime,
|
||||||
StoredObjectPointInTime
|
|
||||||
} from "./../../../types";
|
} from "./../../../types";
|
||||||
|
|
||||||
interface HistoryButtonListConfig {
|
interface HistoryButtonListConfig {
|
||||||
@@ -29,7 +28,9 @@ const open = () => {
|
|||||||
state.opened = true;
|
state.opened = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRestoreVersion = (payload : { newVersion: StoredObjectVersionWithPointInTime }) => emit('restoreVersion', payload)
|
const onRestoreVersion = (payload: {
|
||||||
|
newVersion: StoredObjectVersionWithPointInTime;
|
||||||
|
}) => emit("restoreVersion", payload);
|
||||||
|
|
||||||
defineExpose({ open });
|
defineExpose({ open });
|
||||||
</script>
|
</script>
|
||||||
@@ -45,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"
|
||||||
onRestoreVersion
|
|
||||||
"
|
|
||||||
></history-button-list>
|
></history-button-list>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</modal>
|
||||||
|
@@ -66,8 +66,11 @@ class EntityToJsonTransformer implements DataTransformerInterface
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function denormalizeOne(array $item)
|
private function denormalizeOne(array|string $item)
|
||||||
{
|
{
|
||||||
|
if ('me' === $item) {
|
||||||
|
return $item;
|
||||||
|
}
|
||||||
if (!\array_key_exists('type', $item)) {
|
if (!\array_key_exists('type', $item)) {
|
||||||
throw new TransformationFailedException('the key "type" is missing on element');
|
throw new TransformationFailedException('the key "type" is missing on element');
|
||||||
}
|
}
|
||||||
@@ -98,5 +101,6 @@ class EntityToJsonTransformer implements DataTransformerInterface
|
|||||||
'json',
|
'json',
|
||||||
$context,
|
$context,
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,82 @@
|
|||||||
|
<?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\Form\Type;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\MainBundle\Form\Type\DataTransformer\EntityToJsonTransformer;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\Form\FormInterface;
|
||||||
|
use Symfony\Component\Form\FormView;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||||
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick user dymically, using vuejs module "AddPerson".
|
||||||
|
*
|
||||||
|
* Possible options:
|
||||||
|
*
|
||||||
|
* - `multiple`: pick one or more users
|
||||||
|
* - `suggested`: a list of suggested users
|
||||||
|
* - `suggest_myself`: append the current user to the list of suggested
|
||||||
|
* - `as_id`: only the id will be set in the returned data
|
||||||
|
* - `submit_on_adding_new_entity`: the browser will immediately submit the form when new users are checked
|
||||||
|
*/
|
||||||
|
class PickUserOrMeDynamicType extends AbstractType
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly DenormalizerInterface $denormalizer,
|
||||||
|
private readonly SerializerInterface $serializer,
|
||||||
|
private readonly NormalizerInterface $normalizer,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
{
|
||||||
|
$builder->addViewTransformer(new EntityToJsonTransformer($this->denormalizer, $this->serializer, $options['multiple'], 'user'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||||
|
{
|
||||||
|
$view->vars['multiple'] = $options['multiple'];
|
||||||
|
$view->vars['types'] = ['user'];
|
||||||
|
$view->vars['uniqid'] = uniqid('pick_user_or_me_dyn');
|
||||||
|
$view->vars['suggested'] = [];
|
||||||
|
$view->vars['as_id'] = true === $options['as_id'] ? '1' : '0';
|
||||||
|
$view->vars['submit_on_adding_new_entity'] = true === $options['submit_on_adding_new_entity'] ? '1' : '0';
|
||||||
|
|
||||||
|
foreach ($options['suggested'] as $user) {
|
||||||
|
$view->vars['suggested'][] = $this->normalizer->normalize($user, 'json', ['groups' => 'read']);
|
||||||
|
}
|
||||||
|
// $user = /* should come from context */ $options['context'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver
|
||||||
|
->setDefault('multiple', false)
|
||||||
|
->setAllowedTypes('multiple', ['bool'])
|
||||||
|
->setDefault('compound', false)
|
||||||
|
->setDefault('suggested', [])
|
||||||
|
// if set to true, only the id will be set inside the content. The denormalization will not work.
|
||||||
|
->setDefault('as_id', false)
|
||||||
|
->setAllowedTypes('as_id', ['bool'])
|
||||||
|
->setDefault('submit_on_adding_new_entity', false)
|
||||||
|
->setAllowedTypes('submit_on_adding_new_entity', ['bool']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBlockPrefix()
|
||||||
|
{
|
||||||
|
return 'pick_entity_dynamic';
|
||||||
|
}
|
||||||
|
}
|
@@ -12,6 +12,11 @@ function loadDynamicPicker(element) {
|
|||||||
let apps = element.querySelectorAll('[data-module="pick-dynamic"]');
|
let apps = element.querySelectorAll('[data-module="pick-dynamic"]');
|
||||||
|
|
||||||
apps.forEach(function (el) {
|
apps.forEach(function (el) {
|
||||||
|
let suggested;
|
||||||
|
let as_id;
|
||||||
|
let submit_on_adding_new_entity;
|
||||||
|
let label;
|
||||||
|
let isCurrentUserPicker;
|
||||||
const isMultiple = parseInt(el.dataset.multiple) === 1,
|
const isMultiple = parseInt(el.dataset.multiple) === 1,
|
||||||
uniqId = el.dataset.uniqid,
|
uniqId = el.dataset.uniqid,
|
||||||
input = element.querySelector(
|
input = element.querySelector(
|
||||||
@@ -22,12 +27,13 @@ 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;
|
||||||
|
isCurrentUserPicker = uniqId.startsWith("pick_user_or_me_dyn");
|
||||||
|
|
||||||
if (!isMultiple) {
|
if (!isMultiple) {
|
||||||
if (input.value === "[]") {
|
if (input.value === "[]") {
|
||||||
@@ -44,6 +50,7 @@ function loadDynamicPicker(element) {
|
|||||||
':uniqid="uniqid" ' +
|
':uniqid="uniqid" ' +
|
||||||
':suggested="notPickedSuggested" ' +
|
':suggested="notPickedSuggested" ' +
|
||||||
':label="label" ' +
|
':label="label" ' +
|
||||||
|
':isCurrentUserPicker="isCurrentUserPicker" ' +
|
||||||
'@addNewEntity="addNewEntity" ' +
|
'@addNewEntity="addNewEntity" ' +
|
||||||
'@removeEntity="removeEntity" ' +
|
'@removeEntity="removeEntity" ' +
|
||||||
'@addNewEntityProcessEnded="addNewEntityProcessEnded"' +
|
'@addNewEntityProcessEnded="addNewEntityProcessEnded"' +
|
||||||
@@ -61,6 +68,7 @@ function loadDynamicPicker(element) {
|
|||||||
as_id,
|
as_id,
|
||||||
submit_on_adding_new_entity,
|
submit_on_adding_new_entity,
|
||||||
label,
|
label,
|
||||||
|
isCurrentUserPicker,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -89,7 +97,8 @@ function loadDynamicPicker(element) {
|
|||||||
const ids = this.picked.map((el) => el.id);
|
const ids = this.picked.map((el) => el.id);
|
||||||
input.value = ids.join(",");
|
input.value = ids.join(",");
|
||||||
}
|
}
|
||||||
console.log(entity);
|
console.log(this.picked);
|
||||||
|
// console.log(entity);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
|
@@ -1,10 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<ul :class="listClasses" v-if="picked.length && displayPicked">
|
<ul :class="listClasses" v-if="picked.length && displayPicked">
|
||||||
<li v-for="p in picked" @click="removeEntity(p)" :key="p.type + p.id">
|
<li v-for="p in picked" @click="removeEntity(p)" :key="p.type + p.id">
|
||||||
<span class="chill_denomination">{{ p.text }}</span>
|
<span
|
||||||
|
v-if="'me' === p"
|
||||||
|
class="chill_denomination current-user updatedBy"
|
||||||
|
>{{ trans(USER_CURRENT_USER) }}</span
|
||||||
|
>
|
||||||
|
<span v-else class="chill_denomination">{{ p.text }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
|
<li v-if="isCurrentUserPicker" class="btn btn-sm btn-misc">
|
||||||
|
<label class="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
ref="itsMeCheckbox"
|
||||||
|
:type="multiple ? 'checkbox' : 'radio'"
|
||||||
|
@change="selectItsMe"
|
||||||
|
/>
|
||||||
|
{{ trans(USER_CURRENT_USER) }}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
<li class="add-persons">
|
<li class="add-persons">
|
||||||
<add-persons
|
<add-persons
|
||||||
:options="addPersonsOptions"
|
:options="addPersonsOptions"
|
||||||
@@ -24,119 +39,83 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
import { ref, computed } from "vue";
|
||||||
|
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue"; // eslint-disable-line
|
||||||
import { appMessages } from "./i18n";
|
import { appMessages } from "./i18n";
|
||||||
|
import { trans, USER_CURRENT_USER } from "translator";
|
||||||
|
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: "PickEntity",
|
multiple: Boolean,
|
||||||
props: {
|
types: Array,
|
||||||
multiple: {
|
picked: Array,
|
||||||
type: Boolean,
|
uniqid: String,
|
||||||
required: true,
|
removableIfSet: { type: Boolean, default: true },
|
||||||
},
|
displayPicked: { type: Boolean, default: true },
|
||||||
types: {
|
suggested: { type: Array, default: () => [] },
|
||||||
type: Array,
|
label: String,
|
||||||
required: true,
|
isCurrentUserPicker: { type: Boolean, default: false },
|
||||||
},
|
});
|
||||||
picked: {
|
|
||||||
required: true,
|
const emit = defineEmits([
|
||||||
},
|
"addNewEntity",
|
||||||
uniqid: {
|
"removeEntity",
|
||||||
type: String,
|
"addNewEntityProcessEnded",
|
||||||
required: true,
|
]);
|
||||||
},
|
|
||||||
removableIfSet: {
|
const itsMeCheckbox = ref(null);
|
||||||
type: Boolean,
|
const addPersons = ref(null);
|
||||||
default: true,
|
|
||||||
},
|
const addPersonsOptions = computed(() => ({
|
||||||
displayPicked: {
|
uniq: !props.multiple,
|
||||||
// display picked entities.
|
type: props.types,
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
suggested: {
|
|
||||||
type: Array,
|
|
||||||
default: [],
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["addNewEntity", "removeEntity", "addNewEntityProcessEnded"],
|
|
||||||
components: {
|
|
||||||
AddPersons,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
key: "",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
addPersonsOptions() {
|
|
||||||
return {
|
|
||||||
uniq: !this.multiple,
|
|
||||||
type: this.types,
|
|
||||||
priority: null,
|
priority: null,
|
||||||
button: {
|
button: { size: "btn-sm", class: "btn-submit" },
|
||||||
size: "btn-sm",
|
}));
|
||||||
class: "btn-submit",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
translatedListOfTypes() {
|
|
||||||
if (this.label !== "") {
|
|
||||||
return this.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
let trans = [];
|
const translatedListOfTypes = computed(() => {
|
||||||
this.types.forEach((t) => {
|
if (props.label) return props.label;
|
||||||
if (this.$props.multiple) {
|
let trans = props.types.map((t) =>
|
||||||
trans.push(appMessages.fr.pick_entity[t].toLowerCase());
|
props.multiple
|
||||||
} else {
|
? appMessages.fr.pick_entity[t].toLowerCase()
|
||||||
trans.push(
|
: appMessages.fr.pick_entity[t + "_one"].toLowerCase(),
|
||||||
appMessages.fr.pick_entity[t + "_one"].toLowerCase(),
|
|
||||||
);
|
);
|
||||||
}
|
return props.multiple
|
||||||
});
|
? appMessages.fr.pick_entity.modal_title + trans.join(", ")
|
||||||
|
: appMessages.fr.pick_entity.modal_title_one + trans.join(", ");
|
||||||
|
});
|
||||||
|
|
||||||
if (this.$props.multiple) {
|
const listClasses = computed(() => ({
|
||||||
return (
|
|
||||||
appMessages.fr.pick_entity.modal_title + trans.join(", ")
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
appMessages.fr.pick_entity.modal_title_one +
|
|
||||||
trans.join(", ")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
listClasses() {
|
|
||||||
return {
|
|
||||||
"list-suggest": true,
|
"list-suggest": true,
|
||||||
"remove-items": this.$props.removableIfSet,
|
"remove-items": props.removableIfSet,
|
||||||
};
|
}));
|
||||||
},
|
|
||||||
},
|
const selectItsMe = (event) =>
|
||||||
methods: {
|
event.target.checked ? addNewSuggested("me") : removeEntity("me");
|
||||||
addNewSuggested(entity) {
|
|
||||||
this.$emit("addNewEntity", { entity: entity });
|
const addNewSuggested = (entity) => {
|
||||||
},
|
emit("addNewEntity", { entity });
|
||||||
addNewEntity({ selected, modal }) {
|
};
|
||||||
selected.forEach((item) => {
|
|
||||||
this.$emit("addNewEntity", { entity: item.result });
|
const addNewEntity = ({ selected, modal }) => {
|
||||||
}, this);
|
selected.forEach((item) => emit("addNewEntity", { entity: item.result }));
|
||||||
this.$refs.addPersons.resetSearch(); // to cast child method
|
addPersons.value?.resetSearch();
|
||||||
modal.showModal = false;
|
modal.showModal = false;
|
||||||
this.$emit("addNewEntityProcessEnded");
|
emit("addNewEntityProcessEnded");
|
||||||
},
|
};
|
||||||
removeEntity(entity) {
|
|
||||||
if (!this.$props.removableIfSet) {
|
const removeEntity = (entity) => {
|
||||||
return;
|
if (!props.removableIfSet) return;
|
||||||
|
if (entity === "me" && itsMeCheckbox.value) {
|
||||||
|
itsMeCheckbox.value.checked = false;
|
||||||
}
|
}
|
||||||
this.$emit("removeEntity", { entity: entity });
|
emit("removeEntity", { entity });
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.current-user {
|
||||||
|
color: var(--bs-body-color);
|
||||||
|
background-color: var(--bs-chill-l-gray) !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@@ -46,8 +46,9 @@ const onPickGenericDoc = ({
|
|||||||
emit("pickGenericDoc", { genericDoc });
|
emit("pickGenericDoc", { genericDoc });
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRemoveAttachment = (payload: { attachment: WorkflowAttachment }) => { emit('removeAttachment', payload) };
|
const onRemoveAttachment = (payload: { attachment: WorkflowAttachment }) => {
|
||||||
|
emit("removeAttachment", payload);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@@ -72,9 +72,13 @@ const placeTrans = (str: string): string => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPickDocument = (payload: { genericDoc: GenericDocForAccompanyingPeriod }) => emit('pickGenericDoc', payload);
|
const onPickDocument = (payload: {
|
||||||
|
genericDoc: GenericDocForAccompanyingPeriod;
|
||||||
|
}) => emit("pickGenericDoc", payload);
|
||||||
|
|
||||||
const onRemoveGenericDoc = (payload: {genericDoc: GenericDocForAccompanyingPeriod}) => emit('removeGenericDoc', 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) {
|
||||||
@@ -250,9 +254,7 @@ const filteredDocuments = computed<GenericDocForAccompanyingPeriod[]>(() => {
|
|||||||
:genericDoc="g"
|
:genericDoc="g"
|
||||||
:is-picked="isPicked(g)"
|
:is-picked="isPicked(g)"
|
||||||
@pickGenericDoc="onPickDocument"
|
@pickGenericDoc="onPickDocument"
|
||||||
@removeGenericDoc="
|
@removeGenericDoc="onRemoveGenericDoc"
|
||||||
onRemoveGenericDoc
|
|
||||||
"
|
|
||||||
></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">
|
||||||
|
@@ -49,6 +49,7 @@ Name: Nom
|
|||||||
Label: Nom
|
Label: Nom
|
||||||
|
|
||||||
user:
|
user:
|
||||||
|
current_user: Utilisateur courant
|
||||||
profile:
|
profile:
|
||||||
title: Mon profil
|
title: Mon profil
|
||||||
Phonenumber successfully updated!: Numéro de téléphone mis à jour!
|
Phonenumber successfully updated!: Numéro de téléphone mis à jour!
|
||||||
|
@@ -13,7 +13,7 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
|||||||
|
|
||||||
use Chill\MainBundle\Export\FilterInterface;
|
use Chill\MainBundle\Export\FilterInterface;
|
||||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
|
use Chill\MainBundle\Form\Type\PickUserOrMeDynamicType;
|
||||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||||
use Chill\PersonBundle\Export\Declarations;
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
@@ -66,7 +66,7 @@ class ReferrerFilter implements FilterInterface
|
|||||||
public function buildForm(FormBuilderInterface $builder)
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
{
|
{
|
||||||
$builder
|
$builder
|
||||||
->add('accepted_referrers', PickUserDynamicType::class, [
|
->add('accepted_referrers', PickUserOrMeDynamicType::class, [
|
||||||
'multiple' => true,
|
'multiple' => true,
|
||||||
])
|
])
|
||||||
->add('date_calc', PickRollingDateType::class, [
|
->add('date_calc', PickRollingDateType::class, [
|
||||||
|
Reference in New Issue
Block a user