mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			feature-in
			...
			feature-ac
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | dc58a5673b | 
| @@ -221,12 +221,22 @@ lint.per-file-ignores."src/documents/parsers.py" = [ | |||||||
| lint.per-file-ignores."src/documents/signals/handlers.py" = [ | lint.per-file-ignores."src/documents/signals/handlers.py" = [ | ||||||
|   "PTH", |   "PTH", | ||||||
| ] # TODO Enable & remove | ] # TODO Enable & remove | ||||||
|  | lint.per-file-ignores."src/documents/views.py" = [ | ||||||
|  |   "PTH", | ||||||
|  | ] # TODO Enable & remove | ||||||
|  | lint.per-file-ignores."src/paperless/checks.py" = [ | ||||||
|  |   "PTH", | ||||||
|  | ] # TODO Enable & remove | ||||||
| lint.per-file-ignores."src/paperless/settings.py" = [ | lint.per-file-ignores."src/paperless/settings.py" = [ | ||||||
|   "PTH", |   "PTH", | ||||||
| ] # TODO Enable & remove | ] # TODO Enable & remove | ||||||
|  | lint.per-file-ignores."src/paperless_mail/mail.py" = [ | ||||||
|  |   "PTH", | ||||||
|  | ] # TODO Enable & remove | ||||||
| lint.per-file-ignores."src/paperless_tesseract/tests/test_parser.py" = [ | lint.per-file-ignores."src/paperless_tesseract/tests/test_parser.py" = [ | ||||||
|  |   "PTH", | ||||||
|   "RUF001", |   "RUF001", | ||||||
| ] | ] # TODO PTH Enable & remove | ||||||
| lint.isort.force-single-line = true | lint.isort.force-single-line = true | ||||||
|  |  | ||||||
| [tool.pytest.ini_options] | [tool.pytest.ini_options] | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ module.exports = { | |||||||
|     'abstract-paperless-service', |     'abstract-paperless-service', | ||||||
|   ], |   ], | ||||||
|   transformIgnorePatterns: [ |   transformIgnorePatterns: [ | ||||||
|     `<rootDir>/node_modules/.pnpm/(?!.*\\.mjs$|lodash-es|@angular\\+common.*locales)`, |     `<rootDir>/node_modules/.pnpm/(?!.*\\.mjs$|lodash-es)`, | ||||||
|   ], |   ], | ||||||
|   moduleNameMapper: { |   moduleNameMapper: { | ||||||
|     '^src/(.*)': '<rootDir>/src/$1', |     '^src/(.*)': '<rootDir>/src/$1', | ||||||
|   | |||||||
| @@ -5,14 +5,14 @@ | |||||||
|       <trans-unit id="ngb.alert.close" datatype="html"> |       <trans-unit id="ngb.alert.close" datatype="html"> | ||||||
|         <source>Close</source> |         <source>Close</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/alert/alert.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/alert/alert.ts</context> | ||||||
|           <context context-type="linenumber">51</context> |           <context context-type="linenumber">51</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.carousel.slide-number" datatype="html"> |       <trans-unit id="ngb.carousel.slide-number" datatype="html"> | ||||||
|         <source> Slide <x id="INTERPOLATION" equiv-text="ueryList<NgbSli"/> of <x id="INTERPOLATION_1" equiv-text="EventSource = N"/> </source> |         <source> Slide <x id="INTERPOLATION" equiv-text="ueryList<NgbSli"/> of <x id="INTERPOLATION_1" equiv-text="EventSource = N"/> </source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/carousel/carousel.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/carousel/carousel.ts</context> | ||||||
|           <context context-type="linenumber">132,136</context> |           <context context-type="linenumber">132,136</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|         <note priority="1" from="description">Currently selected slide number read by screen reader</note> |         <note priority="1" from="description">Currently selected slide number read by screen reader</note> | ||||||
| @@ -20,212 +20,212 @@ | |||||||
|       <trans-unit id="ngb.carousel.previous" datatype="html"> |       <trans-unit id="ngb.carousel.previous" datatype="html"> | ||||||
|         <source>Previous</source> |         <source>Previous</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/carousel/carousel.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/carousel/carousel.ts</context> | ||||||
|           <context context-type="linenumber">158,160</context> |           <context context-type="linenumber">158,160</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.carousel.next" datatype="html"> |       <trans-unit id="ngb.carousel.next" datatype="html"> | ||||||
|         <source>Next</source> |         <source>Next</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/carousel/carousel.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/carousel/carousel.ts</context> | ||||||
|           <context context-type="linenumber">199</context> |           <context context-type="linenumber">199</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.datepicker.previous-month" datatype="html"> |       <trans-unit id="ngb.datepicker.previous-month" datatype="html"> | ||||||
|         <source>Previous month</source> |         <source>Previous month</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/datepicker/datepicker-navigation.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/datepicker/datepicker-navigation.ts</context> | ||||||
|           <context context-type="linenumber">77,79</context> |           <context context-type="linenumber">77,79</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/datepicker/datepicker-navigation.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/datepicker/datepicker-navigation.ts</context> | ||||||
|           <context context-type="linenumber">102</context> |           <context context-type="linenumber">102</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.datepicker.next-month" datatype="html"> |       <trans-unit id="ngb.datepicker.next-month" datatype="html"> | ||||||
|         <source>Next month</source> |         <source>Next month</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/datepicker/datepicker-navigation.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/datepicker/datepicker-navigation.ts</context> | ||||||
|           <context context-type="linenumber">102</context> |           <context context-type="linenumber">102</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/datepicker/datepicker-navigation.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/datepicker/datepicker-navigation.ts</context> | ||||||
|           <context context-type="linenumber">102</context> |           <context context-type="linenumber">102</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.HH" datatype="html"> |       <trans-unit id="ngb.timepicker.HH" datatype="html"> | ||||||
|         <source>HH</source> |         <source>HH</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.toast.close-aria" datatype="html"> |       <trans-unit id="ngb.toast.close-aria" datatype="html"> | ||||||
|         <source>Close</source> |         <source>Close</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.datepicker.select-month" datatype="html"> |       <trans-unit id="ngb.datepicker.select-month" datatype="html"> | ||||||
|         <source>Select month</source> |         <source>Select month</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.pagination.first" datatype="html"> |       <trans-unit id="ngb.pagination.first" datatype="html"> | ||||||
|         <source>««</source> |         <source>««</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.hours" datatype="html"> |       <trans-unit id="ngb.timepicker.hours" datatype="html"> | ||||||
|         <source>Hours</source> |         <source>Hours</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.pagination.previous" datatype="html"> |       <trans-unit id="ngb.pagination.previous" datatype="html"> | ||||||
|         <source>«</source> |         <source>«</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.MM" datatype="html"> |       <trans-unit id="ngb.timepicker.MM" datatype="html"> | ||||||
|         <source>MM</source> |         <source>MM</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.pagination.next" datatype="html"> |       <trans-unit id="ngb.pagination.next" datatype="html"> | ||||||
|         <source>»</source> |         <source>»</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.datepicker.select-year" datatype="html"> |       <trans-unit id="ngb.datepicker.select-year" datatype="html"> | ||||||
|         <source>Select year</source> |         <source>Select year</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.minutes" datatype="html"> |       <trans-unit id="ngb.timepicker.minutes" datatype="html"> | ||||||
|         <source>Minutes</source> |         <source>Minutes</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.pagination.last" datatype="html"> |       <trans-unit id="ngb.pagination.last" datatype="html"> | ||||||
|         <source>»»</source> |         <source>»»</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.pagination.first-aria" datatype="html"> |       <trans-unit id="ngb.pagination.first-aria" datatype="html"> | ||||||
|         <source>First</source> |         <source>First</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.increment-hours" datatype="html"> |       <trans-unit id="ngb.timepicker.increment-hours" datatype="html"> | ||||||
|         <source>Increment hours</source> |         <source>Increment hours</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.pagination.previous-aria" datatype="html"> |       <trans-unit id="ngb.pagination.previous-aria" datatype="html"> | ||||||
|         <source>Previous</source> |         <source>Previous</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.decrement-hours" datatype="html"> |       <trans-unit id="ngb.timepicker.decrement-hours" datatype="html"> | ||||||
|         <source>Decrement hours</source> |         <source>Decrement hours</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.pagination.next-aria" datatype="html"> |       <trans-unit id="ngb.pagination.next-aria" datatype="html"> | ||||||
|         <source>Next</source> |         <source>Next</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.increment-minutes" datatype="html"> |       <trans-unit id="ngb.timepicker.increment-minutes" datatype="html"> | ||||||
|         <source>Increment minutes</source> |         <source>Increment minutes</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.pagination.last-aria" datatype="html"> |       <trans-unit id="ngb.pagination.last-aria" datatype="html"> | ||||||
|         <source>Last</source> |         <source>Last</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.decrement-minutes" datatype="html"> |       <trans-unit id="ngb.timepicker.decrement-minutes" datatype="html"> | ||||||
|         <source>Decrement minutes</source> |         <source>Decrement minutes</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.SS" datatype="html"> |       <trans-unit id="ngb.timepicker.SS" datatype="html"> | ||||||
|         <source>SS</source> |         <source>SS</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.seconds" datatype="html"> |       <trans-unit id="ngb.timepicker.seconds" datatype="html"> | ||||||
|         <source>Seconds</source> |         <source>Seconds</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.increment-seconds" datatype="html"> |       <trans-unit id="ngb.timepicker.increment-seconds" datatype="html"> | ||||||
|         <source>Increment seconds</source> |         <source>Increment seconds</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.decrement-seconds" datatype="html"> |       <trans-unit id="ngb.timepicker.decrement-seconds" datatype="html"> | ||||||
|         <source>Decrement seconds</source> |         <source>Decrement seconds</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="ngb.timepicker.PM" datatype="html"> |       <trans-unit id="ngb.timepicker.PM" datatype="html"> | ||||||
|         <source><x id="INTERPOLATION"/></source> |         <source><x id="INTERPOLATION"/></source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/ngb-config.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/ngb-config.ts</context> | ||||||
|           <context context-type="linenumber">13</context> |           <context context-type="linenumber">13</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
| @@ -233,7 +233,7 @@ | |||||||
|         <source><x id="INTERPOLATION" equiv-text="barConfig); |         <source><x id="INTERPOLATION" equiv-text="barConfig); | ||||||
| 	pu"/></source> | 	pu"/></source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.14_@angular+core@19.2.14_rxjs@7._f368c1e2c12c71d00515f6f30d8f21d1/node_modules/src/progressbar/progressbar.ts</context> |           <context context-type="sourcefile">node_modules/.pnpm/@ng-bootstrap+ng-bootstrap@18.0.0_@angular+common@19.2.13_@angular+core@19.2.14_rxjs@7._ce5a45f3b9d5ca136f928f24177f8d04/node_modules/src/progressbar/progressbar.ts</context> | ||||||
|           <context context-type="linenumber">41,42</context> |           <context context-type="linenumber">41,42</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
|   "private": true, |   "private": true, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@angular/cdk": "^19.2.14", |     "@angular/cdk": "^19.2.14", | ||||||
|     "@angular/common": "~19.2.14", |     "@angular/common": "~19.2.13", | ||||||
|     "@angular/compiler": "~19.2.14", |     "@angular/compiler": "~19.2.14", | ||||||
|     "@angular/core": "~19.2.14", |     "@angular/core": "~19.2.14", | ||||||
|     "@angular/forms": "~19.2.14", |     "@angular/forms": "~19.2.14", | ||||||
|   | |||||||
							
								
								
									
										130
									
								
								src-ui/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										130
									
								
								src-ui/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							| @@ -10,10 +10,10 @@ importers: | |||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/cdk': |       '@angular/cdk': | ||||||
|         specifier: ^19.2.14 |         specifier: ^19.2.14 | ||||||
|         version: 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |         version: 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/common': |       '@angular/common': | ||||||
|         specifier: ~19.2.14 |         specifier: ~19.2.13 | ||||||
|         version: 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |         version: 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/compiler': |       '@angular/compiler': | ||||||
|         specifier: ~19.2.14 |         specifier: ~19.2.14 | ||||||
|         version: 19.2.14 |         version: 19.2.14 | ||||||
| @@ -22,28 +22,28 @@ importers: | |||||||
|         version: 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |         version: 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/forms': |       '@angular/forms': | ||||||
|         specifier: ~19.2.14 |         specifier: ~19.2.14 | ||||||
|         version: 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) |         version: 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) | ||||||
|       '@angular/localize': |       '@angular/localize': | ||||||
|         specifier: ~19.2.14 |         specifier: ~19.2.14 | ||||||
|         version: 19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14) |         version: 19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14) | ||||||
|       '@angular/platform-browser': |       '@angular/platform-browser': | ||||||
|         specifier: ~19.2.14 |         specifier: ~19.2.14 | ||||||
|         version: 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) |         version: 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) | ||||||
|       '@angular/platform-browser-dynamic': |       '@angular/platform-browser-dynamic': | ||||||
|         specifier: ~19.2.14 |         specifier: ~19.2.14 | ||||||
|         version: 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))) |         version: 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))) | ||||||
|       '@angular/router': |       '@angular/router': | ||||||
|         specifier: ~19.2.14 |         specifier: ~19.2.14 | ||||||
|         version: 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) |         version: 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) | ||||||
|       '@ng-bootstrap/ng-bootstrap': |       '@ng-bootstrap/ng-bootstrap': | ||||||
|         specifier: ^18.0.0 |         specifier: ^18.0.0 | ||||||
|         version: 18.0.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@popperjs/core@2.11.8)(rxjs@7.8.2) |         version: 18.0.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@popperjs/core@2.11.8)(rxjs@7.8.2) | ||||||
|       '@ng-select/ng-select': |       '@ng-select/ng-select': | ||||||
|         specifier: ^14.9.0 |         specifier: ^14.9.0 | ||||||
|         version: 14.9.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)) |         version: 14.9.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)) | ||||||
|       '@ngneat/dirty-check-forms': |       '@ngneat/dirty-check-forms': | ||||||
|         specifier: ^3.0.3 |         specifier: ^3.0.3 | ||||||
|         version: 3.0.3(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/router@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(lodash-es@4.17.21)(rxjs@7.8.2) |         version: 3.0.3(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/router@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(lodash-es@4.17.21)(rxjs@7.8.2) | ||||||
|       '@popperjs/core': |       '@popperjs/core': | ||||||
|         specifier: ^2.11.8 |         specifier: ^2.11.8 | ||||||
|         version: 2.11.8 |         version: 2.11.8 | ||||||
| @@ -61,19 +61,19 @@ importers: | |||||||
|         version: 10.4.0 |         version: 10.4.0 | ||||||
|       ngx-bootstrap-icons: |       ngx-bootstrap-icons: | ||||||
|         specifier: ^1.9.3 |         specifier: ^1.9.3 | ||||||
|         version: 1.9.3(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) |         version: 1.9.3(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) | ||||||
|       ngx-color: |       ngx-color: | ||||||
|         specifier: ^10.0.0 |         specifier: ^10.0.0 | ||||||
|         version: 10.0.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) |         version: 10.0.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) | ||||||
|       ngx-cookie-service: |       ngx-cookie-service: | ||||||
|         specifier: ^19.1.2 |         specifier: ^19.1.2 | ||||||
|         version: 19.1.2(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) |         version: 19.1.2(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) | ||||||
|       ngx-device-detector: |       ngx-device-detector: | ||||||
|         specifier: ^9.0.0 |         specifier: ^9.0.0 | ||||||
|         version: 9.0.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) |         version: 9.0.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) | ||||||
|       ngx-ui-tour-ng-bootstrap: |       ngx-ui-tour-ng-bootstrap: | ||||||
|         specifier: ^16.0.0 |         specifier: ^16.0.0 | ||||||
|         version: 16.0.0(b22d6d97efbc9cb8f9e09ff61a244f2e) |         version: 16.0.0(f0e74b8bab83f30cf77f70d2cc04d4ae) | ||||||
|       rxjs: |       rxjs: | ||||||
|         specifier: ^7.8.2 |         specifier: ^7.8.2 | ||||||
|         version: 7.8.2 |         version: 7.8.2 | ||||||
| @@ -95,7 +95,7 @@ importers: | |||||||
|         version: 19.0.1(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14)(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@types/node@22.15.29)(chokidar@4.0.3)(jest-environment-jsdom@29.7.0)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jiti@1.21.7)(typescript@5.5.4)(vite@6.2.7(@types/node@22.15.29)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.7.0))(yaml@2.7.0) |         version: 19.0.1(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14)(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@types/node@22.15.29)(chokidar@4.0.3)(jest-environment-jsdom@29.7.0)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jiti@1.21.7)(typescript@5.5.4)(vite@6.2.7(@types/node@22.15.29)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.7.0))(yaml@2.7.0) | ||||||
|       '@angular-builders/jest': |       '@angular-builders/jest': | ||||||
|         specifier: ^19.0.1 |         specifier: ^19.0.1 | ||||||
|         version: 19.0.1(4b49eb59c0a92e3dbc1542019395d573) |         version: 19.0.1(a3a7a7b7cf5c06373f7925dd32bde0cb) | ||||||
|       '@angular-devkit/build-angular': |       '@angular-devkit/build-angular': | ||||||
|         specifier: ^19.2.14 |         specifier: ^19.2.14 | ||||||
|         version: 19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14)(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@types/node@22.15.29)(chokidar@4.0.3)(jest-environment-jsdom@29.7.0)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jiti@1.21.7)(typescript@5.5.4)(vite@6.2.7(@types/node@22.15.29)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.7.0))(yaml@2.7.0) |         version: 19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14)(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@types/node@22.15.29)(chokidar@4.0.3)(jest-environment-jsdom@29.7.0)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jiti@1.21.7)(typescript@5.5.4)(vite@6.2.7(@types/node@22.15.29)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.7.0))(yaml@2.7.0) | ||||||
| @@ -161,7 +161,7 @@ importers: | |||||||
|         version: 16.0.0 |         version: 16.0.0 | ||||||
|       jest-preset-angular: |       jest-preset-angular: | ||||||
|         specifier: ^14.5.5 |         specifier: ^14.5.5 | ||||||
|         version: 14.5.5(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))))(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jsdom@20.0.3)(typescript@5.5.4) |         version: 14.5.5(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))))(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jsdom@20.0.3)(typescript@5.5.4) | ||||||
|       jest-websocket-mock: |       jest-websocket-mock: | ||||||
|         specifier: ^2.5.0 |         specifier: ^2.5.0 | ||||||
|         version: 2.5.0 |         version: 2.5.0 | ||||||
| @@ -386,11 +386,11 @@ packages: | |||||||
|     engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} |     engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} | ||||||
|     hasBin: true |     hasBin: true | ||||||
|  |  | ||||||
|   '@angular/common@19.2.14': |   '@angular/common@19.2.13': | ||||||
|     resolution: {integrity: sha512-NcNklcuyqaTjOVGf7aru8APX9mjsnZ01gFZrn47BxHozhaR0EMRrotYQTdi8YdVjPkeYFYanVntSLfhyobq/jg==} |     resolution: {integrity: sha512-k7I4bLH+bgI02VL81MaL0NcZPfVl153KAiARwk+ZlkmQjMnWlmsAHQ6054SWoNEXwP855ATR6YYDVqJh8TZaqw==} | ||||||
|     engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} |     engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
|       '@angular/core': 19.2.14 |       '@angular/core': 19.2.13 | ||||||
|       rxjs: ^6.5.3 || ^7.4.0 |       rxjs: ^6.5.3 || ^7.4.0 | ||||||
|  |  | ||||||
|   '@angular/compiler-cli@19.2.14': |   '@angular/compiler-cli@19.2.14': | ||||||
| @@ -6141,7 +6141,7 @@ snapshots: | |||||||
|       - webpack-cli |       - webpack-cli | ||||||
|       - yaml |       - yaml | ||||||
|  |  | ||||||
|   '@angular-builders/jest@19.0.1(4b49eb59c0a92e3dbc1542019395d573)': |   '@angular-builders/jest@19.0.1(a3a7a7b7cf5c06373f7925dd32bde0cb)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular-builders/common': 3.0.1(@types/node@22.15.29)(chokidar@4.0.3)(typescript@5.5.4) |       '@angular-builders/common': 3.0.1(@types/node@22.15.29)(chokidar@4.0.3)(typescript@5.5.4) | ||||||
|       '@angular-devkit/architect': 0.1902.8(chokidar@4.0.3) |       '@angular-devkit/architect': 0.1902.8(chokidar@4.0.3) | ||||||
| @@ -6149,9 +6149,9 @@ snapshots: | |||||||
|       '@angular-devkit/core': 19.2.14(chokidar@4.0.3) |       '@angular-devkit/core': 19.2.14(chokidar@4.0.3) | ||||||
|       '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4) |       '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/platform-browser-dynamic': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))) |       '@angular/platform-browser-dynamic': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))) | ||||||
|       jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)) |       jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)) | ||||||
|       jest-preset-angular: 14.5.4(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))))(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jsdom@20.0.3)(typescript@5.5.4) |       jest-preset-angular: 14.5.4(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))))(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jsdom@20.0.3)(typescript@5.5.4) | ||||||
|       lodash: 4.17.21 |       lodash: 4.17.21 | ||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - '@babel/core' |       - '@babel/core' | ||||||
| @@ -6422,9 +6422,9 @@ snapshots: | |||||||
|       - tsx |       - tsx | ||||||
|       - yaml |       - yaml | ||||||
|  |  | ||||||
|   '@angular/cdk@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': |   '@angular/cdk@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       parse5: 7.3.0 |       parse5: 7.3.0 | ||||||
|       rxjs: 7.8.2 |       rxjs: 7.8.2 | ||||||
| @@ -6454,7 +6454,7 @@ snapshots: | |||||||
|       - chokidar |       - chokidar | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
|   '@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': |   '@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       rxjs: 7.8.2 |       rxjs: 7.8.2 | ||||||
| @@ -6485,11 +6485,11 @@ snapshots: | |||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|       zone.js: 0.15.1 |       zone.js: 0.15.1 | ||||||
|  |  | ||||||
|   '@angular/forms@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': |   '@angular/forms@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/platform-browser': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) |       '@angular/platform-browser': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) | ||||||
|       rxjs: 7.8.2 |       rxjs: 7.8.2 | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
| @@ -6504,25 +6504,25 @@ snapshots: | |||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|  |  | ||||||
|   '@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))': |   '@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/compiler': 19.2.14 |       '@angular/compiler': 19.2.14 | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/platform-browser': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) |       '@angular/platform-browser': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   '@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))': |   '@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   '@angular/router@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': |   '@angular/router@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/platform-browser': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) |       '@angular/platform-browser': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)) | ||||||
|       rxjs: 7.8.2 |       rxjs: 7.8.2 | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
| @@ -8103,28 +8103,28 @@ snapshots: | |||||||
|       '@napi-rs/nice-win32-x64-msvc': 1.0.1 |       '@napi-rs/nice-win32-x64-msvc': 1.0.1 | ||||||
|     optional: true |     optional: true | ||||||
|  |  | ||||||
|   '@ng-bootstrap/ng-bootstrap@18.0.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@popperjs/core@2.11.8)(rxjs@7.8.2)': |   '@ng-bootstrap/ng-bootstrap@18.0.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@popperjs/core@2.11.8)(rxjs@7.8.2)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/forms': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) |       '@angular/forms': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) | ||||||
|       '@angular/localize': 19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14) |       '@angular/localize': 19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14) | ||||||
|       '@popperjs/core': 2.11.8 |       '@popperjs/core': 2.11.8 | ||||||
|       rxjs: 7.8.2 |       rxjs: 7.8.2 | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   '@ng-select/ng-select@14.9.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))': |   '@ng-select/ng-select@14.9.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/forms': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) |       '@angular/forms': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   '@ngneat/dirty-check-forms@3.0.3(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/router@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(lodash-es@4.17.21)(rxjs@7.8.2)': |   '@ngneat/dirty-check-forms@3.0.3(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/router@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(lodash-es@4.17.21)(rxjs@7.8.2)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/forms': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) |       '@angular/forms': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) | ||||||
|       '@angular/router': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) |       '@angular/router': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) | ||||||
|       lodash-es: 4.17.21 |       lodash-es: 4.17.21 | ||||||
|       rxjs: 7.8.2 |       rxjs: 7.8.2 | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
| @@ -10471,11 +10471,11 @@ snapshots: | |||||||
|     optionalDependencies: |     optionalDependencies: | ||||||
|       jest-resolve: 29.7.0 |       jest-resolve: 29.7.0 | ||||||
|  |  | ||||||
|   jest-preset-angular@14.5.4(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))))(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jsdom@20.0.3)(typescript@5.5.4): |   jest-preset-angular@14.5.4(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))))(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jsdom@20.0.3)(typescript@5.5.4): | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4) |       '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/platform-browser-dynamic': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))) |       '@angular/platform-browser-dynamic': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))) | ||||||
|       bs-logger: 0.2.6 |       bs-logger: 0.2.6 | ||||||
|       esbuild-wasm: 0.25.3 |       esbuild-wasm: 0.25.3 | ||||||
|       jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)) |       jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)) | ||||||
| @@ -10497,11 +10497,11 @@ snapshots: | |||||||
|       - supports-color |       - supports-color | ||||||
|       - utf-8-validate |       - utf-8-validate | ||||||
|  |  | ||||||
|   jest-preset-angular@14.5.5(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))))(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jsdom@20.0.3)(typescript@5.5.4): |   jest-preset-angular@14.5.5(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser-dynamic@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))))(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)))(jsdom@20.0.3)(typescript@5.5.4): | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4) |       '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/platform-browser-dynamic': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))) |       '@angular/platform-browser-dynamic': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@19.2.14)(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))) | ||||||
|       bs-logger: 0.2.6 |       bs-logger: 0.2.6 | ||||||
|       esbuild-wasm: 0.25.2 |       esbuild-wasm: 0.25.2 | ||||||
|       jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)) |       jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.5.4)) | ||||||
| @@ -11093,46 +11093,46 @@ snapshots: | |||||||
|       pdfjs-dist: 4.8.69 |       pdfjs-dist: 4.8.69 | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   ngx-bootstrap-icons@1.9.3(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)): |   ngx-bootstrap-icons@1.9.3(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)): | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   ngx-color@10.0.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)): |   ngx-color@10.0.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)): | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@ctrl/tinycolor': 4.1.0 |       '@ctrl/tinycolor': 4.1.0 | ||||||
|       material-colors: 1.2.6 |       material-colors: 1.2.6 | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   ngx-cookie-service@19.1.2(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)): |   ngx-cookie-service@19.1.2(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)): | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   ngx-device-detector@9.0.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)): |   ngx-device-detector@9.0.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)): | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   ngx-ui-tour-core@14.0.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/router@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(rxjs@7.8.2): |   ngx-ui-tour-core@14.0.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/router@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(rxjs@7.8.2): | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@angular/router': 19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) |       '@angular/router': 19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) | ||||||
|       rxjs: 7.8.2 |       rxjs: 7.8.2 | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|  |  | ||||||
|   ngx-ui-tour-ng-bootstrap@16.0.0(b22d6d97efbc9cb8f9e09ff61a244f2e): |   ngx-ui-tour-ng-bootstrap@16.0.0(f0e74b8bab83f30cf77f70d2cc04d4ae): | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@angular/common': 19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) |       '@angular/common': 19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) | ||||||
|       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) |       '@angular/core': 19.2.14(rxjs@7.8.2)(zone.js@0.15.1) | ||||||
|       '@ng-bootstrap/ng-bootstrap': 18.0.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@popperjs/core@2.11.8)(rxjs@7.8.2) |       '@ng-bootstrap/ng-bootstrap': 18.0.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/localize@19.2.14(@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.5.4))(@angular/compiler@19.2.14))(@popperjs/core@2.11.8)(rxjs@7.8.2) | ||||||
|       ngx-ui-tour-core: 14.0.0(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/router@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(rxjs@7.8.2) |       ngx-ui-tour-core: 14.0.0(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/router@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/common@19.2.13(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(rxjs@7.8.2) | ||||||
|       tslib: 2.8.1 |       tslib: 2.8.1 | ||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - '@angular/router' |       - '@angular/router' | ||||||
|   | |||||||
| @@ -17,6 +17,8 @@ from guardian.shortcuts import get_users_with_perms | |||||||
| from whoosh import classify | from whoosh import classify | ||||||
| from whoosh import highlight | from whoosh import highlight | ||||||
| from whoosh import query | from whoosh import query | ||||||
|  | from whoosh.analysis import CharsetFilter | ||||||
|  | from whoosh.analysis import StemmingAnalyzer | ||||||
| from whoosh.fields import BOOLEAN | from whoosh.fields import BOOLEAN | ||||||
| from whoosh.fields import DATETIME | from whoosh.fields import DATETIME | ||||||
| from whoosh.fields import KEYWORD | from whoosh.fields import KEYWORD | ||||||
| @@ -36,6 +38,7 @@ from whoosh.qparser.dateparse import DateParserPlugin | |||||||
| from whoosh.qparser.dateparse import English | from whoosh.qparser.dateparse import English | ||||||
| from whoosh.qparser.plugins import FieldsPlugin | from whoosh.qparser.plugins import FieldsPlugin | ||||||
| from whoosh.scoring import TF_IDF | from whoosh.scoring import TF_IDF | ||||||
|  | from whoosh.support.charset import accent_map | ||||||
| from whoosh.util.times import timespan | from whoosh.util.times import timespan | ||||||
| from whoosh.writing import AsyncWriter | from whoosh.writing import AsyncWriter | ||||||
|  |  | ||||||
| @@ -54,10 +57,13 @@ logger = logging.getLogger("paperless.index") | |||||||
|  |  | ||||||
|  |  | ||||||
| def get_schema() -> Schema: | def get_schema() -> Schema: | ||||||
|  |     # add accent-folding filter to a stemming analyzer: | ||||||
|  |     af_analyzer = StemmingAnalyzer() | CharsetFilter(accent_map) | ||||||
|  |  | ||||||
|     return Schema( |     return Schema( | ||||||
|         id=NUMERIC(stored=True, unique=True), |         id=NUMERIC(stored=True, unique=True), | ||||||
|         title=TEXT(sortable=True), |         title=TEXT(sortable=True, analyzer=af_analyzer), | ||||||
|         content=TEXT(), |         content=TEXT(analyzer=af_analyzer), | ||||||
|         asn=NUMERIC(sortable=True, signed=False), |         asn=NUMERIC(sortable=True, signed=False), | ||||||
|         correspondent=TEXT(sortable=True), |         correspondent=TEXT(sortable=True), | ||||||
|         correspondent_id=NUMERIC(), |         correspondent_id=NUMERIC(), | ||||||
|   | |||||||
| @@ -1,24 +0,0 @@ | |||||||
| # Generated by Django 5.1.8 on 2025-06-19 09:33 |  | ||||||
|  |  | ||||||
| from django.db import migrations |  | ||||||
| from django.db import models |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class Migration(migrations.Migration): |  | ||||||
|     dependencies = [ |  | ||||||
|         ("documents", "1068_alter_document_created"), |  | ||||||
|     ] |  | ||||||
|  |  | ||||||
|     operations = [ |  | ||||||
|         migrations.AlterField( |  | ||||||
|             model_name="paperlesstask", |  | ||||||
|             name="task_id", |  | ||||||
|             field=models.CharField( |  | ||||||
|                 db_index=True, |  | ||||||
|                 help_text="Celery ID for the Task that was run", |  | ||||||
|                 max_length=255, |  | ||||||
|                 unique=True, |  | ||||||
|                 verbose_name="Task ID", |  | ||||||
|             ), |  | ||||||
|         ), |  | ||||||
|     ] |  | ||||||
| @@ -545,7 +545,6 @@ class PaperlessTask(ModelWithOwner): | |||||||
|         INDEX_OPTIMIZE = ("index_optimize", _("Index Optimize")) |         INDEX_OPTIMIZE = ("index_optimize", _("Index Optimize")) | ||||||
|  |  | ||||||
|     task_id = models.CharField( |     task_id = models.CharField( | ||||||
|         db_index=True, |  | ||||||
|         max_length=255, |         max_length=255, | ||||||
|         unique=True, |         unique=True, | ||||||
|         verbose_name=_("Task ID"), |         verbose_name=_("Task ID"), | ||||||
|   | |||||||
| @@ -1189,6 +1189,7 @@ class SavedViewSerializer(OwnedObjectSerializer): | |||||||
|             "owner", |             "owner", | ||||||
|             "permissions", |             "permissions", | ||||||
|             "user_can_change", |             "user_can_change", | ||||||
|  |             "set_permissions", | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
|     def validate(self, attrs): |     def validate(self, attrs): | ||||||
| @@ -1753,8 +1754,6 @@ class StoragePathSerializer(MatchingModelSerializer, OwnedObjectSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| class UiSettingsViewSerializer(serializers.ModelSerializer): | class UiSettingsViewSerializer(serializers.ModelSerializer): | ||||||
|     settings = serializers.DictField(required=False, allow_null=True) |  | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = UiSettings |         model = UiSettings | ||||||
|         depth = 1 |         depth = 1 | ||||||
| @@ -2021,9 +2020,8 @@ class WorkflowTriggerSerializer(serializers.ModelSerializer): | |||||||
|         ): |         ): | ||||||
|             attrs["filter_path"] = None |             attrs["filter_path"] = None | ||||||
|  |  | ||||||
|         trigger_type = attrs.get("type", getattr(self.instance, "type", None)) |  | ||||||
|         if ( |         if ( | ||||||
|             trigger_type == WorkflowTrigger.WorkflowTriggerType.CONSUMPTION |             attrs["type"] == WorkflowTrigger.WorkflowTriggerType.CONSUMPTION | ||||||
|             and "filter_mailrule" not in attrs |             and "filter_mailrule" not in attrs | ||||||
|             and ("filter_filename" not in attrs or attrs["filter_filename"] is None) |             and ("filter_filename" not in attrs or attrs["filter_filename"] is None) | ||||||
|             and ("filter_path" not in attrs or attrs["filter_path"] is None) |             and ("filter_path" not in attrs or attrs["filter_path"] is None) | ||||||
|   | |||||||
| @@ -1021,7 +1021,7 @@ def run_workflows( | |||||||
|  |  | ||||||
|         if action.remove_all_custom_fields: |         if action.remove_all_custom_fields: | ||||||
|             if not use_overrides: |             if not use_overrides: | ||||||
|                 CustomFieldInstance.objects.filter(document=document).hard_delete() |                 CustomFieldInstance.objects.filter(document=document).delete() | ||||||
|             else: |             else: | ||||||
|                 overrides.custom_fields = None |                 overrides.custom_fields = None | ||||||
|         elif action.remove_custom_fields.exists(): |         elif action.remove_custom_fields.exists(): | ||||||
| @@ -1029,7 +1029,7 @@ def run_workflows( | |||||||
|                 CustomFieldInstance.objects.filter( |                 CustomFieldInstance.objects.filter( | ||||||
|                     field__in=action.remove_custom_fields.all(), |                     field__in=action.remove_custom_fields.all(), | ||||||
|                     document=document, |                     document=document, | ||||||
|                 ).hard_delete() |                 ).delete() | ||||||
|             elif overrides.custom_fields: |             elif overrides.custom_fields: | ||||||
|                 for field in action.remove_custom_fields.filter( |                 for field in action.remove_custom_fields.filter( | ||||||
|                     pk__in=overrides.custom_fields.keys(), |                     pk__in=overrides.custom_fields.keys(), | ||||||
|   | |||||||
| @@ -167,25 +167,3 @@ class TestApiAppConfig(DirectoriesMixin, APITestCase): | |||||||
|                 }, |                 }, | ||||||
|             ) |             ) | ||||||
|         self.assertFalse(Path(old_logo.path).exists()) |         self.assertFalse(Path(old_logo.path).exists()) | ||||||
|  |  | ||||||
|     def test_create_not_allowed(self): |  | ||||||
|         """ |  | ||||||
|         GIVEN: |  | ||||||
|             - API request to create a new app config |  | ||||||
|         WHEN: |  | ||||||
|             - API is called |  | ||||||
|         THEN: |  | ||||||
|             - Correct HTTP response |  | ||||||
|             - No new config is created |  | ||||||
|         """ |  | ||||||
|         response = self.client.post( |  | ||||||
|             self.ENDPOINT, |  | ||||||
|             json.dumps( |  | ||||||
|                 { |  | ||||||
|                     "output_type": "pdf", |  | ||||||
|                 }, |  | ||||||
|             ), |  | ||||||
|             content_type="application/json", |  | ||||||
|         ) |  | ||||||
|         self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) |  | ||||||
|         self.assertEqual(ApplicationConfiguration.objects.count(), 1) |  | ||||||
|   | |||||||
| @@ -557,7 +557,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase): | |||||||
|  |  | ||||||
|         response = self.client.get("/api/search/autocomplete/?term=app") |         response = self.client.get("/api/search/autocomplete/?term=app") | ||||||
|         self.assertEqual(response.status_code, status.HTTP_200_OK) |         self.assertEqual(response.status_code, status.HTTP_200_OK) | ||||||
|         self.assertEqual(response.data, [b"apples", b"applebaum", b"appletini"]) |         self.assertEqual(response.data, [b"appl", b"applebaum", b"appletini"]) | ||||||
|  |  | ||||||
|         d3.owner = u2 |         d3.owner = u2 | ||||||
|  |  | ||||||
| @@ -566,7 +566,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase): | |||||||
|  |  | ||||||
|         response = self.client.get("/api/search/autocomplete/?term=app") |         response = self.client.get("/api/search/autocomplete/?term=app") | ||||||
|         self.assertEqual(response.status_code, status.HTTP_200_OK) |         self.assertEqual(response.status_code, status.HTTP_200_OK) | ||||||
|         self.assertEqual(response.data, [b"apples", b"applebaum"]) |         self.assertEqual(response.data, [b"appl", b"applebaum"]) | ||||||
|  |  | ||||||
|         assign_perm("view_document", u1, d3) |         assign_perm("view_document", u1, d3) | ||||||
|  |  | ||||||
| @@ -575,7 +575,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase): | |||||||
|  |  | ||||||
|         response = self.client.get("/api/search/autocomplete/?term=app") |         response = self.client.get("/api/search/autocomplete/?term=app") | ||||||
|         self.assertEqual(response.status_code, status.HTTP_200_OK) |         self.assertEqual(response.status_code, status.HTTP_200_OK) | ||||||
|         self.assertEqual(response.data, [b"apples", b"applebaum", b"appletini"]) |         self.assertEqual(response.data, [b"appl", b"applebaum", b"appletini"]) | ||||||
|  |  | ||||||
|     def test_search_autocomplete_field_name_match(self): |     def test_search_autocomplete_field_name_match(self): | ||||||
|         """ |         """ | ||||||
|   | |||||||
| @@ -117,30 +117,6 @@ class TestApiUiSettings(DirectoriesMixin, APITestCase): | |||||||
|  |  | ||||||
|         self.assertEqual(response.status_code, status.HTTP_200_OK) |         self.assertEqual(response.status_code, status.HTTP_200_OK) | ||||||
|  |  | ||||||
|     def test_settings_must_be_dict(self): |  | ||||||
|         """ |  | ||||||
|         GIVEN: |  | ||||||
|             - API request to update ui_settings with settings not being a dict |  | ||||||
|         WHEN: |  | ||||||
|             - API is called |  | ||||||
|         THEN: |  | ||||||
|             - Correct HTTP 400 response |  | ||||||
|         """ |  | ||||||
|         response = self.client.post( |  | ||||||
|             self.ENDPOINT, |  | ||||||
|             json.dumps( |  | ||||||
|                 { |  | ||||||
|                     "settings": "not a dict", |  | ||||||
|                 }, |  | ||||||
|             ), |  | ||||||
|             content_type="application/json", |  | ||||||
|         ) |  | ||||||
|         self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) |  | ||||||
|         self.assertIn( |  | ||||||
|             "Expected a dictionary", |  | ||||||
|             str(response.data["settings"]), |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     @override_settings( |     @override_settings( | ||||||
|         OAUTH_CALLBACK_BASE_URL="http://localhost:8000", |         OAUTH_CALLBACK_BASE_URL="http://localhost:8000", | ||||||
|         GMAIL_OAUTH_CLIENT_ID="abc123", |         GMAIL_OAUTH_CLIENT_ID="abc123", | ||||||
|   | |||||||
| @@ -650,7 +650,7 @@ class DocumentViewSet( | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def get_metadata(self, file, mime_type): |     def get_metadata(self, file, mime_type): | ||||||
|         if not Path(file).is_file(): |         if not os.path.isfile(file): | ||||||
|             return None |             return None | ||||||
|  |  | ||||||
|         parser_class = get_parser_class_for_mime_type(mime_type) |         parser_class = get_parser_class_for_mime_type(mime_type) | ||||||
| @@ -668,8 +668,8 @@ class DocumentViewSet( | |||||||
|             return [] |             return [] | ||||||
|  |  | ||||||
|     def get_filesize(self, filename): |     def get_filesize(self, filename): | ||||||
|         if Path(filename).is_file(): |         if os.path.isfile(filename): | ||||||
|             return Path(filename).stat().st_size |             return os.stat(filename).st_size | ||||||
|         else: |         else: | ||||||
|             return None |             return None | ||||||
|  |  | ||||||
| @@ -1215,37 +1215,31 @@ class UnifiedSearchViewSet(DocumentViewSet): | |||||||
| class LogViewSet(ViewSet): | class LogViewSet(ViewSet): | ||||||
|     permission_classes = (IsAuthenticated, PaperlessAdminPermissions) |     permission_classes = (IsAuthenticated, PaperlessAdminPermissions) | ||||||
|  |  | ||||||
|     ALLOWED_LOG_FILES = { |     log_files = ["paperless", "mail", "celery"] | ||||||
|         "paperless": "paperless.log", |  | ||||||
|         "mail": "mail.log", |  | ||||||
|         "celery": "celery.log", |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     def get_log_file(self, log_key: str) -> Path: |     def get_log_filename(self, log): | ||||||
|         return Path(settings.LOGGING_DIR) / self.ALLOWED_LOG_FILES[log_key] |         return os.path.join(settings.LOGGING_DIR, f"{log}.log") | ||||||
|  |  | ||||||
|     def retrieve(self, request, *args, **kwargs): |     def retrieve(self, request, *args, **kwargs): | ||||||
|         log_key = kwargs.get("pk") |         log_file = kwargs.get("pk") | ||||||
|         if log_key not in self.ALLOWED_LOG_FILES: |         if log_file not in self.log_files: | ||||||
|             raise Http404 |             raise Http404 | ||||||
|  |  | ||||||
|         log_file = self.get_log_file(log_key) |         filename = self.get_log_filename(log_file) | ||||||
|  |  | ||||||
|         if not log_file.is_file(): |         if not os.path.isfile(filename): | ||||||
|             raise Http404 |             raise Http404 | ||||||
|  |  | ||||||
|         with log_file.open() as f: |         with open(filename) as f: | ||||||
|             lines = [line.rstrip() for line in f.readlines()] |             lines = [line.rstrip() for line in f.readlines()] | ||||||
|  |  | ||||||
|         return Response(lines) |         return Response(lines) | ||||||
|  |  | ||||||
|     def list(self, request, *args, **kwargs): |     def list(self, request, *args, **kwargs): | ||||||
|         existing_logs = [ |         exist = [ | ||||||
|             log_key |             log for log in self.log_files if os.path.isfile(self.get_log_filename(log)) | ||||||
|             for log_key in self.ALLOWED_LOG_FILES |  | ||||||
|             if self.get_log_file(log_key).is_file() |  | ||||||
|         ] |         ] | ||||||
|         return Response(existing_logs) |         return Response(exist) | ||||||
|  |  | ||||||
|  |  | ||||||
| class SavedViewViewSet(ModelViewSet, PassUserMixin): | class SavedViewViewSet(ModelViewSet, PassUserMixin): | ||||||
| @@ -2079,7 +2073,7 @@ class BulkDownloadView(GenericAPIView): | |||||||
|                 strategy.add_document(document) |                 strategy.add_document(document) | ||||||
|  |  | ||||||
|         # TODO(stumpylog): Investigate using FileResponse here |         # TODO(stumpylog): Investigate using FileResponse here | ||||||
|         with Path(temp.name).open("rb") as f: |         with open(temp.name, "rb") as f: | ||||||
|             response = HttpResponse(f, content_type="application/zip") |             response = HttpResponse(f, content_type="application/zip") | ||||||
|             response["Content-Disposition"] = '{}; filename="{}"'.format( |             response["Content-Disposition"] = '{}; filename="{}"'.format( | ||||||
|                 "attachment", |                 "attachment", | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: paperless-ngx\n" | "Project-Id-Version: paperless-ngx\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2025-06-17 05:45+0000\n" | "POT-Creation-Date: 2025-06-14 19:08-0700\n" | ||||||
| "PO-Revision-Date: 2022-02-17 04:17\n" | "PO-Revision-Date: 2022-02-17 04:17\n" | ||||||
| "Last-Translator: \n" | "Last-Translator: \n" | ||||||
| "Language-Team: English\n" | "Language-Team: English\n" | ||||||
| @@ -1185,12 +1185,12 @@ msgstr "" | |||||||
| msgid "Invalid color." | msgid "Invalid color." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: documents/serialisers.py:1645 | #: documents/serialisers.py:1646 | ||||||
| #, python-format | #, python-format | ||||||
| msgid "File type %(type)s not supported" | msgid "File type %(type)s not supported" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: documents/serialisers.py:1739 | #: documents/serialisers.py:1740 | ||||||
| msgid "Invalid variable detected." | msgid "Invalid variable detected." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ import os | |||||||
| import pwd | import pwd | ||||||
| import shutil | import shutil | ||||||
| import stat | import stat | ||||||
| from pathlib import Path |  | ||||||
|  |  | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.core.checks import Error | from django.core.checks import Error | ||||||
| @@ -20,23 +19,26 @@ writeable_hint = ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| def path_check(var, directory: Path) -> list[Error]: | def path_check(var, directory): | ||||||
|     messages: list[Error] = [] |     messages = [] | ||||||
|     if directory: |     if directory: | ||||||
|         if not directory.is_dir(): |         if not os.path.isdir(directory): | ||||||
|             messages.append( |             messages.append( | ||||||
|                 Error(exists_message.format(var), exists_hint.format(directory)), |                 Error(exists_message.format(var), exists_hint.format(directory)), | ||||||
|             ) |             ) | ||||||
|         else: |         else: | ||||||
|             test_file: Path = directory / f"__paperless_write_test_{os.getpid()}__" |             test_file = os.path.join( | ||||||
|  |                 directory, | ||||||
|  |                 f"__paperless_write_test_{os.getpid()}__", | ||||||
|  |             ) | ||||||
|             try: |             try: | ||||||
|                 with test_file.open("w"): |                 with open(test_file, "w"): | ||||||
|                     pass |                     pass | ||||||
|             except PermissionError: |             except PermissionError: | ||||||
|                 dir_stat: os.stat_result = Path(directory).stat() |                 dir_stat = os.stat(directory) | ||||||
|                 dir_mode: str = stat.filemode(dir_stat.st_mode) |                 dir_mode = stat.filemode(dir_stat.st_mode) | ||||||
|                 dir_owner: str = pwd.getpwuid(dir_stat.st_uid).pw_name |                 dir_owner = pwd.getpwuid(dir_stat.st_uid).pw_name | ||||||
|                 dir_group: str = grp.getgrgid(dir_stat.st_gid).gr_name |                 dir_group = grp.getgrgid(dir_stat.st_gid).gr_name | ||||||
|                 messages.append( |                 messages.append( | ||||||
|                     Error( |                     Error( | ||||||
|                         writeable_message.format(var), |                         writeable_message.format(var), | ||||||
| @@ -46,18 +48,14 @@ def path_check(var, directory: Path) -> list[Error]: | |||||||
|                     ), |                     ), | ||||||
|                 ) |                 ) | ||||||
|             finally: |             finally: | ||||||
|                 try: |                 if os.path.isfile(test_file): | ||||||
|                     if test_file.is_file(): |                     os.remove(test_file) | ||||||
|                         test_file.unlink() |  | ||||||
|                 except (PermissionError, OSError): |  | ||||||
|                     # Skip cleanup if we can't access the file — expected in permission tests |  | ||||||
|                     pass |  | ||||||
|  |  | ||||||
|     return messages |     return messages | ||||||
|  |  | ||||||
|  |  | ||||||
| @register() | @register() | ||||||
| def paths_check(app_configs, **kwargs) -> list[Error]: | def paths_check(app_configs, **kwargs): | ||||||
|     """ |     """ | ||||||
|     Check the various paths for existence, readability and writeability |     Check the various paths for existence, readability and writeability | ||||||
|     """ |     """ | ||||||
|   | |||||||
| @@ -27,9 +27,9 @@ class TestChecks(DirectoriesMixin, TestCase): | |||||||
|         self.assertEqual(paths_check(None), []) |         self.assertEqual(paths_check(None), []) | ||||||
|  |  | ||||||
|     @override_settings( |     @override_settings( | ||||||
|         MEDIA_ROOT=Path("uuh"), |         MEDIA_ROOT="uuh", | ||||||
|         DATA_DIR=Path("whatever"), |         DATA_DIR="whatever", | ||||||
|         CONSUMPTION_DIR=Path("idontcare"), |         CONSUMPTION_DIR="idontcare", | ||||||
|     ) |     ) | ||||||
|     def test_paths_check_dont_exist(self): |     def test_paths_check_dont_exist(self): | ||||||
|         msgs = paths_check(None) |         msgs = paths_check(None) | ||||||
|   | |||||||
| @@ -363,7 +363,7 @@ urlpatterns = [ | |||||||
|  |  | ||||||
|  |  | ||||||
| websocket_urlpatterns = [ | websocket_urlpatterns = [ | ||||||
|     path("ws/status/", StatusConsumer.as_asgi()), |     path(settings.BASE_URL.lstrip("/") + "ws/status/", StatusConsumer.as_asgi()), | ||||||
| ] | ] | ||||||
|  |  | ||||||
| # Text in each page's <h1> (and above login form). | # Text in each page's <h1> (and above login form). | ||||||
|   | |||||||
| @@ -342,10 +342,6 @@ class ApplicationConfigurationViewSet(ModelViewSet): | |||||||
|     serializer_class = ApplicationConfigurationSerializer |     serializer_class = ApplicationConfigurationSerializer | ||||||
|     permission_classes = (IsAuthenticated, DjangoModelPermissions) |     permission_classes = (IsAuthenticated, DjangoModelPermissions) | ||||||
|  |  | ||||||
|     @extend_schema(exclude=True) |  | ||||||
|     def create(self, request, *args, **kwargs): |  | ||||||
|         return Response(status=405)  # Not Allowed |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @extend_schema_view( | @extend_schema_view( | ||||||
|     post=extend_schema( |     post=extend_schema( | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| import datetime | import datetime | ||||||
| import itertools | import itertools | ||||||
| import logging | import logging | ||||||
|  | import os | ||||||
| import ssl | import ssl | ||||||
| import tempfile | import tempfile | ||||||
| import traceback | import traceback | ||||||
| @@ -483,7 +484,7 @@ class MailAccountHandler(LoggingMixin): | |||||||
|             return message.subject |             return message.subject | ||||||
|  |  | ||||||
|         elif rule.assign_title_from == MailRule.TitleSource.FROM_FILENAME: |         elif rule.assign_title_from == MailRule.TitleSource.FROM_FILENAME: | ||||||
|             return Path(att.filename).stem |             return os.path.splitext(os.path.basename(att.filename))[0] | ||||||
|  |  | ||||||
|         elif rule.assign_title_from == MailRule.TitleSource.NONE: |         elif rule.assign_title_from == MailRule.TitleSource.NONE: | ||||||
|             return None |             return None | ||||||
| @@ -907,7 +908,7 @@ class MailAccountHandler(LoggingMixin): | |||||||
|             dir=settings.SCRATCH_DIR, |             dir=settings.SCRATCH_DIR, | ||||||
|             suffix=".eml", |             suffix=".eml", | ||||||
|         ) |         ) | ||||||
|         with Path(temp_filename).open("wb") as f: |         with open(temp_filename, "wb") as f: | ||||||
|             # Move "From"-header to beginning of file |             # Move "From"-header to beginning of file | ||||||
|             # TODO: This ugly workaround is needed because the parser is |             # TODO: This ugly workaround is needed because the parser is | ||||||
|             #   chosen only by the mime_type detected via magic |             #   chosen only by the mime_type detected via magic | ||||||
|   | |||||||
| @@ -108,20 +108,18 @@ class MailRuleSerializer(OwnedObjectSerializer): | |||||||
|         return instance |         return instance | ||||||
|  |  | ||||||
|     def create(self, validated_data): |     def create(self, validated_data): | ||||||
|         assign_tags = validated_data.pop("assign_tags", []) |         if "assign_tags" in validated_data: | ||||||
|  |             assign_tags = validated_data.pop("assign_tags") | ||||||
|         mail_rule = super().create(validated_data) |         mail_rule = super().create(validated_data) | ||||||
|         if assign_tags: |         if assign_tags: | ||||||
|             mail_rule.assign_tags.set(assign_tags) |             mail_rule.assign_tags.set(assign_tags) | ||||||
|         return mail_rule |         return mail_rule | ||||||
|  |  | ||||||
|     def validate(self, attrs): |     def validate(self, attrs): | ||||||
|         action = attrs.get("action") |  | ||||||
|         action_parameter = attrs.get("action_parameter") |  | ||||||
|  |  | ||||||
|         if ( |         if ( | ||||||
|             action in [MailRule.MailAction.TAG, MailRule.MailAction.MOVE] |             attrs["action"] == MailRule.MailAction.TAG | ||||||
|             and not action_parameter |             or attrs["action"] == MailRule.MailAction.MOVE | ||||||
|         ): |         ) and attrs["action_parameter"] is None: | ||||||
|             raise serializers.ValidationError("An action parameter is required.") |             raise serializers.ValidationError("An action parameter is required.") | ||||||
|  |  | ||||||
|         return attrs |         return attrs | ||||||
|   | |||||||
| @@ -1822,66 +1822,3 @@ class TestMailAccountProcess(APITestCase): | |||||||
|         response = self.client.post(self.url) |         response = self.client.post(self.url) | ||||||
|         self.assertEqual(response.status_code, status.HTTP_200_OK) |         self.assertEqual(response.status_code, status.HTTP_200_OK) | ||||||
|         m.assert_called_once() |         m.assert_called_once() | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestMailRuleAPI(APITestCase): |  | ||||||
|     def setUp(self): |  | ||||||
|         self.user = User.objects.create_superuser( |  | ||||||
|             username="testuser", |  | ||||||
|             password="testpassword", |  | ||||||
|         ) |  | ||||||
|         self.client.force_authenticate(user=self.user) |  | ||||||
|         self.account = MailAccount.objects.create( |  | ||||||
|             imap_server="imap.example.com", |  | ||||||
|             imap_port=993, |  | ||||||
|             imap_security=MailAccount.ImapSecurity.SSL, |  | ||||||
|             username="admin", |  | ||||||
|             password="secret", |  | ||||||
|             account_type=MailAccount.MailAccountType.IMAP, |  | ||||||
|             owner=self.user, |  | ||||||
|         ) |  | ||||||
|         self.url = "/api/mail_rules/" |  | ||||||
|  |  | ||||||
|     def test_create_mail_rule(self): |  | ||||||
|         """ |  | ||||||
|         GIVEN: |  | ||||||
|             - Valid data for creating a mail rule |  | ||||||
|         WHEN: |  | ||||||
|             - A POST request is made to the mail rules endpoint |  | ||||||
|         THEN: |  | ||||||
|             - The rule should be created successfully |  | ||||||
|             - The response should contain the created rule's details |  | ||||||
|         """ |  | ||||||
|         data = { |  | ||||||
|             "name": "Test Rule", |  | ||||||
|             "account": self.account.pk, |  | ||||||
|             "action": MailRule.MailAction.MOVE, |  | ||||||
|             "action_parameter": "inbox", |  | ||||||
|         } |  | ||||||
|         response = self.client.post(self.url, data, format="json") |  | ||||||
|         self.assertEqual(response.status_code, status.HTTP_201_CREATED) |  | ||||||
|         self.assertEqual(MailRule.objects.count(), 1) |  | ||||||
|         rule = MailRule.objects.first() |  | ||||||
|         self.assertEqual(rule.name, "Test Rule") |  | ||||||
|  |  | ||||||
|     def test_mail_rule_action_parameter_required_for_tag_or_move(self): |  | ||||||
|         """ |  | ||||||
|         GIVEN: |  | ||||||
|             - Valid data for creating a mail rule without action_parameter |  | ||||||
|         WHEN: |  | ||||||
|             - A POST request is made to the mail rules endpoint |  | ||||||
|         THEN: |  | ||||||
|             - The request should fail with a 400 Bad Request status |  | ||||||
|             - The response should indicate that action_parameter is required |  | ||||||
|         """ |  | ||||||
|         data = { |  | ||||||
|             "name": "Test Rule", |  | ||||||
|             "account": self.account.pk, |  | ||||||
|             "action": MailRule.MailAction.MOVE, |  | ||||||
|         } |  | ||||||
|         response = self.client.post(self.url, data, format="json") |  | ||||||
|         self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) |  | ||||||
|         self.assertIn( |  | ||||||
|             "action parameter is required", |  | ||||||
|             str(response.data["non_field_errors"]), |  | ||||||
|         ) |  | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import os | ||||||
| import shutil | import shutil | ||||||
| import tempfile | import tempfile | ||||||
| import uuid | import uuid | ||||||
| @@ -69,13 +70,13 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(uuid.uuid4()) |         parser = RasterisedDocumentParser(uuid.uuid4()) | ||||||
|         page_count = parser.get_page_count( |         page_count = parser.get_page_count( | ||||||
|             (self.SAMPLE_FILES / "simple-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "simple-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(page_count, 1) |         self.assertEqual(page_count, 1) | ||||||
|  |  | ||||||
|         page_count = parser.get_page_count( |         page_count = parser.get_page_count( | ||||||
|             (self.SAMPLE_FILES / "multi-page-mixed.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-mixed.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(page_count, 6) |         self.assertEqual(page_count, 6) | ||||||
| @@ -92,7 +93,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         parser = RasterisedDocumentParser(uuid.uuid4()) |         parser = RasterisedDocumentParser(uuid.uuid4()) | ||||||
|         with self.assertLogs("paperless.parsing.tesseract", level="WARNING") as cm: |         with self.assertLogs("paperless.parsing.tesseract", level="WARNING") as cm: | ||||||
|             page_count = parser.get_page_count( |             page_count = parser.get_page_count( | ||||||
|                 (self.SAMPLE_FILES / "password-protected.pdf").as_posix(), |                 os.path.join(self.SAMPLE_FILES, "password-protected.pdf"), | ||||||
|                 "application/pdf", |                 "application/pdf", | ||||||
|             ) |             ) | ||||||
|             self.assertEqual(page_count, None) |             self.assertEqual(page_count, None) | ||||||
| @@ -101,7 +102,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_thumbnail(self): |     def test_thumbnail(self): | ||||||
|         parser = RasterisedDocumentParser(uuid.uuid4()) |         parser = RasterisedDocumentParser(uuid.uuid4()) | ||||||
|         thumb = parser.get_thumbnail( |         thumb = parser.get_thumbnail( | ||||||
|             (self.SAMPLE_FILES / "simple-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "simple-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(thumb) |         self.assertIsFile(thumb) | ||||||
| @@ -118,7 +119,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|  |  | ||||||
|         parser = RasterisedDocumentParser(uuid.uuid4()) |         parser = RasterisedDocumentParser(uuid.uuid4()) | ||||||
|         thumb = parser.get_thumbnail( |         thumb = parser.get_thumbnail( | ||||||
|             (self.SAMPLE_FILES / "simple-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "simple-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(thumb) |         self.assertIsFile(thumb) | ||||||
| @@ -126,7 +127,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_thumbnail_encrypted(self): |     def test_thumbnail_encrypted(self): | ||||||
|         parser = RasterisedDocumentParser(uuid.uuid4()) |         parser = RasterisedDocumentParser(uuid.uuid4()) | ||||||
|         thumb = parser.get_thumbnail( |         thumb = parser.get_thumbnail( | ||||||
|             (self.SAMPLE_FILES / "encrypted.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "encrypted.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(thumb) |         self.assertIsFile(thumb) | ||||||
| @@ -134,17 +135,17 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_get_dpi(self): |     def test_get_dpi(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         dpi = parser.get_dpi((self.SAMPLE_FILES / "simple-no-dpi.png").as_posix()) |         dpi = parser.get_dpi(os.path.join(self.SAMPLE_FILES, "simple-no-dpi.png")) | ||||||
|         self.assertEqual(dpi, None) |         self.assertEqual(dpi, None) | ||||||
|  |  | ||||||
|         dpi = parser.get_dpi((self.SAMPLE_FILES / "simple.png").as_posix()) |         dpi = parser.get_dpi(os.path.join(self.SAMPLE_FILES, "simple.png")) | ||||||
|         self.assertEqual(dpi, 72) |         self.assertEqual(dpi, 72) | ||||||
|  |  | ||||||
|     def test_simple_digital(self): |     def test_simple_digital(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "simple-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "simple-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -156,7 +157,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "with-form.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "with-form.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -172,7 +173,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "with-form.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "with-form.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -186,7 +187,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_signed(self): |     def test_signed(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         parser.parse((self.SAMPLE_FILES / "signed.pdf").as_posix(), "application/pdf") |         parser.parse(os.path.join(self.SAMPLE_FILES, "signed.pdf"), "application/pdf") | ||||||
|  |  | ||||||
|         self.assertIsNone(parser.archive_path) |         self.assertIsNone(parser.archive_path) | ||||||
|         self.assertContainsStrings( |         self.assertContainsStrings( | ||||||
| @@ -202,7 +203,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "encrypted.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "encrypted.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -213,7 +214,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_with_form_error_notext(self): |     def test_with_form_error_notext(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "with-form.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "with-form.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -227,7 +228,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "with-form.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "with-form.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -239,7 +240,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_image_simple(self): |     def test_image_simple(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         parser.parse((self.SAMPLE_FILES / "simple.png").as_posix(), "image/png") |         parser.parse(os.path.join(self.SAMPLE_FILES, "simple.png"), "image/png") | ||||||
|  |  | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
|  |  | ||||||
| @@ -251,11 +252,11 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         with tempfile.TemporaryDirectory() as tempdir: |         with tempfile.TemporaryDirectory() as tempdir: | ||||||
|             # Copy sample file to temp directory, as the parsing changes the file |             # Copy sample file to temp directory, as the parsing changes the file | ||||||
|             # and this makes it modified to Git |             # and this makes it modified to Git | ||||||
|             sample_file = self.SAMPLE_FILES / "simple-alpha.png" |             sample_file = os.path.join(self.SAMPLE_FILES, "simple-alpha.png") | ||||||
|             dest_file = Path(tempdir) / "simple-alpha.png" |             dest_file = os.path.join(tempdir, "simple-alpha.png") | ||||||
|             shutil.copy(sample_file, dest_file) |             shutil.copy(sample_file, dest_file) | ||||||
|  |  | ||||||
|             parser.parse(dest_file.as_posix(), "image/png") |             parser.parse(dest_file, "image/png") | ||||||
|  |  | ||||||
|             self.assertIsFile(parser.archive_path) |             self.assertIsFile(parser.archive_path) | ||||||
|  |  | ||||||
| @@ -265,7 +266,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         dpi = parser.calculate_a4_dpi( |         dpi = parser.calculate_a4_dpi( | ||||||
|             (self.SAMPLE_FILES / "simple-no-dpi.png").as_posix(), |             os.path.join(self.SAMPLE_FILES, "simple-no-dpi.png"), | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.assertEqual(dpi, 62) |         self.assertEqual(dpi, 62) | ||||||
| @@ -277,7 +278,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|  |  | ||||||
|         def f(): |         def f(): | ||||||
|             parser.parse( |             parser.parse( | ||||||
|                 (self.SAMPLE_FILES / "simple-no-dpi.png").as_posix(), |                 os.path.join(self.SAMPLE_FILES, "simple-no-dpi.png"), | ||||||
|                 "image/png", |                 "image/png", | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
| @@ -287,7 +288,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_image_no_dpi_default(self): |     def test_image_no_dpi_default(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         parser.parse((self.SAMPLE_FILES / "simple-no-dpi.png").as_posix(), "image/png") |         parser.parse(os.path.join(self.SAMPLE_FILES, "simple-no-dpi.png"), "image/png") | ||||||
|  |  | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
|  |  | ||||||
| @@ -299,7 +300,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_multi_page(self): |     def test_multi_page(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
| @@ -312,7 +313,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_multi_page_pages_skip(self): |     def test_multi_page_pages_skip(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
| @@ -325,7 +326,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_multi_page_pages_redo(self): |     def test_multi_page_pages_redo(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
| @@ -338,7 +339,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_multi_page_pages_force(self): |     def test_multi_page_pages_force(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
| @@ -351,7 +352,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     def test_multi_page_analog_pages_skip(self): |     def test_multi_page_analog_pages_skip(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-images.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-images.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
| @@ -375,7 +376,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-images.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-images.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
| @@ -397,7 +398,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-images.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-images.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
| @@ -419,7 +420,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNone(parser.archive_path) |         self.assertIsNone(parser.archive_path) | ||||||
| @@ -442,7 +443,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-images.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-images.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -467,7 +468,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNotNone(parser.archive_path) |         self.assertIsNotNone(parser.archive_path) | ||||||
| @@ -490,7 +491,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-images.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-images.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNotNone(parser.archive_path) |         self.assertIsNotNone(parser.archive_path) | ||||||
| @@ -513,7 +514,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNone(parser.archive_path) |         self.assertIsNone(parser.archive_path) | ||||||
| @@ -536,7 +537,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-images.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-images.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNotNone(parser.archive_path) |         self.assertIsNotNone(parser.archive_path) | ||||||
| @@ -559,7 +560,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNone(parser.archive_path) |         self.assertIsNone(parser.archive_path) | ||||||
| @@ -582,7 +583,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-images.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-images.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNone(parser.archive_path) |         self.assertIsNone(parser.archive_path) | ||||||
| @@ -605,7 +606,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-mixed.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-mixed.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNotNone(parser.archive_path) |         self.assertIsNotNone(parser.archive_path) | ||||||
| @@ -615,7 +616,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|             ["page 1", "page 2", "page 3", "page 4", "page 5", "page 6"], |             ["page 1", "page 2", "page 3", "page 4", "page 5", "page 6"], | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         with (parser.tempdir / "sidecar.txt").open() as f: |         with open(os.path.join(parser.tempdir, "sidecar.txt")) as f: | ||||||
|             sidecar = f.read() |             sidecar = f.read() | ||||||
|  |  | ||||||
|         self.assertIn("[OCR skipped on page(s) 4-6]", sidecar) |         self.assertIn("[OCR skipped on page(s) 4-6]", sidecar) | ||||||
| @@ -636,7 +637,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "single-page-mixed.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "single-page-mixed.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNotNone(parser.archive_path) |         self.assertIsNotNone(parser.archive_path) | ||||||
| @@ -650,7 +651,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|             ], |             ], | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         with (parser.tempdir / "sidecar.txt").open() as f: |         with open(os.path.join(parser.tempdir, "sidecar.txt")) as f: | ||||||
|             sidecar = f.read().lower() |             sidecar = f.read().lower() | ||||||
|  |  | ||||||
|         self.assertIn("this is some text, but in an image, also on page 1.", sidecar) |         self.assertIn("this is some text, but in an image, also on page 1.", sidecar) | ||||||
| @@ -673,7 +674,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-mixed.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-mixed.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|         self.assertIsNone(parser.archive_path) |         self.assertIsNone(parser.archive_path) | ||||||
| @@ -685,7 +686,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|     @override_settings(OCR_MODE="skip", OCR_ROTATE_PAGES=True) |     @override_settings(OCR_MODE="skip", OCR_ROTATE_PAGES=True) | ||||||
|     def test_rotate(self): |     def test_rotate(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse((self.SAMPLE_FILES / "rotated.pdf").as_posix(), "application/pdf") |         parser.parse(os.path.join(self.SAMPLE_FILES, "rotated.pdf"), "application/pdf") | ||||||
|         self.assertContainsStrings( |         self.assertContainsStrings( | ||||||
|             parser.get_text(), |             parser.get_text(), | ||||||
|             [ |             [ | ||||||
| @@ -707,7 +708,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "multi-page-images.tiff").as_posix(), |             os.path.join(self.SAMPLE_FILES, "multi-page-images.tiff"), | ||||||
|             "image/tiff", |             "image/tiff", | ||||||
|         ) |         ) | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
| @@ -727,7 +728,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|             - Text from all pages extracted |             - Text from all pages extracted | ||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         sample_file = self.SAMPLE_FILES / "multi-page-images-alpha.tiff" |         sample_file = os.path.join(self.SAMPLE_FILES, "multi-page-images-alpha.tiff") | ||||||
|         with tempfile.NamedTemporaryFile() as tmp_file: |         with tempfile.NamedTemporaryFile() as tmp_file: | ||||||
|             shutil.copy(sample_file, tmp_file.name) |             shutil.copy(sample_file, tmp_file.name) | ||||||
|             parser.parse( |             parser.parse( | ||||||
| @@ -752,9 +753,10 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|             - Text from all pages extracted |             - Text from all pages extracted | ||||||
|         """ |         """ | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         sample_file = ( |         sample_file = os.path.join( | ||||||
|             self.SAMPLE_FILES / "multi-page-images-alpha-rgb.tiff" |             self.SAMPLE_FILES, | ||||||
|         ).as_posix() |             "multi-page-images-alpha-rgb.tiff", | ||||||
|  |         ) | ||||||
|         with tempfile.NamedTemporaryFile() as tmp_file: |         with tempfile.NamedTemporaryFile() as tmp_file: | ||||||
|             shutil.copy(sample_file, tmp_file.name) |             shutil.copy(sample_file, tmp_file.name) | ||||||
|             parser.parse( |             parser.parse( | ||||||
| @@ -843,7 +845,7 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|  |  | ||||||
|         parser.parse( |         parser.parse( | ||||||
|             (self.SAMPLE_FILES / "rtl-test.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "rtl-test.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -858,52 +860,49 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | |||||||
|         self.assertRaises( |         self.assertRaises( | ||||||
|             ParseError, |             ParseError, | ||||||
|             parser.parse, |             parser.parse, | ||||||
|             (self.SAMPLE_FILES / "simple-digital.pdf").as_posix(), |             os.path.join(self.SAMPLE_FILES, "simple-digital.pdf"), | ||||||
|             "application/pdf", |             "application/pdf", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestParserFileTypes(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | class TestParserFileTypes(DirectoriesMixin, FileSystemAssertsMixin, TestCase): | ||||||
|     SAMPLE_FILES = Path(__file__).parent / "samples" |     SAMPLE_FILES = os.path.join(os.path.dirname(__file__), "samples") | ||||||
|  |  | ||||||
|     def test_bmp(self): |     def test_bmp(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse((self.SAMPLE_FILES / "simple.bmp").as_posix(), "image/bmp") |         parser.parse(os.path.join(self.SAMPLE_FILES, "simple.bmp"), "image/bmp") | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
|         self.assertIn("this is a test document", parser.get_text().lower()) |         self.assertIn("this is a test document", parser.get_text().lower()) | ||||||
|  |  | ||||||
|     def test_jpg(self): |     def test_jpg(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse((self.SAMPLE_FILES / "simple.jpg").as_posix(), "image/jpeg") |         parser.parse(os.path.join(self.SAMPLE_FILES, "simple.jpg"), "image/jpeg") | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
|         self.assertIn("this is a test document", parser.get_text().lower()) |         self.assertIn("this is a test document", parser.get_text().lower()) | ||||||
|  |  | ||||||
|     def test_heic(self): |     def test_heic(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse((self.SAMPLE_FILES / "simple.heic").as_posix(), "image/heic") |         parser.parse(os.path.join(self.SAMPLE_FILES, "simple.heic"), "image/heic") | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
|         self.assertIn("pizza", parser.get_text().lower()) |         self.assertIn("pizza", parser.get_text().lower()) | ||||||
|  |  | ||||||
|     @override_settings(OCR_IMAGE_DPI=200) |     @override_settings(OCR_IMAGE_DPI=200) | ||||||
|     def test_gif(self): |     def test_gif(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse((self.SAMPLE_FILES / "simple.gif").as_posix(), "image/gif") |         parser.parse(os.path.join(self.SAMPLE_FILES, "simple.gif"), "image/gif") | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
|         self.assertIn("this is a test document", parser.get_text().lower()) |         self.assertIn("this is a test document", parser.get_text().lower()) | ||||||
|  |  | ||||||
|     def test_tiff(self): |     def test_tiff(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse((self.SAMPLE_FILES / "simple.tif").as_posix(), "image/tiff") |         parser.parse(os.path.join(self.SAMPLE_FILES, "simple.tif"), "image/tiff") | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
|         self.assertIn("this is a test document", parser.get_text().lower()) |         self.assertIn("this is a test document", parser.get_text().lower()) | ||||||
|  |  | ||||||
|     @override_settings(OCR_IMAGE_DPI=72) |     @override_settings(OCR_IMAGE_DPI=72) | ||||||
|     def test_webp(self): |     def test_webp(self): | ||||||
|         parser = RasterisedDocumentParser(None) |         parser = RasterisedDocumentParser(None) | ||||||
|         parser.parse( |         parser.parse(os.path.join(self.SAMPLE_FILES, "document.webp"), "image/webp") | ||||||
|             (self.SAMPLE_FILES / "document.webp").as_posix(), |  | ||||||
|             "image/webp", |  | ||||||
|         ) |  | ||||||
|         self.assertIsFile(parser.archive_path) |         self.assertIsFile(parser.archive_path) | ||||||
|         # Older tesseracts consistently mangle the space between "a webp", |         # Older tesseracts consistently mangle the space between "a webp", | ||||||
|         # tesseract 5.3.0 seems to do a better job, so we're accepting both |         # tesseract 5.3.0 seems to do a better job, so we're accepting both | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user