mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 01:08:26 +00:00 
			
		
		
		
	Compare commits
	
		
			4 Commits
		
	
	
		
			321-text-e
			...
			362-bug-ma
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 499aa3adea | |||
| b597ff89e0 | |||
| 3c801a6d0e | |||
| 4093949c2f | 
							
								
								
									
										6
									
								
								.changes/unreleased/DX-20250131-131801.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/DX-20250131-131801.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: DX | ||||
| body: Create an unique source of trust for translations | ||||
| time: 2025-01-31T13:18:01.239211506+01:00 | ||||
| custom: | ||||
|     Issue: "333" | ||||
|     SchemaChange: No schema change | ||||
| @@ -1,6 +0,0 @@ | ||||
| kind: DX | ||||
| body: Remove dead code for wopi-link module | ||||
| time: 2025-04-30T14:45:50.406111606+02:00 | ||||
| custom: | ||||
|     Issue: "352" | ||||
|     SchemaChange: No schema change | ||||
							
								
								
									
										6
									
								
								.changes/unreleased/Feature-20250130-120207.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/Feature-20250130-120207.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: Feature | ||||
| body: Suggest all referrers within actions of the accompanying period when creating an activity | ||||
| time: 2025-01-30T12:02:07.053587034+01:00 | ||||
| custom: | ||||
|     Issue: "349" | ||||
|     SchemaChange: No schema change | ||||
							
								
								
									
										6
									
								
								.changes/unreleased/Feature-20250130-120459.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/Feature-20250130-120459.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: Feature | ||||
| body: Add possibility to export a csv with all social issues and social actions | ||||
| time: 2025-01-30T12:04:59.754998541+01:00 | ||||
| custom: | ||||
|     Issue: "343" | ||||
|     SchemaChange: No schema change | ||||
							
								
								
									
										6
									
								
								.changes/unreleased/Feature-20250214-150328.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/Feature-20250214-150328.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: Feature | ||||
| body: Restore document to previous kept version when a workflow is canceled | ||||
| time: 2025-02-14T15:03:28.707250207+01:00 | ||||
| custom: | ||||
|     Issue: "360" | ||||
|     SchemaChange: No schema change | ||||
							
								
								
									
										6
									
								
								.changes/unreleased/Feature-20250219-120928.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/Feature-20250219-120928.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: Feature | ||||
| body: Add a list of third parties from within the admin (csv download) | ||||
| time: 2025-02-19T12:09:28.487991703+01:00 | ||||
| custom: | ||||
|     Issue: "341" | ||||
|     SchemaChange: No schema change | ||||
| @@ -1,7 +0,0 @@ | ||||
| kind: Feature | ||||
| body: Add the document file name to the document title when a user upload a document, | ||||
|   unless there is already a document title. | ||||
| time: 2025-04-24T14:22:11.800975422+02:00 | ||||
| custom: | ||||
|   Issue: "377" | ||||
|   SchemaChange: No schema change | ||||
| @@ -1,6 +0,0 @@ | ||||
| kind: Feature | ||||
| body: Add desactivation date for social action and issue csv export | ||||
| time: 2025-05-20T09:56:28.108941934+02:00 | ||||
| custom: | ||||
|     Issue: "" | ||||
|     SchemaChange: No schema change | ||||
							
								
								
									
										6
									
								
								.changes/unreleased/Fixed-20250214-121010.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/Fixed-20250214-121010.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: Fixed | ||||
