@arsedizioni/ars-utils 21.2.208 → 21.2.220
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs +179 -159
- package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-clipper.ui.mjs +48 -48
- package/fesm2022/arsedizioni-ars-utils-clipper.ui.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-core.mjs +104 -104
- package/fesm2022/arsedizioni-ars-utils-core.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs +280 -252
- package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-help.mjs +115 -102
- package/fesm2022/arsedizioni-ars-utils-help.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-support.common.mjs +43 -36
- package/fesm2022/arsedizioni-ars-utils-support.common.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-support.ui.mjs +68 -77
- package/fesm2022/arsedizioni-ars-utils-support.ui.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-tinymce.mjs +41 -26
- package/fesm2022/arsedizioni-ars-utils-tinymce.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-ui.application.mjs +803 -732
- package/fesm2022/arsedizioni-ars-utils-ui.application.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-ui.mjs +475 -330
- package/fesm2022/arsedizioni-ars-utils-ui.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-ui.oauth.mjs +29 -25
- package/fesm2022/arsedizioni-ars-utils-ui.oauth.mjs.map +1 -1
- package/package.json +1 -1
- package/types/arsedizioni-ars-utils-clipper.common.d.ts +88 -62
- package/types/arsedizioni-ars-utils-clipper.ui.d.ts +1 -1
- package/types/arsedizioni-ars-utils-core.d.ts +1 -1
- package/types/arsedizioni-ars-utils-evolution.common.d.ts +131 -70
- package/types/arsedizioni-ars-utils-help.d.ts +76 -66
- package/types/arsedizioni-ars-utils-support.common.d.ts +29 -19
- package/types/arsedizioni-ars-utils-support.ui.d.ts +29 -25
- package/types/arsedizioni-ars-utils-tinymce.d.ts +25 -10
- package/types/arsedizioni-ars-utils-ui.application.d.ts +458 -328
- package/types/arsedizioni-ars-utils-ui.d.ts +282 -145
- package/types/arsedizioni-ars-utils-ui.oauth.d.ts +25 -18
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { signal, computed, inject, DestroyRef, Injectable, NgModule } from '@angular/core';
|
|
3
|
+
import { HttpClient, HttpHeaders, HttpRequest, HttpErrorResponse } from '@angular/common/http';
|
|
3
4
|
import { BroadcastService, SystemUtils } from '@arsedizioni/ars-utils/core';
|
|
4
5
|
import { EMPTY, throwError, of, catchError as catchError$1 } from 'rxjs';
|
|
5
|
-
import { HttpClient, HttpHeaders, HttpRequest } from '@angular/common/http';
|
|
6
6
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
7
7
|
import { DialogService } from '@arsedizioni/ars-utils/ui';
|
|
8
8
|
import { catchError, finalize, map } from 'rxjs/operators';
|
|
@@ -1586,34 +1586,24 @@ class ClipperChannelSettings {
|
|
|
1586
1586
|
this.regions = [];
|
|
1587
1587
|
}
|
|
1588
1588
|
/**
|
|
1589
|
-
*
|
|
1590
|
-
*
|
|
1591
|
-
* @
|
|
1589
|
+
* Returns `true` when the channel is active and at least one of the given sector codes
|
|
1590
|
+
* matches a sector assigned to this channel.
|
|
1591
|
+
* @param values - Array of sector code strings to test against.
|
|
1592
1592
|
*/
|
|
1593
1593
|
hasAnyOfSectors(values) {
|
|
1594
|
-
if (this.isEnabled
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
return true;
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
return false;
|
|
1594
|
+
if (this.isEnabled !== true || this.isActive !== true)
|
|
1595
|
+
return false;
|
|
1596
|
+
return values.some(v => this.sectors.some(s => s.value === v));
|
|
1602
1597
|
}
|
|
1603
1598
|
/**
|
|
1604
|
-
*
|
|
1605
|
-
*
|
|
1606
|
-
* @
|
|
1599
|
+
* Returns `true` when the channel is active and at least one of the given region codes
|
|
1600
|
+
* matches a region assigned to this channel.
|
|
1601
|
+
* @param values - Array of region code strings to test against.
|
|
1607
1602
|
*/
|
|
1608
1603
|
hasAnyOfRegions(values) {
|
|
1609
|
-
if (this.isEnabled
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
return true;
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
return false;
|
|
1604
|
+
if (this.isEnabled !== true || this.isActive !== true)
|
|
1605
|
+
return false;
|
|
1606
|
+
return values.some(v => this.regions.some(r => r.value === v));
|
|
1617
1607
|
}
|
|
1618
1608
|
}
|
|
1619
1609
|
var ClipperQueryDocumentFlags;
|
|
@@ -1763,49 +1753,46 @@ class ClipperDashboard {
|
|
|
1763
1753
|
}, ...(ngDevMode ? [{ debugName: "unreadItemsByModel" }] : /* istanbul ignore next */ []));
|
|
1764
1754
|
}
|
|
1765
1755
|
/**
|
|
1766
|
-
*
|
|
1767
|
-
*
|
|
1768
|
-
* @param
|
|
1769
|
-
* @param
|
|
1756
|
+
* Increments (or decrements) the unread item counter for the given module or model.
|
|
1757
|
+
* Triggers a signal update so computed values and templates react to the change.
|
|
1758
|
+
* @param module - The `ClipperModule` whose counter should be adjusted.
|
|
1759
|
+
* @param model - Optional `ClipperModel` for sub-module granularity.
|
|
1760
|
+
* @param increment - Amount to add (use a negative value to decrement).
|
|
1770
1761
|
*/
|
|
1771
1762
|
updateUnreadItems(module, model, increment) {
|
|
1772
1763
|
if (model) {
|
|
1773
|
-
this.items()
|
|
1774
|
-
|
|
1764
|
+
for (const item of this.items()) {
|
|
1765
|
+
const itemModel = item.models?.find(x => x.id === model);
|
|
1775
1766
|
if (itemModel) {
|
|
1776
1767
|
itemModel.unreadItems += increment;
|
|
1777
|
-
|
|
1768
|
+
break;
|
|
1778
1769
|
}
|
|
1779
|
-
}
|
|
1770
|
+
}
|
|
1780
1771
|
}
|
|
1781
|
-
|
|
1772
|
+
const item = this.items().find((x) => x.id === module);
|
|
1782
1773
|
if (item) {
|
|
1783
1774
|
item.unreadItems += increment;
|
|
1784
1775
|
}
|
|
1785
1776
|
this.items.update(values => [...values]);
|
|
1786
1777
|
}
|
|
1787
|
-
|
|
1788
|
-
*
|
|
1789
|
-
* @param module
|
|
1790
|
-
* @param model
|
|
1791
|
-
* @returns
|
|
1778
|
+
/**
|
|
1779
|
+
* Returns the unread-item count for the given module, or for a specific model within it.
|
|
1780
|
+
* @param module - The `ClipperModule` to query.
|
|
1781
|
+
* @param model - Optional `ClipperModel` for sub-module granularity.
|
|
1782
|
+
* @returns Number of unread items, or `0` when none are found.
|
|
1792
1783
|
*/
|
|
1793
1784
|
getUnreadItems(module, model) {
|
|
1794
1785
|
if (model) {
|
|
1795
|
-
return this.unreadItemsByModel()
|
|
1786
|
+
return this.unreadItemsByModel().find((x) => x[0] === model)?.[1] ?? 0;
|
|
1796
1787
|
}
|
|
1797
|
-
return this.unreadItems()
|
|
1788
|
+
return this.unreadItems().find((x) => x[0] === module)?.[1] ?? 0;
|
|
1798
1789
|
}
|
|
1799
1790
|
/**
|
|
1800
|
-
*
|
|
1801
|
-
* @returns
|
|
1791
|
+
* Returns the sum of unread items across all tracked modules.
|
|
1792
|
+
* @returns Total unread-item count.
|
|
1802
1793
|
*/
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
this.unreadItems().forEach(item => {
|
|
1806
|
-
totalUnread += item[1];
|
|
1807
|
-
});
|
|
1808
|
-
return totalUnread;
|
|
1794
|
+
getTotalUnreadItems() {
|
|
1795
|
+
return this.unreadItems().reduce((acc, item) => acc + item[1], 0);
|
|
1809
1796
|
}
|
|
1810
1797
|
}
|
|
1811
1798
|
class ClipperTeamMemberInfo {
|
|
@@ -1892,9 +1879,9 @@ var ClipperArchiveCopyMode;
|
|
|
1892
1879
|
})(ClipperArchiveCopyMode || (ClipperArchiveCopyMode = {}));
|
|
1893
1880
|
class ClipperUtils {
|
|
1894
1881
|
/**
|
|
1895
|
-
*
|
|
1896
|
-
*
|
|
1897
|
-
* @
|
|
1882
|
+
* Returns `true` when the given model corresponds to a readable document type
|
|
1883
|
+
* (i.e., can be opened in the document viewer).
|
|
1884
|
+
* @param model - The `ClipperModel` to test.
|
|
1898
1885
|
*/
|
|
1899
1886
|
static isClipperModelReadable(model) {
|
|
1900
1887
|
return model !== ClipperModel.Unknown &&
|
|
@@ -1903,9 +1890,9 @@ class ClipperUtils {
|
|
|
1903
1890
|
model !== ClipperModel.Segnalazioni;
|
|
1904
1891
|
}
|
|
1905
1892
|
/**
|
|
1906
|
-
*
|
|
1907
|
-
* @param item
|
|
1908
|
-
* @returns the module
|
|
1893
|
+
* Returns the `ClipperModule` that owns the given document, derived from its model type.
|
|
1894
|
+
* @param item - The document info object to inspect.
|
|
1895
|
+
* @returns The matching `ClipperModule`, or `undefined` when the model has no direct module mapping.
|
|
1909
1896
|
*/
|
|
1910
1897
|
static getClipperModuleFromModel(item) {
|
|
1911
1898
|
switch (item.model) {
|
|
@@ -1924,63 +1911,66 @@ class ClipperUtils {
|
|
|
1924
1911
|
return undefined;
|
|
1925
1912
|
}
|
|
1926
1913
|
/**
|
|
1927
|
-
*
|
|
1928
|
-
* @param value
|
|
1929
|
-
* @returns
|
|
1914
|
+
* Returns the display name for the given `ClipperModuleGroup`.
|
|
1915
|
+
* @param value - The module group enum value to look up.
|
|
1916
|
+
* @returns The group display name, or an empty string when not found.
|
|
1930
1917
|
*/
|
|
1931
1918
|
static getClipperModuleGroupName(value) {
|
|
1932
|
-
return ClipperModuleGroups.
|
|
1919
|
+
return ClipperModuleGroups.find(n => n.value === value)?.name ?? '';
|
|
1933
1920
|
}
|
|
1934
1921
|
/**
|
|
1935
|
-
*
|
|
1936
|
-
* @param value
|
|
1937
|
-
* @returns
|
|
1922
|
+
* Returns the list of `ClipperModule` items belonging to the given module group.
|
|
1923
|
+
* @param value - The module group to filter by.
|
|
1924
|
+
* @returns Array of matching `NameValueItem` entries.
|
|
1938
1925
|
*/
|
|
1939
1926
|
static getClipperModuleGroupItems(value) {
|
|
1940
1927
|
return ClipperModules.filter(n => n.parentValue === value);
|
|
1941
1928
|
}
|
|
1942
1929
|
/**
|
|
1943
|
-
*
|
|
1944
|
-
* @param modules
|
|
1945
|
-
* @param
|
|
1946
|
-
* @
|
|
1930
|
+
* Tests a set of modules against the currently selected modules in the search filter.
|
|
1931
|
+
* @param modules - The modules to test.
|
|
1932
|
+
* @param currentModules - The currently selected modules to check against.
|
|
1933
|
+
* @param mode - Matching strategy:
|
|
1934
|
+
* `1` = all and only the specified modules (exact set),
|
|
1935
|
+
* `2` = all specified modules must be present,
|
|
1936
|
+
* `3` = at least one specified module must be present.
|
|
1937
|
+
* @returns `true` when the condition defined by `mode` is satisfied.
|
|
1947
1938
|
*/
|
|
1948
1939
|
static checkModules(modules, currentModules, mode = 1) {
|
|
1949
1940
|
let ok = false;
|
|
1950
1941
|
if (mode === 1) {
|
|
1951
1942
|
// All and only the elements specified
|
|
1952
|
-
for (
|
|
1953
|
-
ok =
|
|
1954
|
-
if (!ok)
|
|
1943
|
+
for (const current of currentModules) {
|
|
1944
|
+
ok = modules.findIndex(x => x === current.value) !== -1;
|
|
1945
|
+
if (!ok)
|
|
1955
1946
|
break;
|
|
1956
|
-
}
|
|
1957
1947
|
}
|
|
1958
|
-
ok = ok && modules.length >=
|
|
1948
|
+
ok = ok && modules.length >= currentModules.length;
|
|
1959
1949
|
}
|
|
1960
1950
|
else if (mode === 2) {
|
|
1961
1951
|
// All the elements specified
|
|
1962
|
-
for (
|
|
1963
|
-
ok =
|
|
1964
|
-
if (!ok)
|
|
1952
|
+
for (const mod of modules) {
|
|
1953
|
+
ok = currentModules.findIndex(x => x.value === mod) !== -1;
|
|
1954
|
+
if (!ok)
|
|
1965
1955
|
break;
|
|
1966
|
-
}
|
|
1967
1956
|
}
|
|
1968
1957
|
}
|
|
1969
1958
|
else if (mode === 3) {
|
|
1970
|
-
// Any of the specified elements
|
|
1971
|
-
for (
|
|
1972
|
-
ok =
|
|
1973
|
-
if (ok)
|
|
1959
|
+
// Any of the specified elements
|
|
1960
|
+
for (const mod of modules) {
|
|
1961
|
+
ok = currentModules.findIndex(x => x.value === mod) !== -1;
|
|
1962
|
+
if (ok)
|
|
1974
1963
|
break;
|
|
1975
|
-
}
|
|
1976
1964
|
}
|
|
1977
1965
|
}
|
|
1978
1966
|
return ok;
|
|
1979
1967
|
}
|
|
1980
1968
|
/**
|
|
1981
|
-
*
|
|
1982
|
-
*
|
|
1983
|
-
* @
|
|
1969
|
+
* Returns the sort options available for the given module selection.
|
|
1970
|
+
* Includes the relevance option only when the query contains free text.
|
|
1971
|
+
* @param modules - Currently selected modules (used to determine which date axes are available).
|
|
1972
|
+
* @param params - Current search params (checked for free-text content).
|
|
1973
|
+
* @returns Array of applicable `NameValueItem<ClipperSort>` sort options.
|
|
1984
1974
|
*/
|
|
1985
1975
|
static getClipperAvailableSortOptions(modules, params) {
|
|
1986
1976
|
const options = [
|
|
@@ -1991,7 +1981,7 @@ class ClipperUtils {
|
|
|
1991
1981
|
{ name: "Rilevanza", value: ClipperSort.Relevance },
|
|
1992
1982
|
//{ name: "Popolarità", value: ClipperSort.Popularity },
|
|
1993
1983
|
];
|
|
1994
|
-
|
|
1984
|
+
const sortOptions = [];
|
|
1995
1985
|
if (params && ClipperSearchUtils.isTextQuery(params)) {
|
|
1996
1986
|
sortOptions.push(options[4]);
|
|
1997
1987
|
}
|
|
@@ -2019,8 +2009,8 @@ class ClipperUtils {
|
|
|
2019
2009
|
}
|
|
2020
2010
|
class ClipperSearchUtils {
|
|
2021
2011
|
/**
|
|
2022
|
-
*
|
|
2023
|
-
* @param params
|
|
2012
|
+
* Resets all filter fields of a `ClipperSearchParams` instance to their default (empty) values.
|
|
2013
|
+
* @param params - The search-params object to clear.
|
|
2024
2014
|
*/
|
|
2025
2015
|
static clear(params) {
|
|
2026
2016
|
params.sector = undefined;
|
|
@@ -2068,14 +2058,14 @@ class ClipperSearchUtils {
|
|
|
2068
2058
|
params.modules = undefined;
|
|
2069
2059
|
}
|
|
2070
2060
|
/**
|
|
2071
|
-
*
|
|
2072
|
-
* @param modules
|
|
2073
|
-
* @returns the
|
|
2061
|
+
* Returns the list of `ClipperModel` values that correspond to the given modules.
|
|
2062
|
+
* @param modules - The selected modules to map to their underlying data models.
|
|
2063
|
+
* @returns Array of `ClipperModel` values matching the provided modules.
|
|
2074
2064
|
*/
|
|
2075
2065
|
static getModulesModels(modules) {
|
|
2076
2066
|
const models = [];
|
|
2077
|
-
if (
|
|
2078
|
-
modules
|
|
2067
|
+
if (modules && modules.length > 0) {
|
|
2068
|
+
modules.forEach(module => {
|
|
2079
2069
|
switch (module.value) {
|
|
2080
2070
|
case ClipperModule.ScadenzeESegnalazioni:
|
|
2081
2071
|
[ClipperModel.Scadenze, ClipperModel.Segnalazioni].forEach(x => models.push(x));
|
|
@@ -2113,18 +2103,18 @@ class ClipperSearchUtils {
|
|
|
2113
2103
|
return models;
|
|
2114
2104
|
}
|
|
2115
2105
|
/**
|
|
2116
|
-
*
|
|
2117
|
-
* @param params
|
|
2118
|
-
* @returns true if is a text based search
|
|
2106
|
+
* Returns `true` when the search params contain a non-empty free-text query.
|
|
2107
|
+
* @param params - The search params to inspect.
|
|
2119
2108
|
*/
|
|
2120
2109
|
static isTextQuery(params) {
|
|
2121
|
-
return params.text != null && params.text
|
|
2110
|
+
return params.text != null && params.text.length > 0;
|
|
2122
2111
|
}
|
|
2123
2112
|
/**
|
|
2124
|
-
*
|
|
2125
|
-
* @param q
|
|
2126
|
-
* @param queries
|
|
2127
|
-
|
|
2113
|
+
* Wraps `q` in quotes (if not already quoted) and appends it to `queries`.
|
|
2114
|
+
* @param q - A single search term to process.
|
|
2115
|
+
* @param queries - The accumulated query string to append to.
|
|
2116
|
+
* @returns The updated `queries` string.
|
|
2117
|
+
*/
|
|
2128
2118
|
static concatTextQuery(q, queries) {
|
|
2129
2119
|
if (q && q.length > 1) {
|
|
2130
2120
|
if ((q[0] === '+' || q[0] === '-') && q[1] !== '"') {
|
|
@@ -2138,9 +2128,9 @@ class ClipperSearchUtils {
|
|
|
2138
2128
|
return queries;
|
|
2139
2129
|
}
|
|
2140
2130
|
/**
|
|
2141
|
-
*
|
|
2142
|
-
* @param text
|
|
2143
|
-
* @returns
|
|
2131
|
+
* Normalises a comma-separated search string by wrapping each term in quotes.
|
|
2132
|
+
* @param text - The raw search input to normalise.
|
|
2133
|
+
* @returns The normalised query string, or `undefined` when `text` is empty.
|
|
2144
2134
|
*/
|
|
2145
2135
|
static normalizeTextQuery(text) {
|
|
2146
2136
|
if (!text || text.length === 0)
|
|
@@ -2159,22 +2149,24 @@ class ClipperSearchUtils {
|
|
|
2159
2149
|
return queries;
|
|
2160
2150
|
}
|
|
2161
2151
|
/**
|
|
2162
|
-
*
|
|
2163
|
-
*
|
|
2164
|
-
* @param text
|
|
2165
|
-
* @returns
|
|
2152
|
+
* Wraps the entire query in double quotes when it contains no boolean operators
|
|
2153
|
+
* (`"`, `+`, or ` -`), making it an exact-phrase search.
|
|
2154
|
+
* @param text - The query string to normalise.
|
|
2155
|
+
* @returns The normalised query string.
|
|
2166
2156
|
*/
|
|
2167
2157
|
static normalizeTextQuery2(text) {
|
|
2158
|
+
if (!text)
|
|
2159
|
+
return text;
|
|
2168
2160
|
// Add quotes only if there are no quoted elements, no '+', and no ' -'
|
|
2169
|
-
if (!text
|
|
2161
|
+
if (!text.includes('"') && !text.includes('+') && !text.includes(' -')) {
|
|
2170
2162
|
return '"' + text + '"';
|
|
2171
2163
|
}
|
|
2172
2164
|
return text;
|
|
2173
2165
|
}
|
|
2174
2166
|
/**
|
|
2175
|
-
*
|
|
2176
|
-
* @param value
|
|
2177
|
-
* @returns
|
|
2167
|
+
* Maps a letter rank (`A`, `B`, or any other) to a numeric relevance threshold.
|
|
2168
|
+
* @param value - The single-character rank string.
|
|
2169
|
+
* @returns `0.751` for `'A'`, `0.71` for `'B'`, `0.51` for anything else.
|
|
2178
2170
|
*/
|
|
2179
2171
|
static getRankFromChar(value) {
|
|
2180
2172
|
switch (value.toUpperCase()) {
|
|
@@ -3334,79 +3326,107 @@ class ClipperService {
|
|
|
3334
3326
|
getPropertiesTrackingsPending() {
|
|
3335
3327
|
return this.httpClient.get(this._serviceUri + '/account/properties/trackings/pending');
|
|
3336
3328
|
}
|
|
3337
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
3338
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
3329
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ClipperService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3330
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ClipperService, providedIn: 'root' }); }
|
|
3339
3331
|
}
|
|
3340
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
3332
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ClipperService, decorators: [{
|
|
3341
3333
|
type: Injectable,
|
|
3342
3334
|
args: [{
|
|
3343
3335
|
providedIn: 'root',
|
|
3344
3336
|
}]
|
|
3345
3337
|
}] });
|
|
3346
3338
|
|
|
3339
|
+
/** Minimum milliseconds between consecutive error broadcasts (debounce guard). */
|
|
3340
|
+
const ERROR_DEBOUNCE_MS = 5000;
|
|
3341
|
+
/**
|
|
3342
|
+
* HTTP interceptor that attaches Clipper authentication headers to every request
|
|
3343
|
+
* targeting the Clipper service, and broadcasts user-friendly error messages
|
|
3344
|
+
* when the server returns an error response.
|
|
3345
|
+
*/
|
|
3347
3346
|
class ClipperAuthInterceptor {
|
|
3348
3347
|
constructor() {
|
|
3349
3348
|
this.clipperService = inject(ClipperService);
|
|
3350
3349
|
this.broadcastService = inject(BroadcastService);
|
|
3351
3350
|
this.lastErrorTime = -1;
|
|
3352
3351
|
}
|
|
3352
|
+
/**
|
|
3353
|
+
* Intercepts every outgoing HTTP request.
|
|
3354
|
+
* When the request targets the Clipper service URI, attaches credentials and
|
|
3355
|
+
* a client-ID header, then pipes the response through an error handler.
|
|
3356
|
+
* @param request - The outgoing HTTP request.
|
|
3357
|
+
* @param next - The next handler in the interceptor chain.
|
|
3358
|
+
* @returns An observable of the HTTP event stream.
|
|
3359
|
+
*/
|
|
3353
3360
|
intercept(request, next) {
|
|
3354
|
-
if (request.url.startsWith(this.clipperService.serviceUri)) {
|
|
3355
|
-
|
|
3356
|
-
withCredentials: true,
|
|
3357
|
-
setHeaders: {
|
|
3358
|
-
'ngsw-bypass': 'ngsw-bypass',
|
|
3359
|
-
'X-Client-Id': sessionStorage.getItem('clipper_client_id') ?? ''
|
|
3360
|
-
}
|
|
3361
|
-
});
|
|
3362
|
-
return next.handle(request)
|
|
3363
|
-
.pipe(catchError$1(error => {
|
|
3364
|
-
if (error.url.startsWith(this.clipperService.serviceUri)) {
|
|
3365
|
-
const errorStatus = parseInt(error.status ?? "0");
|
|
3366
|
-
if ((errorStatus > 0 && errorStatus < 500) || (this.clipperService.flags & ClipperServiceFlags.NotifySystemErrors) > 0) {
|
|
3367
|
-
const errorTime = new Date().getTime();
|
|
3368
|
-
if (errorTime - this.lastErrorTime > 5000) {
|
|
3369
|
-
this.lastErrorTime = errorTime;
|
|
3370
|
-
let message = "";
|
|
3371
|
-
switch (errorStatus) {
|
|
3372
|
-
case 0:
|
|
3373
|
-
message = "In questo momento Clipper non è disponibile. Riprova tra qualche minuto.";
|
|
3374
|
-
break;
|
|
3375
|
-
case 403:
|
|
3376
|
-
message = "Non hai i permessi necessari per eseguire l'operazione richiesta.";
|
|
3377
|
-
break;
|
|
3378
|
-
default:
|
|
3379
|
-
message = (error.error?.message ?? error.message ?? "Impossibile eseguire l'operazione richiesta.").replaceAll("\r\n", "</p><p>");
|
|
3380
|
-
break;
|
|
3381
|
-
}
|
|
3382
|
-
this.broadcastService.sendMessage(ClipperMessages.ERROR, {
|
|
3383
|
-
invalidateSession: errorStatus === 405 || errorStatus === 410,
|
|
3384
|
-
message: message,
|
|
3385
|
-
title: "Errore in Clipper",
|
|
3386
|
-
errorStatus: errorStatus,
|
|
3387
|
-
service: this.clipperService.serviceUri
|
|
3388
|
-
});
|
|
3389
|
-
}
|
|
3390
|
-
}
|
|
3391
|
-
}
|
|
3392
|
-
return throwError(() => error);
|
|
3393
|
-
}));
|
|
3361
|
+
if (!request.url.startsWith(this.clipperService.serviceUri)) {
|
|
3362
|
+
return next.handle(request);
|
|
3394
3363
|
}
|
|
3395
|
-
|
|
3364
|
+
const authenticatedRequest = request.clone({
|
|
3365
|
+
withCredentials: true,
|
|
3366
|
+
setHeaders: {
|
|
3367
|
+
'ngsw-bypass': 'ngsw-bypass',
|
|
3368
|
+
'X-Client-Id': sessionStorage.getItem('clipper_client_id') ?? ''
|
|
3369
|
+
}
|
|
3370
|
+
});
|
|
3371
|
+
return next.handle(authenticatedRequest).pipe(catchError$1((error) => {
|
|
3372
|
+
this.handleError(error);
|
|
3373
|
+
return throwError(() => error);
|
|
3374
|
+
}));
|
|
3375
|
+
}
|
|
3376
|
+
/**
|
|
3377
|
+
* Processes an HTTP error, broadcasting a user-friendly message when appropriate.
|
|
3378
|
+
* Errors are debounced: only one message is sent per `ERROR_DEBOUNCE_MS` window.
|
|
3379
|
+
* @param error - The raw error value thrown by the HTTP layer.
|
|
3380
|
+
*/
|
|
3381
|
+
handleError(error) {
|
|
3382
|
+
if (!(error instanceof HttpErrorResponse))
|
|
3383
|
+
return;
|
|
3384
|
+
if (!error.url?.startsWith(this.clipperService.serviceUri))
|
|
3385
|
+
return;
|
|
3386
|
+
const errorStatus = error.status;
|
|
3387
|
+
const shouldNotify = (errorStatus > 0 && errorStatus < 500) ||
|
|
3388
|
+
(this.clipperService.flags & ClipperServiceFlags.NotifySystemErrors) > 0;
|
|
3389
|
+
if (!shouldNotify)
|
|
3390
|
+
return;
|
|
3391
|
+
const now = Date.now();
|
|
3392
|
+
if (now - this.lastErrorTime <= ERROR_DEBOUNCE_MS)
|
|
3393
|
+
return;
|
|
3394
|
+
this.lastErrorTime = now;
|
|
3395
|
+
let message;
|
|
3396
|
+
switch (errorStatus) {
|
|
3397
|
+
case 0:
|
|
3398
|
+
message = "In questo momento Clipper non è disponibile. Riprova tra qualche minuto.";
|
|
3399
|
+
break;
|
|
3400
|
+
case 403:
|
|
3401
|
+
message = "Non hai i permessi necessari per eseguire l'operazione richiesta.";
|
|
3402
|
+
break;
|
|
3403
|
+
default:
|
|
3404
|
+
message = (error.error?.['message'] ??
|
|
3405
|
+
error.message ??
|
|
3406
|
+
"Impossibile eseguire l'operazione richiesta.").replaceAll('\r\n', '</p><p>');
|
|
3407
|
+
break;
|
|
3408
|
+
}
|
|
3409
|
+
this.broadcastService.sendMessage(ClipperMessages.ERROR, {
|
|
3410
|
+
invalidateSession: errorStatus === 405 || errorStatus === 410,
|
|
3411
|
+
message,
|
|
3412
|
+
title: "Errore in Clipper",
|
|
3413
|
+
errorStatus,
|
|
3414
|
+
service: this.clipperService.serviceUri
|
|
3415
|
+
});
|
|
3396
3416
|
}
|
|
3397
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
3398
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
3417
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ClipperAuthInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3418
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ClipperAuthInterceptor }); }
|
|
3399
3419
|
}
|
|
3400
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
3420
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ClipperAuthInterceptor, decorators: [{
|
|
3401
3421
|
type: Injectable
|
|
3402
3422
|
}] });
|
|
3403
3423
|
|
|
3404
3424
|
class ArsClipperCommonModule {
|
|
3405
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
3406
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.
|
|
3407
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.
|
|
3425
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ArsClipperCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
3426
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.10", ngImport: i0, type: ArsClipperCommonModule }); }
|
|
3427
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ArsClipperCommonModule }); }
|
|
3408
3428
|
}
|
|
3409
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
3429
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ArsClipperCommonModule, decorators: [{
|
|
3410
3430
|
type: NgModule
|
|
3411
3431
|
}] });
|
|
3412
3432
|
|