| body: fix generation of document with accompanying period context, and list of activities and works | ||||
| time: 2025-02-14T12:10:10.920355454+01:00 | ||||
| custom: | ||||
|     Issue: "" | ||||
|     SchemaChange: No schema change | ||||
| @@ -1,7 +0,0 @@ | ||||
| kind: Fixed | ||||
| body: trying to prevent bug of typeerror in doc-history + improved display of document | ||||
|   history | ||||
| time: 2025-04-24T13:39:43.878468232+02:00 | ||||
| custom: | ||||
|   Issue: "376" | ||||
|   SchemaChange: No schema change | ||||
| @@ -1,7 +0,0 @@ | ||||
| kind: Fixed | ||||
| body: Display previous participation in acc course work even if the person has left | ||||
|   the acc course | ||||
| time: 2025-04-24T16:37:46.970203594+02:00 | ||||
| custom: | ||||
|   Issue: "381" | ||||
|   SchemaChange: No schema change | ||||
| @@ -1,6 +0,0 @@ | ||||
| kind: Fixed | ||||
| body: Fix display of text in calendar events | ||||
| time: 2025-05-05T10:27:15.461493066+02:00 | ||||
| custom: | ||||
|     Issue: "372" | ||||
|     SchemaChange: No schema change | ||||
| @@ -1,6 +0,0 @@ | ||||
| kind: Fixed | ||||
| body: Add missing translation for user_group.no_user_groups | ||||
| time: 2025-05-14T14:53:39.53927329+02:00 | ||||
| custom: | ||||
|     Issue: "" | ||||
|     SchemaChange: No schema change | ||||
| @@ -1,6 +0,0 @@ | ||||
| kind: UX | ||||
| body: Remove default filter in_progress for the page 'my tasks'; Allows for new tasks to be displayed upon opening of the page | ||||
| time: 2025-04-23T17:26:24.45777387+02:00 | ||||
| custom: | ||||
|     Issue: "374" | ||||
|     SchemaChange: No schema change | ||||
| @@ -1,6 +0,0 @@ | ||||
| ## 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    | ||||
| @@ -1,3 +0,0 @@ | ||||
| ## v3.10.1 - 2025-03-17 | ||||
| ### DX | ||||
| * Remove yarn dependency to symfony/ux-translator, to ease the build process | ||||
| @@ -1,3 +0,0 @@ | ||||
| ## v3.10.2 - 2025-03-17 | ||||
| ### Fixed | ||||
| * Replace a ts-expect-error with a ts-ignore    | ||||
| @@ -1,3 +0,0 @@ | ||||
| ## v3.10.3 - 2025-03-18 | ||||
| ### DX | ||||
| * Eslint fixes    | ||||
| @@ -1,19 +0,0 @@ | ||||
| ## v3.11.0 - 2025-04-17 | ||||
| ### Feature | ||||
| * ([#365](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/365)) Add counters of actions and activities, with 2 boxes to (1) show the number of active actions on total actions and (2) show the number of activities in a accompanying period, and pills in menus for showing the number of active actions and the number of activities. | ||||
| * ([#364](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/364)) Added a second phone number "telephone2" to the thirdParty entity. Adapted twig templates and vuejs apps to handle this phone number | ||||
|  | ||||
|   **Schema Change**: Add columns or tables | ||||
| * Signature: add a button to go directly to the signature zone, even if there is only one | ||||
| ### Fixed | ||||
| * Fixed wrong translations in the on-the-fly for creation of thirdParty | ||||
| * Fixed update of phone number in on-the-fly edition of thirdParty | ||||
| * Fixed closing of modal when editing thirdParty in accompanying course works | ||||
| * Shorten the delay between two execution of AccompanyingPeriodStepChangeCronjob, to ensure at least one execution in a day | ||||
| * ([#102](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/102)) Fix display of title in document list | ||||
| * When cleaning the old stored object versions, do not throw an error if the stored object is not found on disk | ||||
| * Add consistent log prefix and key to logs when stale workflows are automatically canceled | ||||
| * ([#380](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/380)) Remove the "not null" validation constraint on recently added properties on HouseholdComposition | ||||
|  | ||||
| ### DX | ||||
| * Add new chill-col style for displaying title and aside in a flex table | ||||
| @@ -1,10 +0,0 @@ | ||||
| ## 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    | ||||
| @@ -1,3 +0,0 @@ | ||||
| ## v3.9.1 - 2025-02-27 | ||||
| ### Fixed | ||||
| * Fix post/patch request with missing 'type' property for gender    | ||||
| @@ -1,3 +0,0 @@ | ||||
| ## v3.9.2 - 2025-02-27 | ||||
| ### Fixed | ||||
| * Use fetchResults method to fetch all social issues instead of only the first page    | ||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -13,7 +13,6 @@ docker/rabbitmq/data | ||||
| # in this development bundle, we want to ignore directories related to a real app | ||||
| assets/* | ||||
| !assets/translator.ts | ||||
| !assets/ux-translator | ||||
| migrations/* | ||||
| templates/* | ||||
| translations/* | ||||
|   | ||||
							
								
								
									
										38
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -6,44 +6,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), | ||||
| 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    | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| import { trans, setLocale, setLocaleFallbacks } from "./ux-translator"; | ||||
| // @ts-ignore Cannot find module (when used within an app) | ||||
| import { trans, getLocale, setLocale, setLocaleFallbacks } from "@symfony/ux-translator"; | ||||
|  | ||||
| setLocaleFallbacks({"en": "fr", "nl": "fr", "fr": "en"}); | ||||
| setLocale('fr'); | ||||
|  | ||||
| export { trans }; | ||||
| // @ts-ignore Cannot find module (when used within an app) | ||||
| export * from '../var/translations'; | ||||
|   | ||||
| @@ -1,3 +0,0 @@ | ||||
| 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 +0,0 @@ | ||||
| export declare function format(id: string, parameters: Record<string, string | number>, locale: string): string; | ||||
| @@ -1 +0,0 @@ | ||||
| export declare function formatIntl(id: string, parameters: Record<string, string | number>, locale: string): string; | ||||
							
								
								
									
										27
									
								
								assets/ux-translator/dist/translator.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								assets/ux-translator/dist/translator.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1,27 +0,0 @@ | ||||
| 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 +0,0 @@ | ||||
| export * from './translator'; | ||||
							
								
								
									
										283
									
								
								assets/ux-translator/dist/translator_controller.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										283
									
								
								assets/ux-translator/dist/translator_controller.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,283 +0,0 @@ | ||||
| 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
									
									
								
							
							
						
						
									
										1
									
								
								assets/ux-translator/dist/utils.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | ||||
| export declare function strtr(string: string, replacePairs: Record<string, string | number>): string; | ||||
| @@ -1,34 +0,0 @@ | ||||
| { | ||||
|     "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" | ||||
|     } | ||||
| } | ||||
| @@ -220,7 +220,6 @@ framework: | ||||
|                         - attenteModification | ||||
|                         - attenteMiseEnForme | ||||
|                         - attenteValidationMiseEnForme | ||||
|                         - attenteSignature | ||||
|                         - attenteVisa | ||||
|                         - postSignature | ||||
|                         - attenteTraitement | ||||
|   | ||||
| @@ -34,7 +34,6 @@ export default ts.config( | ||||
|             // override/add rules settings here, such as: | ||||
|             "vue/multi-word-component-names": "off", | ||||
|             "@typescript-eslint/no-require-imports": "off", | ||||
|             "@typescript-eslint/ban-ts-comment": "off" | ||||
|         }, | ||||
|     }, | ||||
| ); | ||||
|   | ||||
| @@ -59,7 +59,6 @@ | ||||
|     "bootstrap-icons": "^1.11.3", | ||||
|     "dropzone": "^5.7.6", | ||||
|     "es6-promise": "^4.2.8", | ||||
|     "intl-messageformat": "^10.5.11", | ||||
|     "leaflet": "^1.7.1", | ||||
|     "marked": "^12.0.2", | ||||
|     "masonry-layout": "^4.2.2", | ||||
|   | ||||
| @@ -11,7 +11,6 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\ActivityBundle\Menu; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\MainBundle\Routing\LocalMenuBuilderInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| @@ -24,30 +23,22 @@ use Symfony\Contracts\Translation\TranslatorInterface; | ||||
|  */ | ||||
| class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface | ||||
| { | ||||
|     public function __construct( | ||||
|         protected Security $security, | ||||
|         protected TranslatorInterface $translator, | ||||
|         private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, | ||||
|     ) {} | ||||
|     public function __construct(protected Security $security, protected TranslatorInterface $translator) {} | ||||
|  | ||||
|     public function buildMenu($menuId, MenuItem $menu, array $parameters) | ||||
|     { | ||||
|         $period = $parameters['accompanyingCourse']; | ||||
|  | ||||
|         $activities = $this->managerRegistry->getManager()->getRepository(Activity::class)->findBy( | ||||
|             ['accompanyingPeriod' => $period] | ||||
|         ); | ||||
|  | ||||
|         if ( | ||||
|             AccompanyingPeriod::STEP_DRAFT !== $period->getStep() | ||||
|             && $this->security->isGranted(ActivityVoter::SEE, $period) | ||||
|         ) { | ||||
|             $menu->addChild($this->translator->trans('Activities'), [ | ||||
|             $menu->addChild($this->translator->trans('Activity'), [ | ||||
|                 'route' => 'chill_activity_activity_list', | ||||
|                 'routeParameters' => [ | ||||
|                     'accompanying_period_id' => $period->getId(), | ||||
|                 ], ]) | ||||
|                 ->setExtras(['order' => 40, 'counter' => count($activities) > 0 ? count($activities) : null]); | ||||
|                 ->setExtras(['order' => 40]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,6 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\ActivityBundle\Menu; | ||||
|  | ||||
| use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\MainBundle\Routing\LocalMenuBuilderInterface; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| @@ -24,20 +23,13 @@ use Symfony\Contracts\Translation\TranslatorInterface; | ||||
|  */ | ||||
| final readonly class PersonMenuBuilder implements LocalMenuBuilderInterface | ||||
| { | ||||
|     public function __construct( | ||||
|         private readonly ActivityACLAwareRepositoryInterface $activityACLAwareRepository, | ||||
|         private AuthorizationCheckerInterface $authorizationChecker, | ||||
|         private TranslatorInterface $translator, | ||||
|     ) {} | ||||
|     public function __construct(private AuthorizationCheckerInterface $authorizationChecker, private TranslatorInterface $translator) {} | ||||
|  | ||||
|     public function buildMenu($menuId, MenuItem $menu, array $parameters) | ||||
|     { | ||||
|         /** @var Person $person */ | ||||
|         $person = $parameters['person']; | ||||
|  | ||||
|  | ||||
|         $count = $this->activityACLAwareRepository->countByPerson($person, ActivityVoter::SEE); | ||||
|  | ||||
|         if ($this->authorizationChecker->isGranted(ActivityVoter::SEE, $person)) { | ||||
|             $menu->addChild( | ||||
|                 $this->translator->trans('Activities'), | ||||
| @@ -46,7 +38,7 @@ final readonly class PersonMenuBuilder implements LocalMenuBuilderInterface | ||||
|                     'routeParameters' => ['person_id' => $person->getId()], | ||||
|                 ] | ||||
|             ) | ||||
|                 ->setExtras(['order' => 201, 'counter' => $count > 0 ? $count : null]); | ||||
|                 ->setExtra('order', 201); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -120,34 +120,3 @@ li.document-list-item { | ||||
|         vertical-align: baseline; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .badge-activity-type-simple { | ||||
|     @extend .badge; | ||||
|     display: inline-block; | ||||
|     margin: 0.2rem 0; | ||||
|     padding-left: 0; | ||||
|     padding-right: 0.5rem; | ||||
|  | ||||
|     border-left: 20px groove #9acd32; | ||||
|     border-radius: $badge-border-radius; | ||||
|  | ||||
|     color: black; | ||||
|     font-weight: normal; | ||||
|     font-size: unset; | ||||
|     max-width: 100%; | ||||
|     background-color: $gray-100; | ||||
|  | ||||
|     overflow: hidden; | ||||
|     text-overflow: ellipsis; | ||||
|     text-indent: 5px hanging; | ||||
|     text-align: left; | ||||
|  | ||||
|     &::before { | ||||
|         margin-right: 3px; | ||||
|         position: relative; | ||||
|         left: -0.5px; | ||||
|         font-family: ForkAwesome; | ||||
|         content: '\f04b'; | ||||
|         color: #9acd32; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import Location from "./components/Location.vue"; | ||||
|  | ||||
| export default { | ||||
|     name: "App", | ||||
|     props: ["hasSocialIssues", "hasLocation", "hasPerson", "isSimpleEditor"], | ||||
|     props: ["hasSocialIssues", "hasLocation", "hasPerson"], | ||||
|     components: { | ||||
|         ConcernedGroups, | ||||
|         SocialIssuesAcc, | ||||
|   | ||||
| @@ -68,23 +68,14 @@ | ||||
|                             socialActionsSelected.length) | ||||
|                     " | ||||
|                 > | ||||
|                     <div | ||||
|                         id="actionsList" | ||||
|                         v-for="group in socialActionsList" | ||||
|                         :key="group.issue" | ||||
|                     <check-social-action | ||||
|                         v-for="action in socialActionsList" | ||||
|                         :key="action.id" | ||||
|                         :action="action" | ||||
|                         :selection="socialActionsSelected" | ||||
|                         @updateSelected="updateActionsSelected" | ||||
|                     > | ||||
|                         <span class="badge bg-chill-l-gray text-dark">{{ | ||||
|                             group.issue | ||||
|                         }}</span> | ||||
|                         <check-social-action | ||||
|                             v-for="action in group.actions" | ||||
|                             :key="action.id" | ||||
|                             :action="action" | ||||
|                             :selection="socialActionsSelected" | ||||
|                             @updateSelected="updateActionsSelected" | ||||
|                         > | ||||
|                         </check-social-action> | ||||
|                     </div> | ||||
|                     </check-social-action> | ||||
|                 </template> | ||||
|  | ||||
|                 <span | ||||
| @@ -158,44 +149,53 @@ export default { | ||||
|         }, | ||||
|     }, | ||||
|     mounted() { | ||||
|         /* Load other issues in multiselect */ | ||||
|         /* Load others issues in multiselect | ||||
|          */ | ||||
|         this.issueIsLoading = true; | ||||
|         this.actionAreLoaded = false; | ||||
|         getSocialIssues().then( | ||||
|             (response) => | ||||
|                 new Promise((resolve) => { | ||||
|                     this.$store.commit("updateIssuesOther", response.results); | ||||
|  | ||||
|         getSocialIssues().then((response) => { | ||||
|             /* Add issues to the store */ | ||||
|             this.$store.commit("updateIssuesOther", response); | ||||
|                     /* Add in list the issues already associated (if not yet listed) | ||||
|                      */ | ||||
|                     this.socialIssuesSelected.forEach((issue) => { | ||||
|                         if ( | ||||
|                             this.socialIssuesList.filter( | ||||
|                                 (i) => i.id === issue.id, | ||||
|                             ).length !== 1 | ||||
|                         ) { | ||||
|                             this.$store.commit("addIssueInList", issue); | ||||
|                         } | ||||
|                     }, this); | ||||
|  | ||||
|             /* Add in list the issues already associated (if not yet listed) */ | ||||
|             this.socialIssuesSelected.forEach((issue) => { | ||||
|                 if ( | ||||
|                     this.socialIssuesList.filter((i) => i.id === issue.id) | ||||
|                         .length !== 1 | ||||
|                 ) { | ||||
|                     this.$store.commit("addIssueInList", issue); | ||||
|                 } | ||||
|             }); | ||||
|                     /* Remove from multiselect the issues that are not yet in checkbox list | ||||
|                      */ | ||||
|                     this.socialIssuesList.forEach((issue) => { | ||||
|                         this.$store.commit("removeIssueInOther", issue); | ||||
|                     }, this); | ||||
|  | ||||
|             /* Remove from multiselect the issues that are not yet in the checkbox list */ | ||||
|             this.socialIssuesList.forEach((issue) => { | ||||
|                 this.$store.commit("removeIssueInOther", issue); | ||||
|             }); | ||||
|                     /* Filter issues | ||||
|                      */ | ||||
|                     this.$store.commit("filterList", "issues"); | ||||
|  | ||||
|             /* Filter issues */ | ||||
|             this.$store.commit("filterList", "issues"); | ||||
|                     /* Add in list the actions already associated (if not yet listed) | ||||
|                      */ | ||||
|                     this.socialActionsSelected.forEach((action) => { | ||||
|                         this.$store.commit("addActionInList", action); | ||||
|                     }, this); | ||||
|  | ||||
|             /* Add in list the actions already associated (if not yet listed) */ | ||||
|             this.socialActionsSelected.forEach((action) => { | ||||
|                 this.$store.commit("addActionInList", action); | ||||
|             }); | ||||
|                     /* Filter issues | ||||
|                      */ | ||||
|                     this.$store.commit("filterList", "actions"); | ||||
|  | ||||
|             /* Filter actions */ | ||||
|             this.$store.commit("filterList", "actions"); | ||||
|  | ||||
|             this.issueIsLoading = false; | ||||
|             this.actionAreLoaded = true; | ||||
|             this.updateActionsList(); | ||||
|         }); | ||||
|                     this.issueIsLoading = false; | ||||
|                     this.actionAreLoaded = true; | ||||
|                     this.updateActionsList(); | ||||
|                     resolve(); | ||||
|                 }), | ||||
|         ); | ||||
|     }, | ||||
|     methods: { | ||||
|         /* When choosing an issue in multiselect, add it in checkboxes (as selected), | ||||
| @@ -258,23 +258,7 @@ export default { | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| @import "ChillMainAssets/module/bootstrap/shared"; | ||||
| @import "ChillPersonAssets/chill/scss/mixins"; | ||||
| @import "ChillMainAssets/chill/scss/chill_variables"; | ||||
|  | ||||
| span.multiselect__single { | ||||
|     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> | ||||
|   | ||||
| @@ -10,9 +10,7 @@ | ||||
|                 :value="action" | ||||
|             /> | ||||
|             <label class="form-check-label" :for="action.id"> | ||||
|                 <span class="badge bg-light text-dark" :title="action.text">{{ | ||||
|                     action.text | ||||
|                 }}</span> | ||||
|                 <span class="badge bg-light text-dark">{{ action.text }}</span> | ||||
|             </label> | ||||
|         </div> | ||||
|     </span> | ||||
| @@ -45,9 +43,5 @@ span.badge { | ||||
|     font-size: 95%; | ||||
|     margin-bottom: 5px; | ||||
|     margin-right: 1em; | ||||
|     max-width: 100%; /* Adjust as needed */ | ||||
|     overflow: hidden; | ||||
|     text-overflow: ellipsis; | ||||
|     white-space: nowrap; | ||||
| } | ||||
| </style> | ||||
|   | ||||
| @@ -14,21 +14,18 @@ const i18n = _createI18n(activityMessages); | ||||
| const hasSocialIssues = document.querySelector("#social-issues-acc") !== null; | ||||
| const hasLocation = document.querySelector("#location") !== null; | ||||
| const hasPerson = document.querySelector("#add-persons") !== null; | ||||
| const isSimpleEditor = true; | ||||
|  | ||||
| const app = createApp({ | ||||
|   template: `<app | ||||
|        :hasSocialIssues="hasSocialIssues" | ||||
|        :hasLocation="hasLocation" | ||||
|        :hasPerson="hasPerson" | ||||
|        :isSimpleEditor = "isSimpleEditor" | ||||
|     ></app>`, | ||||
|   data() { | ||||
|     return { | ||||
|       hasSocialIssues, | ||||
|       hasLocation, | ||||
|       hasPerson, | ||||
|       isSimpleEditor | ||||
|     }; | ||||
|   }, | ||||
| }) | ||||
|   | ||||
| @@ -124,19 +124,9 @@ const store = createStore({ | ||||
|         ); | ||||
|     }, | ||||
|     socialActionsListSorted(state) { | ||||
|       return [...state.socialActionsList] | ||||
|         .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; | ||||
|         }, []); | ||||
|       return [...state.socialActionsList].sort( | ||||
|         (a, b) => a.ordering - b.ordering, | ||||
|       ); | ||||
|     }, | ||||
|   }, | ||||
|   mutations: { | ||||
|   | ||||
| @@ -126,4 +126,4 @@ | ||||
|  | ||||
| {% block css %} | ||||
|     {{ encore_entry_link_tags('mod_pickentity_type') }} | ||||
| {% endblock %} | ||||
| {% endblock %} | ||||
| @@ -13,44 +13,44 @@ | ||||
| {% endif %} | ||||
|  | ||||
| <div class="item-row"> | ||||
|     <div class="item-two-col-grid"> | ||||
|         <div class="title"> | ||||
|             {% if document.isPending %} | ||||
|                 <div class="badge text-bg-info" data-docgen-is-pending="{{ document.id }}">{{ 'docgen.Doc generation is pending'|trans }}</div> | ||||
|             {% elseif document.isFailure %} | ||||
|                 <div class="badge text-bg-warning">{{ 'docgen.Doc generation failed'|trans }}</div> | ||||
|             {% endif %} | ||||
|     <div class="item-col" style="width: unset"> | ||||
|         {% if document.isPending %} | ||||
|             <div class="badge text-bg-info" data-docgen-is-pending="{{ document.id }}">{{ 'docgen.Doc generation is pending'|trans }}</div> | ||||
|         {% elseif document.isFailure %} | ||||
|             <div class="badge text-bg-warning">{{ 'docgen.Doc generation failed'|trans }}</div> | ||||
|         {% endif %} | ||||
|  | ||||
|             <div> | ||||
|                 <div> | ||||
|                     <div class="badge-activity-type-simple"> | ||||
|                         {{ activity.type.name | localize_translatable_string }} | ||||
|                     </div> | ||||
|         <div> | ||||
|             {% if activity.accompanyingPeriod is not null and context == 'person' %} | ||||
|                 <span class="badge bg-primary"> | ||||
|                         <i class="fa fa-random"></i> {{ activity.accompanyingPeriod.id }} | ||||
|                     </span>  | ||||
|             {% endif %} | ||||
|             <div class="badge-activity-type"> | ||||
|                 <span class="title_label"></span> | ||||
|                 <span class="title_action"> | ||||
|                     {{ activity.type.name | localize_translatable_string }} | ||||
|                     {% if activity.emergency %} | ||||
|                         <span class="badge bg-danger rounded-pill fs-6 float-end">{{ 'Emergency'|trans|upper }}</span> | ||||
|                     {% endif %} | ||||
|                 </div> | ||||
|                     </span> | ||||
|             </div> | ||||
|             <div class="denomination h2"> | ||||
|                 {{ document.title|chill_print_or_message("No title") }} | ||||
|             </div> | ||||
|             {% if document.hasTemplate %} | ||||
|                 <div> | ||||
|                     <p>{{ document.template.name|localize_translatable_string }}</p> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|         </div> | ||||
|         <div class="aside"> | ||||
|         <div class="denomination h2"> | ||||
|             {{ document.title|chill_print_or_message("No title") }} | ||||
|         </div> | ||||
|         {% if document.hasTemplate %} | ||||
|             <div> | ||||
|                 <p>{{ document.template.name|localize_translatable_string }}</p> | ||||
|             </div> | ||||
|         {% endif %} | ||||
|     </div> | ||||
|  | ||||
|     <div class="item-col"> | ||||
|         <div class="container"> | ||||
|             <div class="dates row text-end"> | ||||
|                 <span>{{ document.createdAt|format_date('short') }}</span> | ||||
|             </div> | ||||
|             {% if activity.accompanyingPeriod is not null and context == 'person' %} | ||||
|                 <div class="text-end"> | ||||
|                     <span class="badge bg-primary"> | ||||
|                         <i class="fa fa-random"></i> {{ activity.accompanyingPeriod.id }} | ||||
|                     </span>  | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|   | ||||
| @@ -15,6 +15,7 @@ use Chill\CalendarBundle\Repository\CalendarRepository; | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Chill\MainBundle\Entity\User; | ||||
| use Chill\MainBundle\Serializer\Model\Collection; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| @@ -23,7 +24,10 @@ use Symfony\Component\Routing\Annotation\Route; | ||||
|  | ||||
| class CalendarAPIController extends ApiController | ||||
| { | ||||
|     public function __construct(private readonly CalendarRepository $calendarRepository) {} | ||||
|     public function __construct(private readonly CalendarRepository $calendarRepository, ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     #[Route(path: '/api/1.0/calendar/calendar/by-user/{id}.{_format}', name: 'chill_api_single_calendar_list_by-user', requirements: ['_format' => 'json'])] | ||||
|     public function listByUser(User $user, Request $request, string $_format): JsonResponse | ||||
|   | ||||
| @@ -15,6 +15,7 @@ use Chill\CalendarBundle\Repository\CalendarRangeRepository; | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Chill\MainBundle\Entity\User; | ||||
| use Chill\MainBundle\Serializer\Model\Collection; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| @@ -23,7 +24,10 @@ use Symfony\Component\Routing\Annotation\Route; | ||||
|  | ||||
| class CalendarRangeAPIController extends ApiController | ||||
| { | ||||
|     public function __construct(private readonly CalendarRangeRepository $calendarRangeRepository) {} | ||||
|     public function __construct(private readonly CalendarRangeRepository $calendarRangeRepository, ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     #[Route(path: '/api/1.0/calendar/calendar-range-available/{id}.{_format}', name: 'chill_api_single_calendar_range_available', requirements: ['_format' => 'json'])] | ||||
|     public function availableRanges(User $user, Request $request, string $_format): JsonResponse | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| @import '~ChillMainAssets/module/bootstrap/shared'; | ||||
| @import '~ChillPersonAssets/chill/scss/mixins.scss'; | ||||
| @import 'bootstrap/scss/_badge.scss'; | ||||
| @import '~ChillMainAssets/module/bootstrap/shared'; | ||||
|  | ||||
| .badge-calendar { | ||||
|     display: inline-block; | ||||
| @@ -24,35 +23,3 @@ | ||||
|     } | ||||
| } | ||||
|  | ||||
| .badge-calendar-simple { | ||||
|     @extend .badge; | ||||
|     display: inline-block; | ||||
|     margin: 0.2rem 0; | ||||
|     padding-left: 0; | ||||
|     padding-right: 0.5rem; | ||||
|  | ||||
|     border-left: 20px groove $chill-l-gray; | ||||
|     border-radius: $badge-border-radius; | ||||
|  | ||||
|     max-width: 100%; | ||||
|     background-color: $gray-100; | ||||
|  | ||||
|     color: black; | ||||
|     font-weight: normal; | ||||
|     overflow: hidden; | ||||
|     font-weight: normal; | ||||
|     font-size: unset; | ||||
|     text-overflow: ellipsis; | ||||
|     text-indent: 5px hanging; | ||||
|     text-align: left; | ||||
|  | ||||
|     &::before { | ||||
|         margin-right: 3px; | ||||
|         position: relative; | ||||
|         left: -0.5px; | ||||
|         font-family: ForkAwesome; | ||||
|         content: '\f04b'; | ||||
|         color: $chill-l-gray; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,7 @@ div.calendar-list { | ||||
|     } | ||||
|  | ||||
|     & > a.calendar-list__global { | ||||
|         display: inline-block; | ||||
|         display: inline-block;; | ||||
|         padding: 0.2rem; | ||||
|         min-width: 2rem; | ||||
|         border: 1px solid var(--bs-chill-blue); | ||||
|   | ||||
| @@ -96,23 +96,23 @@ | ||||
|         </div> | ||||
|     </div> | ||||
|     <FullCalendar :options="calendarOptions" ref="calendarRef"> | ||||
|         <template v-slot:eventContent="{ event }"> | ||||
|             <span :class="eventClasses(event)"> | ||||
|                 <b v-if="event.extendedProps.is === 'remote'">{{ | ||||
|                     event.title | ||||
|         <template v-slot:eventContent="arg: EventApi"> | ||||
|             <span :class="eventClasses(arg.event)"> | ||||
|                 <b v-if="arg.event.extendedProps.is === 'remote'">{{ | ||||
|                     arg.event.title | ||||
|                 }}</b> | ||||
|                 <b v-else-if="event.extendedProps.is === 'range'" | ||||
|                     >{{ formatDate(event.startStr) }} - | ||||
|                     {{ event.extendedProps.locationName }}</b | ||||
|                 <b v-else-if="arg.event.extendedProps.is === 'range'" | ||||
|                     >{{ arg.timeText }} - | ||||
|                     {{ arg.event.extendedProps.locationName }}</b | ||||
|                 > | ||||
|                 <b v-else-if="event.extendedProps.is === 'local'">{{ | ||||
|                     event.title | ||||
|                 <b v-else-if="arg.event.extendedProps.is === 'local'">{{ | ||||
|                     arg.event.title | ||||
|                 }}</b> | ||||
|                 <b v-else>no 'is'</b> | ||||
|                 <a | ||||
|                     v-if="event.extendedProps.is === 'range'" | ||||
|                     v-if="arg.event.extendedProps.is === 'range'" | ||||
|                     class="fa fa-fw fa-times delete" | ||||
|                     @click.prevent="onClickDelete(event)" | ||||
|                     @click.prevent="onClickDelete(arg.event)" | ||||
|                 > | ||||
|                 </a> | ||||
|             </span> | ||||
| @@ -221,12 +221,13 @@ import type { | ||||
|     DatesSetArg, | ||||
|     EventInput, | ||||
| } from "@fullcalendar/core"; | ||||
| import { computed, ref, onMounted } from "vue"; | ||||
| import { reactive, computed, ref, onMounted } from "vue"; | ||||
| import { useStore } from "vuex"; | ||||
| import { key } from "./store"; | ||||
| import FullCalendar from "@fullcalendar/vue3"; | ||||
| import frLocale from "@fullcalendar/core/locales/fr"; | ||||
| import interactionPlugin, { | ||||
|     DropArg, | ||||
|     EventResizeDoneArg, | ||||
| } from "@fullcalendar/interaction"; | ||||
| import timeGridPlugin from "@fullcalendar/timegrid"; | ||||
| @@ -236,13 +237,19 @@ import { | ||||
|     EventDropArg, | ||||
|     EventClickArg, | ||||
| } from "@fullcalendar/core"; | ||||
| import { dateToISO, ISOToDate } from "ChillMainAssets/chill/js/date"; | ||||
| import { | ||||
|     dateToISO, | ||||
|     ISOToDate, | ||||
| } from "../../../../../ChillMainBundle/Resources/public/chill/js/date"; | ||||
| import VueMultiselect from "vue-multiselect"; | ||||
| import { Location } from "ChillMainAssets/types"; | ||||
| import { Location } from "../../../../../ChillMainBundle/Resources/public/types"; | ||||
| import EditLocation from "./Components/EditLocation.vue"; | ||||
| import { useI18n } from "vue-i18n"; | ||||
|  | ||||
| const store = useStore(key); | ||||
|  | ||||
| const { t } = useI18n(); | ||||
|  | ||||
| const showWeekends = ref(false); | ||||
| const slotDuration = ref("00:15:00"); | ||||
| const slotMinTime = ref("09:00:00"); | ||||
| @@ -294,11 +301,6 @@ const nextWeeks = computed((): Weeks[] => | ||||
|     }), | ||||
| ); | ||||
|  | ||||
| const formatDate = (datetime: string) => { | ||||
|     console.log(typeof datetime); | ||||
|     return ISOToDate(datetime); | ||||
| }; | ||||
|  | ||||
| const baseOptions = ref<CalendarOptions>({ | ||||
|     locale: frLocale, | ||||
|     plugins: [interactionPlugin, timeGridPlugin], | ||||
| @@ -351,7 +353,7 @@ const pickedLocation = computed<Location | null>({ | ||||
|  * return the show classes for the event | ||||
|  * @param arg | ||||
|  */ | ||||
| const eventClasses = function (): object { | ||||
| const eventClasses = function (arg: EventApi): object { | ||||
|     return { calendarRangeItems: true }; | ||||
| }; | ||||
|  | ||||
| @@ -429,6 +431,7 @@ function onEventDropOrResize(payload: EventDropArg | EventResizeDoneArg) { | ||||
|     if (payload.event.extendedProps.is !== "range") { | ||||
|         return; | ||||
|     } | ||||
|     const changedEvent = payload.event; | ||||
|  | ||||
|     store.dispatch("calendarRanges/patchRangeTime", { | ||||
|         calendarRangeId: payload.event.extendedProps.calendarRangeId, | ||||
|   | ||||
| @@ -6,48 +6,50 @@ | ||||
|  | ||||
|  | ||||
| <div class="item-row"> | ||||
|     <div class="item-two-col-grid"> | ||||
|         <div class="title"> | ||||
|             {% if document.storedObject.isPending %} | ||||
|                 <div class="badge text-bg-info" data-docgen-is-pending="{{ document.storedObject.id }}">{{ 'docgen.Doc generation is pending'|trans }}</div> | ||||
|             {% elseif document.storedObject.isFailure %} | ||||
|                 <div class="badge text-bg-warning">{{ 'docgen.Doc generation failed'|trans }}</div> | ||||
|     <div class="item-col" style="width: unset"> | ||||
|         {% if document.storedObject.isPending %} | ||||
|             <div class="badge text-bg-info" data-docgen-is-pending="{{ document.storedObject.id }}">{{ 'docgen.Doc generation is pending'|trans }}</div> | ||||
|         {% elseif document.storedObject.isFailure %} | ||||
|             <div class="badge text-bg-warning">{{ 'docgen.Doc generation failed'|trans }}</div> | ||||
|         {% endif %} | ||||
|  | ||||
|         <div> | ||||
|             {% if c.accompanyingPeriod is not null and context == 'person' %} | ||||
|                 <span class="badge bg-primary"> | ||||
|                         <i class="fa fa-random"></i> {{ c.accompanyingPeriod.id }} | ||||
|                     </span>  | ||||
|             {% endif %} | ||||
|  | ||||
|             <div> | ||||
|  | ||||
|                 <span class="badge-calendar-simple"> | ||||
|                     {{ 'Calendar'|trans }} | ||||
|                     {% if c.endDate.diff(c.startDate).days >= 1 %} | ||||
|                         {{ c.startDate|format_datetime('short', 'short') }} | ||||
|                         - {{ c.endDate|format_datetime('short', 'short') }} | ||||
|                     {% else %} | ||||
|                         {{ c.startDate|format_datetime('short', 'short') }} | ||||
|                         - {{ c.endDate|format_datetime('none', 'short') }} | ||||
|                     {% endif %} | ||||
|             <span class="badge-calendar"> | ||||
|                     <span class="title_label"></span> | ||||
|                     <span class="title_action"> | ||||
|                         {{ 'Calendar'|trans }} | ||||
|                         {% if c.endDate.diff(c.startDate).days >= 1 %} | ||||
|                             {{ c.startDate|format_datetime('short', 'short') }} | ||||
|                             - {{ c.endDate|format_datetime('short', 'short') }} | ||||
|                         {% else %} | ||||
|                             {{ c.startDate|format_datetime('short', 'short') }} | ||||
|                             - {{ c.endDate|format_datetime('none', 'short') }} | ||||
|                         {% endif %} | ||||
|                     </span> | ||||
|                 </span> | ||||
|             </div> | ||||
|  | ||||
|             <div class="denomination h2"> | ||||
|                 {{ document.storedObject.title|chill_print_or_message("No title") }} | ||||
|             </div> | ||||
|             {% if document.storedObject.hasTemplate %} | ||||
|                 <div> | ||||
|                     <p>{{ document.storedObject.template.name|localize_translatable_string }}</p> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|         </div> | ||||
|         <div class="aside"> | ||||
|  | ||||
|         <div class="denomination h2"> | ||||
|             {{ document.storedObject.title|chill_print_or_message("No title") }} | ||||
|         </div> | ||||
|         {% if document.storedObject.hasTemplate %} | ||||
|             <div> | ||||
|                 <p>{{ document.storedObject.template.name|localize_translatable_string }}</p> | ||||
|             </div> | ||||
|         {% endif %} | ||||
|     </div> | ||||
|  | ||||
|     <div class="item-col"> | ||||
|         <div class="container"> | ||||
|             <div class="dates row text-end"> | ||||
|                 <span>{{ document.storedObject.createdAt|format_date('short') }}</span> | ||||
|             </div> | ||||
|             {% if c.accompanyingPeriod is not null and context == 'person' %} | ||||
|                 <div class="text-end"> | ||||
|                     <span class="badge bg-primary"> | ||||
|                         <i class="fa fa-random"></i> {{ c.accompanyingPeriod.id }} | ||||
|                     </span>  | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|   | ||||
| @@ -14,6 +14,7 @@ namespace Chill\DocStoreBundle\Controller; | ||||
| use Chill\DocStoreBundle\Entity\StoredObject; | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; | ||||
| use Symfony\Component\Routing\Annotation\Route; | ||||
| @@ -27,7 +28,10 @@ class StoredObjectApiController extends ApiController | ||||
|         private readonly Security $security, | ||||
|         private readonly SerializerInterface $serializer, | ||||
|         private readonly EntityManagerInterface $entityManager, | ||||
|     ) {} | ||||
|         ManagerRegistry $managerRegistry, | ||||
|     ) { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new stored object. | ||||
|   | ||||
| @@ -10,9 +10,6 @@ const startApp = ( | ||||
|     collectionEntry: null | HTMLLIElement, | ||||
| ): void => { | ||||
|     console.log("app started", divElement); | ||||
|  | ||||
|     const inputTitle = collectionEntry?.querySelector("input[type='text']"); | ||||
|  | ||||
|     const input_stored_object: HTMLInputElement | null = | ||||
|         divElement.querySelector("input[data-stored-object]"); | ||||
|     if (null === input_stored_object) { | ||||
| @@ -29,10 +26,9 @@ const startApp = ( | ||||
|     const app = createApp({ | ||||
|         template: | ||||
|             '<drop-file-widget :existingDoc="this.$data.existingDoc" :allowRemove="true" @addDocument="this.addDocument" @removeDocument="removeDocument"></drop-file-widget>', | ||||
|         data() { | ||||
|         data(vm) { | ||||
|             return { | ||||
|                 existingDoc: existingDoc, | ||||
|                 inputTitle: inputTitle, | ||||
|             }; | ||||
|         }, | ||||
|         components: { | ||||
| @@ -42,13 +38,10 @@ const startApp = ( | ||||
|             addDocument: function ({ | ||||
|                 stored_object, | ||||
|                 stored_object_version, | ||||
|                 file_name, | ||||
|             }: { | ||||
|                 stored_object: StoredObject; | ||||
|                 stored_object_version: StoredObjectVersion; | ||||
|                 file_name: string; | ||||
|             }): void { | ||||
|                 stored_object.title = file_name; | ||||
|                 console.log("object added", stored_object); | ||||
|                 console.log("version added", stored_object_version); | ||||
|                 this.$data.existingDoc = stored_object; | ||||
| @@ -56,11 +49,6 @@ const startApp = ( | ||||
|                 input_stored_object.value = JSON.stringify( | ||||
|                     this.$data.existingDoc, | ||||
|                 ); | ||||
|                 if (this.$data.inputTitle) { | ||||
|                     if (!this.$data.inputTitle?.value) { | ||||
|                         this.$data.inputTitle.value = file_name; | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             removeDocument: function (object: StoredObject): void { | ||||
|                 console.log("catch remove document", object); | ||||
|   | ||||
| @@ -2,28 +2,26 @@ | ||||
|     <teleport to="body"> | ||||
|         <modal v-if="modalOpen" @close="modalOpen = false"> | ||||
|             <template v-slot:header> | ||||
|                 <h2>{{ trans(SIGNATURES_SIGNATURE_CONFIRMATION) }}</h2> | ||||
|                 <h2>{{ $t("signature_confirmation") }}</h2> | ||||
|             </template> | ||||
|             <template v-slot:body> | ||||
|                 <div class="signature-modal-body text-center" v-if="loading"> | ||||
|                     <p> | ||||
|                         {{ trans(SIGNATURES_ELECTRONIC_SIGNATURE_IN_PROGRESS) }} | ||||
|                     </p> | ||||
|                     <p>{{ $t("electronic_signature_in_progress") }}</p> | ||||
|                     <div class="loading"> | ||||
|                         <i | ||||
|                             class="fa fa-circle-o-notch fa-spin fa-3x" | ||||
|                             :title="trans(SIGNATURES_LOADING)" | ||||
|                             :title="$t('loading')" | ||||
|                         ></i> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="signature-modal-body text-center" v-else> | ||||
|                     <p>{{ trans(SIGNATURES_YOU_ARE_GOING_TO_SIGN) }}</p> | ||||
|                     <p>{{ trans(SIGNATURES_ARE_YOU_SURE) }}</p> | ||||
|                     <p>{{ $t("you_are_going_to_sign") }}</p> | ||||
|                     <p>{{ $t("are_you_sure") }}</p> | ||||
|                 </div> | ||||
|             </template> | ||||
|             <template v-slot:footer> | ||||
|                 <button class="btn btn-action" @click.prevent="confirmSign"> | ||||
|                     {{ trans(SIGNATURES_YES) }} | ||||
|                     {{ $t("yes") }} | ||||
|                 </button> | ||||
|             </template> | ||||
|         </modal> | ||||
| @@ -84,39 +82,33 @@ | ||||
|                         @change="toggleMultiPage" | ||||
|                     /> | ||||
|                     <label class="form-check-label" for="checkboxMulti"> | ||||
|                         {{ trans(SIGNATURES_ALL_PAGES) }} | ||||
|                         {{ $t("all_pages") }} | ||||
|                     </label> | ||||
|                 </template> | ||||
|             </div> | ||||
|             <div | ||||
|                 v-if="signature.zones.length === 1 && signedState !== 'signed'" | ||||
|                 v-if="signature.zones.length > 0" | ||||
|                 class="col-5 p-0 text-center turnSignature" | ||||
|             > | ||||
|                 <button | ||||
|                     class="btn btn-light btn-sm" | ||||
|                     @click="goToSignatureZoneUnique" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_GO_TO_SIGNATURE_UNIQUE) }} | ||||
|                 </button> | ||||
|             </div> | ||||
|             <div | ||||
|                 v-if="signature.zones.length > 1" | ||||
|                 class="col-5 p-0 text-center turnSignature" | ||||
|             > | ||||
|                 <button | ||||
|                     :disabled="isFirstSignatureZone()" | ||||
|                     :disabled=" | ||||
|                         userSignatureZone === null || | ||||
|                         userSignatureZone?.index < 1 | ||||
|                     " | ||||
|                     class="btn btn-light btn-sm" | ||||
|                     @click="turnSignature(-1)" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_LAST_ZONE) }} | ||||
|                     {{ $t("last_zone") }} | ||||
|                 </button> | ||||
|                 <span>|</span> | ||||
|                 <button | ||||
|                     :disabled="isLastSignatureZone()" | ||||
|                     :disabled=" | ||||
|                         userSignatureZone?.index >= signature.zones.length - 1 | ||||
|                     " | ||||
|                     class="btn btn-light btn-sm" | ||||
|                     @click="turnSignature(1)" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_NEXT_ZONE) }} | ||||
|                     {{ $t("next_zone") }} | ||||
|                 </button> | ||||
|             </div> | ||||
|             <div class="col text-end" v-if="signedState !== 'signed'"> | ||||
| @@ -125,9 +117,9 @@ | ||||
|                     :hidden="!userSignatureZone" | ||||
|                     @click="undoSign" | ||||
|                     v-if="signature.zones.length > 1" | ||||
|                     :title="trans(SIGNATURES_CHOOSE_ANOTHER_SIGNATURE)" | ||||
|                     :title="$t('choose_another_signature')" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_ANOTHER_ZONE) }} | ||||
|                     {{ $t("another_zone") }} | ||||
|                 </button> | ||||
|                 <button | ||||
|                     class="btn btn-misc btn-sm" | ||||
| @@ -135,7 +127,7 @@ | ||||
|                     @click="undoSign" | ||||
|                     v-else | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_CANCEL) }} | ||||
|                     {{ $t("cancel") }} | ||||
|                 </button> | ||||
|                 <button | ||||
|                     v-if="userSignatureZone === null" | ||||
| @@ -147,7 +139,7 @@ | ||||
|                         active: canvasEvent === 'add', | ||||
|                     }" | ||||
|                     @click="toggleAddZone()" | ||||
|                     :title="trans(SIGNATURES_ADD_SIGN_ZONE)" | ||||
|                     :title="$t('add_sign_zone')" | ||||
|                 > | ||||
|                     <template v-if="canvasEvent === 'add'"> | ||||
|                         <div | ||||
| @@ -199,70 +191,58 @@ | ||||
|                         @change="toggleMultiPage" | ||||
|                     /> | ||||
|                     <label class="form-check-label" for="checkboxMulti"> | ||||
|                         {{ trans(SIGNATURES_SEE_ALL_PAGES) }} | ||||
|                         {{ $t("see_all_pages") }} | ||||
|                     </label> | ||||
|                 </template> | ||||
|             </div> | ||||
|             <div | ||||
|                 v-if="signature.zones.length === 1 && signedState !== 'signed'" | ||||
|                 v-if="signature.zones.length > 0 && signedState !== 'signed'" | ||||
|                 class="col-4 d-xl-none text-center turnSignature p-0" | ||||
|             > | ||||
|                 <button | ||||
|                     class="btn btn-light btn-sm" | ||||
|                     @click="goToSignatureZoneUnique" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_GO_TO_SIGNATURE_UNIQUE) }} | ||||
|                 </button> | ||||
|             </div> | ||||
|             <div | ||||
|                 v-if="signature.zones.length > 1 && signedState !== 'signed'" | ||||
|                 class="col-4 d-xl-none text-center turnSignature p-0" | ||||
|             > | ||||
|                 <button | ||||
|                     :disabled="isFirstSignatureZone()" | ||||
|                     :disabled=" | ||||
|                         userSignatureZone === null || | ||||
|                         userSignatureZone?.index < 1 | ||||
|                     " | ||||
|                     class="btn btn-light btn-sm" | ||||
|                     @click="turnSignature(-1)" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_LAST_ZONE) }} | ||||
|                     {{ $t("last_zone") }} | ||||
|                 </button> | ||||
|                 <span>|</span> | ||||
|                 <button | ||||
|                     :disabled="isLastSignatureZone()" | ||||
|                     :disabled=" | ||||
|                         userSignatureZone?.index >= signature.zones.length - 1 | ||||
|                     " | ||||
|                     class="btn btn-light btn-sm" | ||||
|                     @click="turnSignature(1)" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_NEXT_ZONE) }} | ||||
|                     {{ $t("next_zone") }} | ||||
|                 </button> | ||||
|             </div> | ||||
|             <div | ||||
|                 v-if="signature.zones.length === 1 && signedState !== 'signed'" | ||||
|                 v-if="signature.zones.length > 0 && signedState !== 'signed'" | ||||
|                 class="col-4 d-none d-xl-flex p-0 text-center turnSignature" | ||||
|             > | ||||
|                 <button | ||||
|                     class="btn btn-light btn-sm" | ||||
|                     @click="goToSignatureZoneUnique" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_GO_TO_SIGNATURE_UNIQUE) }} | ||||
|                 </button> | ||||
|             </div> | ||||
|             <div | ||||
|                 v-if="signature.zones.length > 1 && signedState !== 'signed'" | ||||
|                 class="col-4 d-none d-xl-flex p-0 text-center turnSignature" | ||||
|             > | ||||
|                 <button | ||||
|                     :disabled="isFirstSignatureZone()" | ||||
|                     :disabled=" | ||||
|                         userSignatureZone === null || | ||||
|                         userSignatureZone?.index < 1 | ||||
|                     " | ||||
|                     class="btn btn-light btn-sm" | ||||
|                     @click="turnSignature(-1)" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_LAST_SIGN_ZONE) }} | ||||
|                     {{ $t("last_sign_zone") }} | ||||
|                 </button> | ||||
|                 <span>|</span> | ||||
|                 <button | ||||
|                     :disabled="isLastSignatureZone()" | ||||
|                     :disabled=" | ||||
|                         userSignatureZone?.index >= signature.zones.length - 1 | ||||
|                     " | ||||
|                     class="btn btn-light btn-sm" | ||||
|                     @click="turnSignature(1)" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_NEXT_SIGN_ZONE) }} | ||||
|                     {{ $t("next_sign_zone") }} | ||||
|                 </button> | ||||
|             </div> | ||||
|             <div class="col text-end" v-if="signedState !== 'signed'"> | ||||
| @@ -272,7 +252,7 @@ | ||||
|                     @click="undoSign" | ||||
|                     v-if="signature.zones.length > 1" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_CHOOSE_ANOTHER_SIGNATURE) }} | ||||
|                     {{ $t("choose_another_signature") }} | ||||
|                 </button> | ||||
|                 <button | ||||
|                     class="btn btn-misc btn-sm" | ||||
| @@ -280,7 +260,7 @@ | ||||
|                     @click="undoSign" | ||||
|                     v-else | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_CANCEL) }} | ||||
|                     {{ $t("cancel") }} | ||||
|                 </button> | ||||
|                 <button | ||||
|                     v-if="userSignatureZone === null" | ||||
| @@ -292,13 +272,13 @@ | ||||
|                         active: canvasEvent === 'add', | ||||
|                     }" | ||||
|                     @click="toggleAddZone()" | ||||
|                     :title="trans(SIGNATURES_ADD_SIGN_ZONE)" | ||||
|                     :title="$t('add_sign_zone')" | ||||
|                 > | ||||
|                     <template v-if="canvasEvent !== 'add'"> | ||||
|                         {{ trans(SIGNATURES_ADD_ZONE) }} | ||||
|                         {{ $t("add_zone") }} | ||||
|                     </template> | ||||
|                     <template v-else> | ||||
|                         {{ trans(SIGNATURES_CLICK_ON_DOCUMENT) }} | ||||
|                         {{ $t("click_on_document") }} | ||||
|                         <div | ||||
|                             class="spinner-border spinner-border-sm" | ||||
|                             role="status" | ||||
| @@ -332,10 +312,10 @@ | ||||
|                     v-if="signedState !== 'signed'" | ||||
|                     :href="getReturnPath()" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_CANCEL) }} | ||||
|                     {{ $t("cancel") }} | ||||
|                 </a> | ||||
|                 <a class="btn btn-misc" v-else :href="getReturnPath()"> | ||||
|                     {{ trans(SIGNATURES_RETURN) }} | ||||
|                     {{ $t("return") }} | ||||
|                 </a> | ||||
|             </div> | ||||
|             <div class="col text-end" v-if="signedState !== 'signed'"> | ||||
| @@ -344,7 +324,7 @@ | ||||
|                     :disabled="!userSignatureZone" | ||||
|                     @click="sign" | ||||
|                 > | ||||
|                     {{ trans(SIGNATURES_SIGN) }} | ||||
|                     {{ $t("sign") }} | ||||
|                 </button> | ||||
|             </div> | ||||
|             <div class="col-4" v-else></div> | ||||
| @@ -353,7 +333,7 @@ | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { ref, Ref } from "vue"; | ||||
| import { ref, Ref, reactive } from "vue"; | ||||
| import { useToast } from "vue-toast-notification"; | ||||
| import "vue-toast-notification/dist/theme-sugar.css"; | ||||
| import { | ||||
| @@ -364,47 +344,25 @@ import { | ||||
|     SignedState, | ||||
|     ZoomLevel, | ||||
| } from "../../types"; | ||||
| import { makeFetch } from "ChillMainAssets/lib/api/apiMethods"; | ||||
| import { makeFetch } from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods"; | ||||
| import * as pdfjsLib from "pdfjs-dist"; | ||||
| import { | ||||
|     PDFDocumentProxy, | ||||
|     PDFPageProxy, | ||||
| } from "pdfjs-dist/types/src/display/api"; | ||||
|  | ||||
| import { | ||||
|     SIGNATURES_YES, | ||||
|     SIGNATURES_ARE_YOU_SURE, | ||||
|     SIGNATURES_YOU_ARE_GOING_TO_SIGN, | ||||
|     SIGNATURES_SIGNATURE_CONFIRMATION, | ||||
|     SIGNATURES_SIGN, | ||||
|     SIGNATURES_CHOOSE_ANOTHER_SIGNATURE, | ||||
|     SIGNATURES_CANCEL, | ||||
|     SIGNATURES_LAST_SIGN_ZONE, | ||||
|     SIGNATURES_NEXT_SIGN_ZONE, | ||||
|     SIGNATURES_ADD_SIGN_ZONE, | ||||
|     SIGNATURES_CLICK_ON_DOCUMENT, | ||||
|     SIGNATURES_LAST_ZONE, | ||||
|     SIGNATURES_NEXT_ZONE, | ||||
|     SIGNATURES_ADD_ZONE, | ||||
|     SIGNATURES_ANOTHER_ZONE, | ||||
|     SIGNATURES_ELECTRONIC_SIGNATURE_IN_PROGRESS, | ||||
|     SIGNATURES_LOADING, | ||||
|     SIGNATURES_RETURN, | ||||
|     SIGNATURES_SEE_ALL_PAGES, | ||||
|     SIGNATURES_ALL_PAGES, | ||||
|     SIGNATURES_GO_TO_SIGNATURE_UNIQUE, | ||||
|     trans, | ||||
| } from "translator"; | ||||
|  | ||||
| // @ts-ignore incredible but the console.log is needed | ||||
| // @ts-ignore | ||||
| import * as PdfWorker from "pdfjs-dist/build/pdf.worker.mjs"; | ||||
| console.log(PdfWorker); | ||||
| console.log(PdfWorker); // incredible but this is needed | ||||
|  | ||||
| // import { PdfWorker } from 'pdfjs-dist/build/pdf.worker.mjs' | ||||
| // pdfjsLib.GlobalWorkerOptions.workerSrc = PdfWorker; | ||||
|  | ||||
| import Modal from "ChillMainAssets/vuejs/_components/Modal.vue"; | ||||
| import { download_doc_as_pdf } from "../StoredObjectButton/helpers"; | ||||
| import { | ||||
|     download_and_decrypt_doc, | ||||
|     download_doc_as_pdf, | ||||
| } from "../StoredObjectButton/helpers"; | ||||
|  | ||||
| pdfjsLib.GlobalWorkerOptions.workerSrc = "pdfjs-dist/build/pdf.worker.mjs"; | ||||
|  | ||||
| @@ -475,16 +433,6 @@ const $toast = useToast(); | ||||
|  | ||||
| const signature = window.signature; | ||||
|  | ||||
| const isFirstSignatureZone = () => | ||||
|     userSignatureZone.value?.index != null | ||||
|         ? userSignatureZone.value.index < 1 | ||||
|         : false; | ||||
|  | ||||
| const isLastSignatureZone = () => | ||||
|     userSignatureZone.value?.index | ||||
|         ? userSignatureZone.value.index >= signature.zones.length - 1 | ||||
|         : false; | ||||
|  | ||||
| const setZoomLevel = async (zoomLevel: string) => { | ||||
|     zoom.value = Number.parseFloat(zoomLevel); | ||||
|     await resetPages(); | ||||
| @@ -656,15 +604,6 @@ const turnPage = async (upOrDown: number) => { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| const selectZoneInCanvas = (signatureZone: SignatureZone) => { | ||||
|     page.value = signatureZone.PDFPage.index + 1; | ||||
|     const canvas = getCanvas(signatureZone.PDFPage.index + 1); | ||||
|     selectZone(signatureZone, canvas); | ||||
|     canvas.scrollIntoView(); | ||||
| }; | ||||
|  | ||||
| const goToSignatureZoneUnique = () => selectZoneInCanvas(signature.zones[0]); | ||||
|  | ||||
| const turnSignature = async (upOrDown: number) => { | ||||
|     let zoneIndex = userSignatureZone.value?.index ?? -1; | ||||
|     if (zoneIndex < -1) { | ||||
| @@ -677,7 +616,10 @@ const turnSignature = async (upOrDown: number) => { | ||||
|     } | ||||
|     let currentZone = signature.zones[zoneIndex]; | ||||
|     if (currentZone) { | ||||
|         selectZoneInCanvas(currentZone); | ||||
|         page.value = currentZone.PDFPage.index + 1; | ||||
|         const canvas = getCanvas(currentZone.PDFPage.index + 1); | ||||
|         selectZone(currentZone, canvas); | ||||
|         canvas.scrollIntoView(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| @@ -812,7 +754,7 @@ const confirmSign = () => { | ||||
|         zone: userSignatureZone.value, | ||||
|     }; | ||||
|     makeFetch("POST", url, body) | ||||
|         .then(() => { | ||||
|         .then((r) => { | ||||
|             checkForReady(); | ||||
|         }) | ||||
|         .catch((error) => { | ||||
| @@ -834,7 +776,9 @@ const undoSign = async () => { | ||||
| }; | ||||
|  | ||||
| const toggleAddZone = () => { | ||||
|     canvasEvent.value = canvasEvent.value === "select" ? "add" : "select"; | ||||
|     canvasEvent.value === "select" | ||||
|         ? (canvasEvent.value = "add") | ||||
|         : (canvasEvent.value = "select"); | ||||
| }; | ||||
|  | ||||
| const addZoneEvent = async (e: PointerEvent, canvas: HTMLCanvasElement) => { | ||||
|   | ||||
| @@ -23,7 +23,6 @@ const emit = | ||||
|             { | ||||
|                 stored_object_version: StoredObjectVersionCreated, | ||||
|                 stored_object: StoredObject, | ||||
|                 file_name: string, | ||||
|             }, | ||||
|         ) => void | ||||
|     >(); | ||||
| @@ -115,21 +114,7 @@ const handleFile = async (file: File): Promise<void> => { | ||||
|         persisted: false, | ||||
|     }; | ||||
|  | ||||
|     const fileName = file.name; | ||||
|     let file_name = "Nouveau document"; | ||||
|     const file_name_split = fileName.split("."); | ||||
|     if (file_name_split.length > 1) { | ||||
|         const extension = file_name_split | ||||
|             ? file_name_split[file_name_split.length - 1] | ||||
|             : ""; | ||||
|         file_name = fileName.replace(extension, "").slice(0, -1); | ||||
|     } | ||||
|  | ||||
|     emit("addDocument", { | ||||
|         stored_object, | ||||
|         stored_object_version, | ||||
|         file_name: file_name, | ||||
|     }); | ||||
|     emit("addDocument", { stored_object, stored_object_version }); | ||||
|     uploading.value = false; | ||||
| }; | ||||
| </script> | ||||
|   | ||||
| @@ -20,7 +20,6 @@ const emit = defineEmits<{ | ||||
|         { | ||||
|             stored_object: StoredObject, | ||||
|             stored_object_version: StoredObjectVersion, | ||||
|             file_name: string, | ||||
|         }, | ||||
|     ): void; | ||||
|     (e: "removeDocument"): void; | ||||
| @@ -43,16 +42,14 @@ const buttonState = computed<"add" | "replace">(() => { | ||||
| function onAddDocument({ | ||||
|     stored_object, | ||||
|     stored_object_version, | ||||
|     file_name, | ||||
| }: { | ||||
|     stored_object: StoredObject; | ||||
|     stored_object_version: StoredObjectVersion; | ||||
|     file_name: string; | ||||
| }): void { | ||||
|     const message = | ||||
|         buttonState.value === "add" ? "Document ajouté" : "Document remplacé"; | ||||
|     $toast.success(message); | ||||
|     emit("addDocument", { stored_object_version, stored_object, file_name }); | ||||
|     emit("addDocument", { stored_object_version, stored_object }); | ||||
|     state.showModal = false; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -19,7 +19,6 @@ const emit = defineEmits<{ | ||||
|         { | ||||
|             stored_object: StoredObject, | ||||
|             stored_object_version: StoredObjectVersion, | ||||
|             file_name: string, | ||||
|         }, | ||||
|     ): void; | ||||
|     (e: "removeDocument"): void; | ||||
| @@ -54,13 +53,11 @@ const dav_link_href = computed<string | undefined>(() => { | ||||
| const onAddDocument = ({ | ||||
|     stored_object, | ||||
|     stored_object_version, | ||||
|     file_name, | ||||
| }: { | ||||
|     stored_object: StoredObject; | ||||
|     stored_object_version: StoredObjectVersion; | ||||
|     file_name: string; | ||||
| }): void => { | ||||
|     emit("addDocument", { stored_object, stored_object_version, file_name }); | ||||
|     emit("addDocument", { stored_object, stored_object_version }); | ||||
| }; | ||||
|  | ||||
| const onRemoveDocument = (e: Event): void => { | ||||
|   | ||||
| @@ -53,7 +53,7 @@ const onRestored = ({ | ||||
| <template> | ||||
|     <template v-if="props.versions.length > 0"> | ||||
|         <div class="container"> | ||||
|             <template v-for="v in props.versions" :key="v.id"> | ||||
|             <template v-for="v in props.versions"> | ||||
|                 <history-button-list-item | ||||
|                     :version="v" | ||||
|                     :can-edit="canEdit" | ||||
|   | ||||
| @@ -32,17 +32,13 @@ const onRestore = ({ | ||||
|     emit("restoreVersion", { newVersion }); | ||||
| }; | ||||
|  | ||||
| const isKeptBeforeConversion = computed<boolean>(() => { | ||||
|     if ("point-in-times" in props.version) { | ||||
|         return props.version["point-in-times"].reduce( | ||||
|             (accumulator: boolean, pit: StoredObjectPointInTime) => | ||||
|                 accumulator || "keep-before-conversion" === pit.reason, | ||||
|             false, | ||||
|         ); | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
| }); | ||||
| const isKeptBeforeConversion = computed<boolean>(() => | ||||
|     props.version["point-in-times"].reduce( | ||||
|         (accumulator: boolean, pit: StoredObjectPointInTime) => | ||||
|             accumulator || "keep-before-conversion" === pit.reason, | ||||
|         false, | ||||
|     ), | ||||
| ); | ||||
|  | ||||
| const isRestored = computed<boolean>( | ||||
|     () => props.version.version > 0 && null !== props.version["from-restored"], | ||||
| @@ -94,11 +90,11 @@ const classes = computed<{ | ||||
|         <div class="col-12"> | ||||
|             <file-icon :type="version.type"></file-icon> | ||||
|             <span | ||||
|                 ><strong> #{{ version.version + 1 }} </strong></span | ||||
|                 ><strong>#{{ version.version + 1 }}</strong></span | ||||
|             > | ||||
|             <template | ||||
|                 v-if="version.createdBy !== null && version.createdAt !== null" | ||||
|                 ><strong v-if="version.version == 0">créé par</strong | ||||
|                 ><strong v-if="version.version == 0">Créé par</strong | ||||
|                 ><strong v-else>modifié par</strong> | ||||
|                 <span class="badge-user" | ||||
|                     ><UserRenderBoxBadge | ||||
|   | ||||
| @@ -28,10 +28,6 @@ const open = () => { | ||||
|     state.opened = true; | ||||
| }; | ||||
|  | ||||
| const onRestoreVersion = (payload: { | ||||
|     newVersion: StoredObjectVersionWithPointInTime; | ||||
| }) => emit("restoreVersion", payload); | ||||
|  | ||||
| defineExpose({ open }); | ||||
| </script> | ||||
| <template> | ||||
| @@ -46,7 +42,9 @@ defineExpose({ open }); | ||||
|                     :versions="props.versions" | ||||
|                     :can-edit="canEdit" | ||||
|                     :stored-object="storedObject" | ||||
|                     @restore-version="onRestoreVersion" | ||||
|                     @restore-version=" | ||||
|                         (payload) => emit('restoreVersion', payload) | ||||
|                     " | ||||
|                 ></history-button-list> | ||||
|             </template> | ||||
|         </modal> | ||||
|   | ||||
| @@ -23,7 +23,7 @@ License * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
| {{ encore_entry_link_tags("mod_document_action_buttons_group") }} | ||||
| {% endblock %} {% block content %} | ||||
|  | ||||
| <div class="document-list"> | ||||
| <div class="col-md-10 col-xxl"> | ||||
|     <h1> | ||||
|         {{ 'Documents for %name%'|trans({ '%name%': person|chill_entity_render_string } ) }} | ||||
|     </h1> | ||||
|   | ||||
| @@ -3,56 +3,54 @@ | ||||
| {% import '@ChillPerson/Macro/updatedBy.html.twig' as mmm %} | ||||
|  | ||||
| <div class="item-row"> | ||||
|     <!-- person document or accompanying course document --> | ||||
|     <div class="item-two-col-grid"> | ||||
|         <div class="title"> | ||||
|             {% if document.object.isPending %} | ||||
|                 <div class="badge text-bg-info" data-docgen-is-pending="{{ document.object.id }}">{{ 'docgen.Doc generation is pending'|trans }}</div> | ||||
|             {% elseif document.object.isFailure %} | ||||
|                 <div class="badge text-bg-warning">{{ 'docgen.Doc generation failed'|trans }}</div> | ||||
|             {% endif %} | ||||
|     <div class="item-col" style="width: unset"> | ||||
|         {% if document.object.isPending %} | ||||
|             <div class="badge text-bg-info" data-docgen-is-pending="{{ document.object.id }}">{{ 'docgen.Doc generation is pending'|trans }}</div> | ||||
|         {% elseif document.object.isFailure %} | ||||
|             <div class="badge text-bg-warning">{{ 'docgen.Doc generation failed'|trans }}</div> | ||||
|         {% endif %} | ||||
|  | ||||
|             <div class="denomination h2"> | ||||
|                 {{ document.title|chill_print_or_message("No title") }} | ||||
|         {% if context == 'person' and accompanyingCourse is defined %} | ||||
|             <div> | ||||
|                     <span class="badge bg-primary"> | ||||
|                         <i class="fa fa-random"></i> {{ accompanyingCourse.id }} | ||||
|                     </span>  | ||||
|             </div> | ||||
|             {% if document.object.type is not empty %} | ||||
|                 <div> | ||||
|                     {{ mm.mimeIcon(document.object.type) }} | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|             {% if document.category %} | ||||
|                 <div> | ||||
|                     <p>{{ document.category.name|localize_translatable_string }}</p> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|             {% if document.object.hasTemplate %} | ||||
|                 <div> | ||||
|                     <p>{{ document.object.template.name|localize_translatable_string }}</p> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|         {% elseif context == 'accompanying-period' and person is defined %} | ||||
|             <div> | ||||
|                     <span class="badge bg-primary"> | ||||
|                         {{  'Document from person %name%'|trans({ '%name%': document.person|chill_entity_render_string }) }} | ||||
|                     </span>  | ||||
|             </div> | ||||
|  | ||||
|         {% endif %} | ||||
|         <div class="denomination h2"> | ||||
|             {{ document.title|chill_print_or_message("No title") }} | ||||
|         </div> | ||||
|         {% if document.date is not null %} | ||||
|             <div class="aside"> | ||||
|                 <div class="dates row text-end"> | ||||
|                     <span>{{ document.date|format_date('short') }}</span> | ||||
|                 </div> | ||||
|                 {% if context == 'person' and accompanyingCourse is defined %} | ||||
|                     <div class="text-end"> | ||||
|                         <span class="badge bg-primary"> | ||||
|                             <i class="fa fa-random"></i> {{ accompanyingCourse.id }} | ||||
|                         </span>  | ||||
|                     </div> | ||||
|                 {% elseif context == 'accompanying-period' and person is defined %} | ||||
|                     <div class="text-end"> | ||||
|                         <span class="badge bg-primary"> | ||||
|                              {{ document.person|chill_entity_render_string }} | ||||
|                         </span>  | ||||
|                     </div> | ||||
|                 {% endif %} | ||||
|         {% if document.object.type is not empty %} | ||||
|             <div> | ||||
|                 {{ mm.mimeIcon(document.object.type) }} | ||||
|             </div> | ||||
|         {% endif %} | ||||
|         <div> | ||||
|             <p>{{ document.category.name|localize_translatable_string }}</p> | ||||
|         </div> | ||||
|         {% if document.object.hasTemplate %} | ||||
|             <div> | ||||
|                 <p>{{ document.object.template.name|localize_translatable_string }}</p> | ||||
|             </div> | ||||
|         {% endif %} | ||||
|     </div> | ||||
|  | ||||
|     <div class="item-col"> | ||||
|         <div class="container"> | ||||
|             {% if document.date is not null %} | ||||
|                 <div class="dates row text-end"> | ||||
|                     <span>{{ document.date|format_date('short') }}</span> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {% if document.description is not empty %} | ||||
|     <div class="item-row"> | ||||
|   | ||||
| @@ -62,15 +62,7 @@ final readonly class RemoveOldVersionMessageHandler implements MessageHandlerInt | ||||
|  | ||||
|         $storedObject = $storedObjectVersion->getStoredObject(); | ||||
|  | ||||
|         if ($this->storedObjectManager->exists($storedObjectVersion)) { | ||||
|             $this->storedObjectManager->delete($storedObjectVersion); | ||||
|         } else { | ||||
|             $this->logger->notice( | ||||
|                 self::LOG_PREFIX.'Stored object version does not exists any more.', | ||||
|                 ['storedObjectVersionName' => $storedObjectVersion->getFilename()], | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $this->storedObjectManager->delete($storedObjectVersion); | ||||
|         // to ensure an immediate deletion | ||||
|         $this->entityManager->remove($storedObjectVersion); | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,7 @@ namespace Chill\DocStoreBundle\Tests\Controller; | ||||
| use Chill\DocStoreBundle\Controller\StoredObjectApiController; | ||||
| use Chill\DocStoreBundle\Entity\StoredObject; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use PHPUnit\Framework\TestCase; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
| @@ -45,7 +46,9 @@ class StoredObjectApiControllerTest extends TestCase | ||||
|             {"type":  "stored-object", "id":  1} | ||||
|             JSON); | ||||
|  | ||||
|         $controller = new StoredObjectApiController($security, $serializer, $entityManager); | ||||
|         $managerRegistry = $this->createMock(ManagerRegistry::class); | ||||
|  | ||||
|         $controller = new StoredObjectApiController($security, $serializer, $entityManager, $managerRegistry); | ||||
|  | ||||
|         $actual = $controller->createStoredObject(); | ||||
|  | ||||
|   | ||||
| @@ -44,7 +44,6 @@ class RemoveOldVersionMessageHandlerTest extends TestCase | ||||
|         $entityManager->expects($this->once())->method('clear'); | ||||
|  | ||||
|         $storedObjectManager = $this->createMock(StoredObjectManagerInterface::class); | ||||
|         $storedObjectManager->expects($this->once())->method('exists')->willReturn(true); | ||||
|         $storedObjectManager->expects($this->once())->method('delete')->with($this->identicalTo($version)); | ||||
|  | ||||
|         $handler = new RemoveOldVersionMessageHandler($storedObjectVersionRepository, new NullLogger(), $entityManager, $storedObjectManager, new MockClock()); | ||||
| @@ -52,29 +51,6 @@ class RemoveOldVersionMessageHandlerTest extends TestCase | ||||
|         $handler(new RemoveOldVersionMessage(1)); | ||||
|     } | ||||
|  | ||||
|     public function testInvokeForVersionNotExisting(): void | ||||
|     { | ||||
|         $object = new StoredObject(); | ||||
|         $version = $object->registerVersion(); | ||||
|         $storedObjectVersionRepository = $this->createMock(StoredObjectVersionRepository::class); | ||||
|         $storedObjectVersionRepository->expects($this->once())->method('find') | ||||
|             ->with($this->identicalTo(1)) | ||||
|             ->willReturn($version); | ||||
|  | ||||
|         $entityManager = $this->createMock(EntityManagerInterface::class); | ||||
|         $entityManager->expects($this->once())->method('remove')->with($this->identicalTo($version)); | ||||
|         $entityManager->expects($this->once())->method('flush'); | ||||
|         $entityManager->expects($this->once())->method('clear'); | ||||
|  | ||||
|         $storedObjectManager = $this->createMock(StoredObjectManagerInterface::class); | ||||
|         $storedObjectManager->expects($this->once())->method('exists')->willReturn(false); | ||||
|         $storedObjectManager->expects($this->never())->method('delete')->with($this->identicalTo($version)); | ||||
|  | ||||
|         $handler = new RemoveOldVersionMessageHandler($storedObjectVersionRepository, new NullLogger(), $entityManager, $storedObjectManager, new MockClock()); | ||||
|  | ||||
|         $handler(new RemoveOldVersionMessage(1)); | ||||
|     } | ||||
|  | ||||
|     public function testInvokeWithStoredObjectToDelete(): void | ||||
|     { | ||||
|         $object = new StoredObject(); | ||||
| @@ -147,6 +123,6 @@ class DummyStoredObjectManager implements StoredObjectManagerInterface | ||||
|  | ||||
|     public function exists(StoredObject|StoredObjectVersion $document): bool | ||||
|     { | ||||
|         return true; | ||||
|         throw new \RuntimeException(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -99,30 +99,3 @@ CHILL_ACCOMPANYING_COURSE_DOCUMENT_UPDATE: Modifier un document | ||||
| entity_display_title: | ||||
|     Document (n°%doc%): "Document (n°%doc%)" | ||||
|     Doc for evaluation (n°%eval%): Document de l'évaluation n°%eval% | ||||
|  | ||||
|  | ||||
| # SIGNATURES | ||||
|  | ||||
| signatures: | ||||
|     yes: Oui | ||||
|     are_you_sure: Êtes-vous sûr·e? | ||||
|     you_are_going_to_sign: Vous allez signer le document | ||||
|     signature_confirmation: Confirmation de la signature | ||||
|     sign: Signer | ||||
|     choose_another_signature: Choisir une autre zone | ||||
|     cancel: Annuler | ||||
|     last_sign_zone: Zone de signature précédente | ||||
|     next_sign_zone: Zone de signature suivante | ||||
|     add_sign_zone: Ajouter une zone de signature | ||||
|     click_on_document: Cliquer sur le document | ||||
|     last_zone: Zone précédente | ||||
|     next_zone: Zone suivante | ||||
|     add_zone: Ajouter une zone | ||||
|     another_zone: Autre zone | ||||
|     electronic_signature_in_progress: Signature électronique en cours... | ||||
|     loading: Chargement... | ||||
|     remove_sign_zone: Enlever la zone | ||||
|     return: Retour | ||||
|     see_all_pages: Voir toutes les pages | ||||
|     all_pages: Toutes les pages | ||||
|     go_to_signature_unique: Aller à la zone de signature | ||||
|   | ||||
| @@ -39,6 +39,8 @@ abstract class AbstractCRUDController extends AbstractController | ||||
|      */ | ||||
|     protected array $crudConfig = []; | ||||
|  | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) {} | ||||
|  | ||||
|     /** | ||||
|      * get the role given from the config. | ||||
|      */ | ||||
| @@ -63,6 +65,7 @@ abstract class AbstractCRUDController extends AbstractController | ||||
|             parent::getSubscribedServices(), | ||||
|             [ | ||||
|                 'chill_main.paginator_factory' => PaginatorFactory::class, | ||||
|                 ManagerRegistry::class => ManagerRegistry::class, | ||||
|                 'translator' => TranslatorInterface::class, | ||||
|                 AuthorizationHelper::class => AuthorizationHelper::class, | ||||
|                 EventDispatcherInterface::class => EventDispatcherInterface::class, | ||||
| @@ -212,7 +215,7 @@ abstract class AbstractCRUDController extends AbstractController | ||||
|  | ||||
|     protected function getManagerRegistry(): ManagerRegistry | ||||
|     { | ||||
|         return $this->container->get('doctrine'); | ||||
|         return $this->managerRegistry; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -225,7 +228,7 @@ abstract class AbstractCRUDController extends AbstractController | ||||
|  | ||||
|     protected function getValidator(): ValidatorInterface | ||||
|     { | ||||
|         return $this->container->get('validator'); | ||||
|         return $this->get('validator'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -13,6 +13,7 @@ namespace Chill\MainBundle\CRUD\Controller; | ||||
|  | ||||
| use Chill\MainBundle\Pagination\PaginatorInterface; | ||||
| use Chill\MainBundle\Serializer\Model\Collection; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | ||||
| @@ -23,6 +24,11 @@ use Symfony\Component\Validator\ConstraintViolationListInterface; | ||||
|  | ||||
| class ApiController extends AbstractCRUDController | ||||
| { | ||||
|     public function __construct(ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Base method for handling api action. | ||||
|      * | ||||
|   | ||||
| @@ -13,6 +13,7 @@ namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Chill\MainBundle\Entity\Address; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| use Symfony\Component\Routing\Annotation\Route; | ||||
| @@ -20,7 +21,10 @@ use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; | ||||
|  | ||||
| class AddressApiController extends ApiController | ||||
| { | ||||
|     public function __construct(private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {} | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Duplicate an existing address. | ||||
|   | ||||
| @@ -17,6 +17,7 @@ use Chill\MainBundle\Pagination\PaginatorFactory; | ||||
| use Chill\MainBundle\Pagination\PaginatorInterface; | ||||
| use Chill\MainBundle\Repository\AddressReferenceRepository; | ||||
| use Chill\MainBundle\Serializer\Model\Collection; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| @@ -26,7 +27,10 @@ use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; | ||||
|  | ||||
| final class AddressReferenceAPIController extends ApiController | ||||
| { | ||||
|     public function __construct(private readonly AddressReferenceRepository $addressReferenceRepository, private readonly PaginatorFactory $paginatorFactory) {} | ||||
|     public function __construct(private readonly AddressReferenceRepository $addressReferenceRepository, private readonly PaginatorFactory $paginatorFactory, ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     #[Route(path: '/api/1.0/main/address-reference/by-postal-code/{id}/search.json')] | ||||
|     public function search(PostalCode $postalCode, Request $request): JsonResponse | ||||
|   | ||||
| @@ -13,10 +13,16 @@ namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Chill\MainBundle\Pagination\PaginatorInterface; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| class CivilityApiController extends ApiController | ||||
| { | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator, $_format) | ||||
|     { | ||||
|         return $query->addOrderBy('e.order', 'ASC'); | ||||
|   | ||||
| @@ -12,5 +12,12 @@ declare(strict_types=1); | ||||
| namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
|  | ||||
| class CountryApiController extends ApiController {} | ||||
| class CountryApiController extends ApiController | ||||
| { | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -13,10 +13,16 @@ namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Chill\MainBundle\Pagination\PaginatorInterface; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| class GenderApiController extends ApiController | ||||
| { | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     protected function customizeQuery(string $action, Request $request, $query): void | ||||
|     { | ||||
|         $query | ||||
|   | ||||
| @@ -12,5 +12,12 @@ declare(strict_types=1); | ||||
| namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
|  | ||||
| class GeographicalUnitApiController extends ApiController {} | ||||
| class GeographicalUnitApiController extends ApiController | ||||
| { | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -14,6 +14,7 @@ namespace Chill\MainBundle\Controller; | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Chill\MainBundle\Pagination\PaginatorInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| /** | ||||
| @@ -21,6 +22,11 @@ use Symfony\Component\HttpFoundation\Request; | ||||
|  */ | ||||
| class LocationApiController extends ApiController | ||||
| { | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     protected function customizeQuery(string $action, Request $request, $query): void | ||||
|     { | ||||
|         $query | ||||
|   | ||||
| @@ -12,6 +12,7 @@ declare(strict_types=1); | ||||
| namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| /** | ||||
| @@ -19,6 +20,11 @@ use Symfony\Component\HttpFoundation\Request; | ||||
|  */ | ||||
| class LocationTypeApiController extends ApiController | ||||
| { | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     public function customizeQuery(string $action, Request $request, $query): void | ||||
|     { | ||||
|         $query->andWhere( | ||||
|   | ||||
| @@ -16,6 +16,7 @@ use Chill\MainBundle\Pagination\PaginatorFactory; | ||||
| use Chill\MainBundle\Repository\CountryRepository; | ||||
| use Chill\MainBundle\Repository\PostalCodeRepositoryInterface; | ||||
| use Chill\MainBundle\Serializer\Model\Collection; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| @@ -26,7 +27,10 @@ use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; | ||||
|  | ||||
| final class PostalCodeAPIController extends ApiController | ||||
| { | ||||
|     public function __construct(private readonly CountryRepository $countryRepository, private readonly PostalCodeRepositoryInterface $postalCodeRepository, private readonly PaginatorFactory $paginatorFactory) {} | ||||
|     public function __construct(private readonly CountryRepository $countryRepository, private readonly PostalCodeRepositoryInterface $postalCodeRepository, private readonly PaginatorFactory $paginatorFactory, ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     #[Route(path: '/api/1.0/main/postal-code/search.json')] | ||||
|     public function search(Request $request): JsonResponse | ||||
|   | ||||
| @@ -12,10 +12,16 @@ declare(strict_types=1); | ||||
| namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| class ScopeApiController extends ApiController | ||||
| { | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     protected function customizeQuery(string $action, Request $request, $query): void | ||||
|     { | ||||
|         if ('_index' === $action) { | ||||
|   | ||||
| @@ -15,6 +15,7 @@ use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Chill\MainBundle\Pagination\PaginatorInterface; | ||||
| use Chill\MainBundle\Security\ChillSecurity; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; | ||||
| @@ -22,7 +23,10 @@ use Symfony\Component\Routing\Annotation\Route; | ||||
|  | ||||
| class UserApiController extends ApiController | ||||
| { | ||||
|     public function __construct(private readonly ChillSecurity $security) {} | ||||
|     public function __construct(private readonly ChillSecurity $security, ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     #[Route(path: '/api/1.0/main/user-current-location.{_format}', name: 'chill_main_user_current_location', requirements: ['_format' => 'json'])] | ||||
|     public function currentLocation(mixed $_format): JsonResponse | ||||
|   | ||||
| @@ -12,5 +12,12 @@ declare(strict_types=1); | ||||
| namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
|  | ||||
| class UserGroupApiController extends ApiController {} | ||||
| class UserGroupApiController extends ApiController | ||||
| { | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -12,10 +12,16 @@ declare(strict_types=1); | ||||
| namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| class UserJobApiController extends ApiController | ||||
| { | ||||
|     public function __construct(protected ManagerRegistry $managerRegistry) | ||||
|     { | ||||
|         parent::__construct($managerRegistry); | ||||
|     } | ||||
|  | ||||
|     protected function customizeQuery(string $action, Request $request, $query): void | ||||
|     { | ||||
|         if ('_index' === $action) { | ||||
|   | ||||
| @@ -75,8 +75,8 @@ final class UserGroupRepository implements UserGroupRepositoryInterface, LocaleA | ||||
|             ->setWhereClauses(' | ||||
|                 ug.active AND ( | ||||
|                 SIMILARITY(LOWER(UNACCENT(?)), ug.label->>?) > 0.15 | ||||
|                 OR LOWER(UNACCENT(ug.label->>?)) LIKE \'%\' || LOWER(UNACCENT(?)) || \'%\') | ||||
|             ', [$pattern, $lang, $lang, $pattern]); | ||||
|                 OR ug.label->>? LIKE \'%\' || LOWER(UNACCENT(?)) || \'%\') | ||||
|             ', [$pattern, $lang, $pattern, $lang]); | ||||
|  | ||||
|         return $query; | ||||
|     } | ||||
|   | ||||
| @@ -33,8 +33,6 @@ | ||||
|  | ||||
| @import './scss/hover.scss'; | ||||
|  | ||||
| @import './scss/comment-editor.scss'; | ||||
|  | ||||
| /* | ||||
|  *    BASE LAYOUT POSITION | ||||
|  */ | ||||
|   | ||||
| @@ -1,39 +0,0 @@ | ||||
| .comment-container { | ||||
|     margin-top: 1.5rem; | ||||
| } | ||||
|  | ||||
| .toggle-button { | ||||
|     background-color: white; | ||||
|     font-size: .8rem; | ||||
|     text-decoration: none; | ||||
|     position: absolute; | ||||
|     bottom: -10px; | ||||
|     left: 20px; | ||||
|     padding: 2px 6px; | ||||
|     cursor: pointer; | ||||
|     z-index: 10; | ||||
|     transition: left 0.1s ease-in-out; | ||||
| } | ||||
|  | ||||
| .rich-editor-active .toggle-button { | ||||
|     bottom: 0; | ||||
| } | ||||
|  | ||||
| .editor-wrapper textarea { | ||||
|     resize: vertical; | ||||
|     min-height: 100px; | ||||
| } | ||||
|  | ||||
| .editor-container { | ||||
|     position: relative; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
| } | ||||
|  | ||||
| .editor-wrapper { | ||||
|     position: relative; | ||||
| } | ||||
|  | ||||
| .hidden-textarea { | ||||
|     display: none; | ||||
| } | ||||
| @@ -25,34 +25,7 @@ div.flex-table { | ||||
|             div.item-col:last-child { | ||||
|                 display: flex; | ||||
|             } | ||||
|  | ||||
|             div.item-two-col-grid { | ||||
|                 display: grid; | ||||
|                 width: 100%; | ||||
|                 justify-content: stretch; | ||||
|  | ||||
|                 @include media-breakpoint-up(lg) { | ||||
|                     grid-template-areas: | ||||
|                         "title aside"; | ||||
|                     grid-template-columns: 1fr minmax(8rem, 1fr); | ||||
|                     column-gap: 0.5em; | ||||
|                 } | ||||
|                 @include media-breakpoint-down(lg) { | ||||
|                     grid-template-areas: | ||||
|                         "aside" | ||||
|                         "title"; | ||||
|                 } | ||||
|  | ||||
|                 & > div.title { | ||||
|                     grid-area: title; | ||||
|                 } | ||||
|  | ||||
|                 & > div.aside { | ||||
|                     grid-area: aside; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     h2, h3, h4, dl, p { | ||||
|   | ||||
| @@ -8,10 +8,10 @@ import { | ||||
|     Heading, | ||||
|     Link, | ||||
|     List, | ||||
| } from 'ckeditor5'; | ||||
| import coreTranslations from 'ckeditor5/translations/fr.js'; | ||||
| } from "ckeditor5"; | ||||
| import coreTranslations from "ckeditor5/translations/fr.js"; | ||||
|  | ||||
| import 'ckeditor5/ckeditor5.css'; | ||||
| import "ckeditor5/ckeditor5.css"; | ||||
|  | ||||
| import "./index.scss"; | ||||
|  | ||||
| @@ -41,8 +41,6 @@ export default { | ||||
|             "redo", | ||||
|         ], | ||||
|     }, | ||||
|     translations: [ | ||||
|         coreTranslations | ||||
|     ], | ||||
|     translations: [coreTranslations], | ||||
|     licenseKey: "GPL", | ||||
| } ; | ||||
| }; | ||||
|   | ||||
| @@ -1,23 +1,12 @@ | ||||
| import App from "../../vuejs/CommentEditor/App.vue" | ||||
| import { createApp, reactive } from "vue"; | ||||
| import config from "./editor_config"; | ||||
| import { ClassicEditor } from "ckeditor5"; | ||||
|  | ||||
| const ckeditorFields: NodeListOf<HTMLTextAreaElement> = | ||||
|     document.querySelectorAll("[id^='comment-app']"); | ||||
|  | ||||
| const globalState = reactive({ | ||||
|     isSimple: localStorage.getItem('editorMode') === 'simple' | ||||
| }); | ||||
| window.addEventListener('storage', () => { | ||||
|     globalState.isSimple = localStorage.getItem('editorMode') === 'simple'; | ||||
| }); | ||||
|  | ||||
|     document.querySelectorAll("textarea[ckeditor]"); | ||||
| ckeditorFields.forEach((field: HTMLTextAreaElement): void => { | ||||
|     const app = createApp(App,{ | ||||
|         fieldName: field.dataset.fieldName, | ||||
|         template: `<app></app>` | ||||
|     ClassicEditor.create(field, config).catch((error) => { | ||||
|         console.error(error.stack); | ||||
|         throw error; | ||||
|     }); | ||||
|  | ||||
|     app.provide('globalState', globalState) | ||||
|         .component("app", App) | ||||
|         .mount(field); | ||||
| }); | ||||
| //Fields.push.apply(Fields, document.querySelectorAll('.cf-fields textarea')); | ||||
|   | ||||
| @@ -10,12 +10,12 @@ let appsPerInput = new Map(); | ||||
|  | ||||
| function loadDynamicPicker(element) { | ||||
|   let apps = element.querySelectorAll('[data-module="pick-dynamic"]'); | ||||
|   let suggested; | ||||
|   let as_id; | ||||
|   let submit_on_adding_new_entity; | ||||
|   let label; | ||||
|  | ||||
|   apps.forEach(function (el) { | ||||
|     let suggested; | ||||
|     let as_id; | ||||
|     let submit_on_adding_new_entity; | ||||
|     let label; | ||||
|     const isMultiple = parseInt(el.dataset.multiple) === 1, | ||||
|       uniqId = el.dataset.uniqid, | ||||
|       input = element.querySelector( | ||||
| @@ -26,12 +26,12 @@ function loadDynamicPicker(element) { | ||||
|         ? JSON.parse(input.value) | ||||
|         : input.value === "[]" || input.value === "" | ||||
|           ? null | ||||
|           : [JSON.parse(input.value)], | ||||
|       suggested = JSON.parse(el.dataset.suggested), | ||||
|       as_id = parseInt(el.dataset.asId) === 1, | ||||
|       submit_on_adding_new_entity = | ||||
|         parseInt(el.dataset.submitOnAddingNewEntity) === 1, | ||||
|       label = el.dataset.label; | ||||
|           : [JSON.parse(input.value)]; | ||||
|     suggested = JSON.parse(el.dataset.suggested); | ||||
|     as_id = parseInt(el.dataset.asId) === 1; | ||||
|     submit_on_adding_new_entity = | ||||
|       parseInt(el.dataset.submitOnAddingNewEntity) === 1; | ||||
|     label = el.dataset.label; | ||||
|  | ||||
|     if (!isMultiple) { | ||||
|       if (input.value === "[]") { | ||||
|   | ||||
| @@ -0,0 +1,45 @@ | ||||
| import { createApp } from "vue"; | ||||
| import OpenWopiLink from "ChillMainAssets/vuejs/_components/OpenWopiLink"; | ||||
| import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n"; | ||||
|  | ||||
| const i18n = _createI18n({}); | ||||
|  | ||||
| //TODO move to chillDocStore or ChillWopi | ||||
|  | ||||
| /* | ||||
|  | ||||
| tags to load module: | ||||
|  | ||||
| <span data-module="wopi-link" | ||||
|     data-wopi-url="{{ path('chill_wopi_file_edit', {'fileId': document.uuid}) }}" | ||||
|     data-doc-type="{{ document.type|e('html_attr') }}" | ||||
|     data-options="{{ options|json_encode }}" | ||||
|         ></span> | ||||
|  | ||||
| */ | ||||
|  | ||||
| window.addEventListener("DOMContentLoaded", function (e) { | ||||
|   document | ||||
|     .querySelectorAll('span[data-module="wopi-link"]') | ||||
|     .forEach(function (el) { | ||||
|       createApp({ | ||||
|         template: | ||||
|           '<open-wopi-link :wopiUrl="wopiUrl" :type="type" :options="options"></open-wopi-link>', | ||||
|         components: { | ||||
|           OpenWopiLink, | ||||
|         }, | ||||
|         data() { | ||||
|           return { | ||||
|             wopiUrl: el.dataset.wopiUrl, | ||||
|             type: el.dataset.docType, | ||||
|             options: | ||||
|               el.dataset.options !== "null" | ||||
|                 ? JSON.parse(el.dataset.options) | ||||
|                 : {}, | ||||
|           }; | ||||
|         }, | ||||
|       }) | ||||
|         .use(i18n) | ||||
|         .mount(el); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,36 +0,0 @@ | ||||
| <template> | ||||
|     <div> | ||||
|         <div> | ||||
|             <comment-editor | ||||
|                 :isSimple="globalState.isSimple" | ||||
|                 :fieldName="fieldName" | ||||
|                 @toggle="toggleEditorMode" | ||||
|                 ></comment-editor> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { defineComponent, inject } from 'vue'; | ||||
| import CommentEditor from "../CommentEditor/component/CommentEditor.vue"; | ||||
|  | ||||
| export default defineComponent({ | ||||
|     name: "App", | ||||
|     components: { CommentEditor }, | ||||
|     props: { | ||||
|         fieldName: String | ||||
|     }, | ||||
|     setup() { | ||||
|         const globalState = inject('globalState'); | ||||
|         const toggleEditorMode = () => { | ||||
|             globalState.isSimple = !globalState.isSimple; | ||||
|             localStorage.setItem('editorMode', globalState.isSimple ? 'simple' : 'rich'); | ||||
|         }; | ||||
|  | ||||
|         return { | ||||
|             globalState, | ||||
|             toggleEditorMode, | ||||
|         }; | ||||
|     } | ||||
| }); | ||||
| </script> | ||||
| @@ -1,58 +0,0 @@ | ||||
| <template> | ||||
|     <div :class="{'editor-container': true, 'rich-editor-active': !isSimple}"> | ||||
|         <div v-if="!isSimple" class="editor-wrapper"> | ||||
|             <ckeditor | ||||
|                 :name="fieldName" | ||||
|                 :editor="classicEditor" | ||||
|                 :config="editorConfig" | ||||
|                 v-model.lazy="content" | ||||
|                 tag-name="textarea" | ||||
|             /> | ||||
|         </div> | ||||
|         <div v-else class="editor-wrapper"> | ||||
|             <textarea | ||||
|                 v-model.lazy="content" | ||||
|                 :name="fieldName" | ||||
|                 class="form-control" | ||||
|             ></textarea> | ||||
|         </div> | ||||
|         <a @click="toggleSimpleEditor" class="toggle-button">{{ isSimple ? "rich" : "simple" }}</a> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts"> | ||||
| import { defineComponent, ref, computed, toRefs } from 'vue'; | ||||
| import { Ckeditor } from "@ckeditor/ckeditor5-vue"; | ||||
| import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config"; | ||||
| import { ClassicEditor } from "ckeditor5"; | ||||
|  | ||||
| export default defineComponent({ | ||||
|     name: "CommentEditor", | ||||
|     components: { | ||||
|         ckeditor: Ckeditor, | ||||
|     }, | ||||
|     props: { | ||||
|         type: String, | ||||
|         isSimple: Boolean, | ||||
|         fieldName: String, | ||||
|     }, | ||||
|     setup(props, { emit }) { | ||||
|         const { isSimple } = toRefs(props); | ||||
|         const content = ref(""); | ||||
|         const classicEditor = ClassicEditor; | ||||
|         const editorConfig = classicEditorConfig; | ||||
|  | ||||
|         const toggleSimpleEditor = () => { | ||||
|             emit("toggle"); | ||||
|         }; | ||||
|  | ||||
|         return { | ||||
|             isSimple, | ||||
|             content, | ||||
|             classicEditor, | ||||
|             editorConfig, | ||||
|             toggleSimpleEditor, | ||||
|         }; | ||||
|     } | ||||
| }); | ||||
| </script> | ||||
| @@ -1,14 +0,0 @@ | ||||
| import {personMessages} from "ChillPersonAssets/vuejs/_js/i18n"; | ||||
| import {calendarUserSelectorMessages} from "ChillCalendarAssets/vuejs/_components/CalendarUserSelector/js/i18n"; | ||||
| import {activityMessages} from "ChillActivityAssets/vuejs/Activity/i18n"; | ||||
|  | ||||
| const appMessages = { | ||||
|   fr: { | ||||
|     mode: { | ||||
|       simple: "Editeur simple", | ||||
|       rich: "Editeur riche" | ||||
|     } | ||||
|   }, | ||||
| }; | ||||
|  | ||||
| export { appMessages }; | ||||
| @@ -45,10 +45,6 @@ const onPickGenericDoc = ({ | ||||
| }) => { | ||||
|     emit("pickGenericDoc", { genericDoc }); | ||||
| }; | ||||
|  | ||||
| const onRemoveAttachment = (payload: { attachment: WorkflowAttachment }) => { | ||||
|     emit("removeAttachment", payload); | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
| @@ -60,7 +56,7 @@ const onRemoveAttachment = (payload: { attachment: WorkflowAttachment }) => { | ||||
|     ></pick-generic-doc-modal> | ||||
|     <attachment-list | ||||
|         :attachments="props.attachments" | ||||
|         @removeAttachment="onRemoveAttachment" | ||||
|         @removeAttachment="(payload) => emit('removeAttachment', payload)" | ||||
|     ></attachment-list> | ||||
|     <ul class="record_actions"> | ||||
|         <li> | ||||
|   | ||||
| @@ -72,14 +72,6 @@ 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[]>(() => { | ||||
|     if (false === loaded.value) { | ||||
|         return []; | ||||
| @@ -253,8 +245,10 @@ const filteredDocuments = computed<GenericDocForAccompanyingPeriod[]>(() => { | ||||
|                 :accompanying-period-id="accompanyingPeriodId" | ||||
|                 :genericDoc="g" | ||||
|                 :is-picked="isPicked(g)" | ||||
|                 @pickGenericDoc="onPickDocument" | ||||
|                 @removeGenericDoc="onRemoveGenericDoc" | ||||
|                 @pickGenericDoc="(payload) => emit('pickGenericDoc', payload)" | ||||
|                 @removeGenericDoc=" | ||||
|                     (payload) => emit('removeGenericDoc', payload) | ||||
|                 " | ||||
|             ></pick-generic-doc-item> | ||||
|         </div> | ||||
|         <div v-else class="text-center chill-no-data-statement"> | ||||
|   | ||||
| @@ -26,9 +26,9 @@ | ||||
|                 trans(THIRDPARTY_CONTACT_OF) | ||||
|             }}</span> | ||||
|             <span v-else-if="props.entity.kind === 'company'">{{ | ||||
|                 trans(THIRDPARTY_A_COMPANY) | ||||
|                 trans(THIRDPARTY_A_CONTACT) | ||||
|             }}</span> | ||||
|             <span v-else>{{ trans(THIRDPARTY_A_CONTACT) }}</span> | ||||
|             <span v-else>{{ $t("thirdparty.contact") }}</span> | ||||
|         </template> | ||||
|     </span> | ||||
|  | ||||
| @@ -54,7 +54,6 @@ import { | ||||
|     ACCEPTED_USERS, | ||||
|     THIRDPARTY_A_CONTACT, | ||||
|     THIRDPARTY_CONTACT_OF, | ||||
|     THIRDPARTY_A_COMPANY, | ||||
|     PERSON, | ||||
|     THIRDPARTY, | ||||
| } from "translator"; | ||||
|   | ||||
| @@ -0,0 +1,214 @@ | ||||
| <template> | ||||
|     <a | ||||
|         v-if="isOpenDocument" | ||||
|         class="btn" | ||||
|         :class="[ | ||||
|             isChangeIcon ? 'change-icon' : '', | ||||
|             isChangeClass ? options.changeClass : 'btn-wopilink', | ||||
|         ]" | ||||
|         @click="openModal" | ||||
|     > | ||||
|         <i v-if="isChangeIcon" class="fa me-2" :class="options.changeIcon"></i> | ||||
|  | ||||
|         <span v-if="!noText"> | ||||
|             {{ trans(WOPI_ONLINE_EDIT_DOCUMENT) }} | ||||
|         </span> | ||||
|     </a> | ||||
|  | ||||
|     <teleport to="body"> | ||||
|         <div class="wopi-frame" v-if="isOpenDocument"> | ||||
|             <modal | ||||
|                 v-if="modal.showModal" | ||||
|                 :modalDialogClass="modal.modalDialogClass" | ||||
|                 :hideFooter="true" | ||||
|                 @close="modal.showModal = false" | ||||
|             > | ||||
|                 <template #header> | ||||
|                     <img class="logo" :src="logo" height="45" /> | ||||
|                     <span class="ms-auto me-3"> | ||||
|                         <span v-if="options.title">{{ options.title }}</span> | ||||
|                     </span> | ||||
|                 </template> | ||||
|  | ||||
|                 <template #body> | ||||
|                     <div v-if="loading" class="loading"> | ||||
|                         <i | ||||
|                             class="fa fa-circle-o-notch fa-spin fa-3x" | ||||
|                             :title="trans(WOPI_LOADING)" | ||||
|                         ></i> | ||||
|                     </div> | ||||
|                     <iframe :src="this.wopiUrl" @load="loaded"></iframe> | ||||
|                 </template> | ||||
|             </modal> | ||||
|         </div> | ||||
|         <div v-else> | ||||
|             <Modal | ||||
|                 v-if="modal.showModal" | ||||
|                 modalDialogClass="modal-sm" | ||||
|                 @close="modal.showModal = false" | ||||
|             > | ||||
|                 <template v-slot:header> | ||||
|                     <h3>{{ trans(WOPI_INVALID_TITLE) }}</h3> | ||||
|                 </template> | ||||
|                 <template v-slot:body> | ||||
|                     <div class="alert alert-warning"> | ||||
|                         {{ trans(WOPI_ONLINE_EDIT_DOCUMENT) }} | ||||
|                     </div> | ||||
|                 </template> | ||||
|             </Modal> | ||||
|         </div> | ||||
|     </teleport> | ||||
| </template> | ||||
|  | ||||
| <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 logo from "ChillMainAssets/chill/img/logo-chill-sans-slogan_white.png"; | ||||
|  | ||||
| // Props | ||||
| const props = defineProps({ | ||||
|     wopiUrl: { | ||||
|         type: String, | ||||
|         required: true, | ||||
|     }, | ||||
|     type: { | ||||
|         type: String, | ||||
|         required: true, | ||||
|     }, | ||||
|     options: { | ||||
|         type: Object, | ||||
|         required: false, | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| // 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> | ||||
|  | ||||
| <style lang="scss"> | ||||
| div.wopi-frame { | ||||
|     div.modal-header { | ||||
|         border-bottom: 0; | ||||
|         background-color: var(--bs-primary); | ||||
|         color: white; | ||||
|     } | ||||
|     div.modal-body { | ||||
|         padding: 0; | ||||
|         overflow-y: unset !important; | ||||
|         iframe { | ||||
|             height: 100%; | ||||
|             width: 100%; | ||||
|         } | ||||
|         div.loading { | ||||
|             position: absolute; | ||||
|             color: var(--bs-chill-gray); | ||||
|             top: calc(50% - 30px); | ||||
|             left: calc(50% - 30px); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| </style> | ||||
| @@ -54,11 +54,6 @@ const messages = { | ||||
|             residential_address: "Adresse de résidence", | ||||
|             located_at: "réside chez", | ||||
|         }, | ||||
|         comment: { | ||||
|             label: "Commentaire", | ||||
|             editor_simple: "Simple", | ||||
|             editor_rich: "Riche" | ||||
|         } | ||||
|     }, | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -136,59 +136,6 @@ | ||||
|   </div> | ||||
| </div> | ||||
|  | ||||
| <h2>Fix the title in the flex table</h2> | ||||
|  | ||||
| <p>This will fix the layout of the row, with a "title" element, and an aside element. Using <code>css grid</code>, this is quite safe and won't overflow</p> | ||||
|  | ||||
| <xmp> | ||||
|     <div class="flex-table"> | ||||
|         <div class="item-bloc"> | ||||
|             <div class="item-row"> | ||||
|                 <div class="item-two-col-grid"> | ||||
|                     <div class="title">This is my title</div> | ||||
|                     <div class="aside">Aside value</div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="item-bloc"> | ||||
|             <div class="item-row"> | ||||
|                 <div class="item-two-col-grid"> | ||||
|                     <div class="title"> | ||||
|                         <div><h3>This is my title, which can be very long and take a lot of place. But it is wrapped successfully, and won't disturb the placement of the aside block</h3></div> | ||||
|                         <div>This is a second line</div> | ||||
|                     </div> | ||||
|                     <div class="aside">Aside value</div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </xmp> | ||||
|  | ||||
|     <p>will render:</p> | ||||
|  | ||||
|     <div class="flex-table"> | ||||
|         <div class="item-bloc"> | ||||
|             <div class="item-row"> | ||||
|                 <div class="item-two-col-grid"> | ||||
|                     <div class="title">This is my title</div> | ||||
|                     <div class="aside">Aside value</div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="item-bloc"> | ||||
|             <div class="item-row"> | ||||
|                 <div class="item-two-col-grid"> | ||||
|                     <div class="title"> | ||||
|                         <div><h3>This is my title, which can be very long and take a lot of place. But it is wrapped successfully, and won't disturb the placement of the aside block</h3></div> | ||||
|                         <div>This is a second line</div> | ||||
|                     </div> | ||||
|                     <div class="aside">Aside value</div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|  | ||||
| <h2>Wrap-list</h2> | ||||
| <p>Une liste inline qui s'aligne, puis glisse sous son titre.</p> | ||||
| <div class="wrap-list debug"> | ||||
| @@ -445,12 +392,4 @@ Toutes les classes btn-* de bootstrap sont fonctionnelles | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| <div class="row"> | ||||
|     <h1>Badges</h1> | ||||
|  | ||||
|     <span class="badge-accompanying-work-type-simple">Action d'accompagnement</span> | ||||
|     <span class="badge-activity-type-simple">Type d'échange</span> | ||||
|     <span class="badge-calendar-simple">Rendez-vous</span> | ||||
| </div> | ||||
|  | ||||
| {% endblock %} | ||||
|   | ||||
| @@ -214,9 +214,7 @@ | ||||
|  | ||||
| {% block private_comment_widget %} | ||||
|     {% for entry in form %} | ||||
|         <div id="comment-app-{{ form.vars.id }}" data-field-name="{{ form.vars.full_name }}"> | ||||
|             {{ form_widget(entry, { attr: { ckeditor: 'true' } }) }} | ||||
|         </div> | ||||
|         {{ form_widget(entry) }} | ||||
|     {% endfor %} | ||||
| {% endblock %} | ||||
|  | ||||
| @@ -226,9 +224,7 @@ | ||||
|  | ||||
| {% block comment_widget %} | ||||
|     {% for entry in form %} | ||||
|         <div id="comment-app-{{ form.vars.id }}" data-field-name="{{ form.vars.full_name }}"> | ||||
|             {{ form_widget(entry, { attr: { ckeditor: 'true' } }) }} | ||||
|         </div> | ||||
|         {{ form_widget(entry) }} | ||||
|     {% endfor %} | ||||
| {% endblock comment_widget %} | ||||
|  | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user