@edifice.io/client 2.5.24 → 2.6.0-develop-integration.20260710151131

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/dist/index.js CHANGED
@@ -1082,9 +1082,9 @@ class Analytics {
1082
1082
  const t = await notify.onSessionReady().promise, s = session.session.description;
1083
1083
  let r;
1084
1084
  for (const l of t.structures) {
1085
- const p = e.structureMap[l];
1086
- if (p && p.collectiviteId && p.UAI) {
1087
- r = p;
1085
+ const h = e.structureMap[l];
1086
+ if (h && h.collectiviteId && h.UAI) {
1087
+ r = h;
1088
1088
  break;
1089
1089
  }
1090
1090
  }
@@ -1096,10 +1096,10 @@ class Analytics {
1096
1096
  const o = i.xiti;
1097
1097
  if (!o || !o.LIBELLE_SERVICE || !r.UAI) return;
1098
1098
  function a(l) {
1099
- let p = "";
1099
+ let h = "";
1100
1100
  for (let E = 0; E < l.length; E++)
1101
- p += l.charCodeAt(E);
1102
- return p;
1101
+ h += l.charCodeAt(E);
1102
+ return h;
1103
1103
  }
1104
1104
  const c = {
1105
1105
  Student: "ELEVE",
@@ -1635,22 +1635,27 @@ const m = class m {
1635
1635
  u(m, "registry", new ServiceRegistry()), // Expose some useful functions
1636
1636
  u(m, "register", m.registry.register.bind(m.registry)), u(m, "findService", m.registry.findService.bind(m.registry)), u(m, "findMainService", m.registry.findMainService.bind(m.registry)), u(m, "isRegistered", m.registry.isRegistered.bind(m.registry));
1637
1637
  let ResourceService = m;
1638
- const APP$3 = "scrapbook", RESOURCE$3 = "scrapbook";
1639
- class ScrapbookResourceService extends ResourceService {
1640
- create(e) {
1641
- throw new Error("Method not implemented.");
1638
+ const APP$3 = "collaborativeeditor", RESOURCE$3 = "collaborativeeditor";
1639
+ class CollaborativeEditorResourceService extends ResourceService {
1640
+ async create(e) {
1641
+ const { name: t, description: s, thumbnail: r, folder: i } = e, o = r ? await this.getThumbnailPath(r) : "", a = await this.http.post("/collaborativeeditor", {
1642
+ name: t,
1643
+ description: s,
1644
+ thumbnail: o,
1645
+ folder: i
1646
+ });
1647
+ return this.checkHttpResponse(a), a;
1642
1648
  }
1643
1649
  async update(e) {
1644
- const t = await this.getThumbnailPath(e.thumbnail), s = await this.http.put(
1645
- `/scrapbook/${e.entId}`,
1650
+ const { name: t, description: s, thumbnail: r, entId: i } = e, o = await this.getThumbnailPath(r), a = await this.http.put(
1651
+ `/collaborativeeditor/${i}`,
1646
1652
  {
1647
- trashed: e.trashed ? 1 : 0,
1648
- title: e.name,
1649
- icon: t,
1650
- subTitle: e.description
1653
+ name: t,
1654
+ description: s,
1655
+ thumbnail: o
1651
1656
  }
1652
1657
  );
1653
- return this.checkHttpResponse(s), { thumbnail: t, entId: e.entId };
1658
+ return this.checkHttpResponse(a), { thumbnail: o, entId: i };
1654
1659
  }
1655
1660
  getResourceType() {
1656
1661
  return RESOURCE$3;
@@ -1658,25 +1663,25 @@ class ScrapbookResourceService extends ResourceService {
1658
1663
  getApplication() {
1659
1664
  return APP$3;
1660
1665
  }
1661
- getFormUrl(e) {
1662
- return e ? `/scrapbook?folderid=${e}#/create-scrapbook/` : "/scrapbook#/create-scrapbook/";
1666
+ getFormUrl() {
1667
+ throw new Error("Method not implemented.");
1663
1668
  }
1664
1669
  getViewUrl(e) {
1665
- return `/scrapbook#/view-scrapbook/${e}`;
1670
+ return `/collaborativeeditor#/view/${e}`;
1666
1671
  }
1667
- getPrintUrl(e) {
1668
- return `/scrapbook/print#/print-scrapbook/${e}`;
1672
+ getPrintUrl() {
1673
+ throw new Error("Method not implemented.");
1669
1674
  }
1670
- getEditUrl(e) {
1671
- return `/scrapbook#/edit-scrapbook/${e}`;
1675
+ getEditUrl() {
1676
+ throw new Error("Method not implemented.");
1672
1677
  }
1673
- getExportUrl(e) {
1674
- return `/scrapbook/exportHtml/${e}`;
1678
+ getExportUrl() {
1679
+ throw new Error("Method not implemented.");
1675
1680
  }
1676
1681
  }
1677
1682
  ResourceService.register(
1678
1683
  { application: RESOURCE$3, resourceType: RESOURCE$3 },
1679
- (n) => new ScrapbookResourceService(n)
1684
+ (n) => new CollaborativeEditorResourceService(n)
1680
1685
  );
1681
1686
  const APP$2 = "homeworks", RESOURCE$2 = "homeworks";
1682
1687
  class HomeworksResourceService extends ResourceService {
@@ -1728,31 +1733,19 @@ ResourceService.register(
1728
1733
  { application: RESOURCE$2, resourceType: RESOURCE$2 },
1729
1734
  (n) => new HomeworksResourceService(n)
1730
1735
  );
1731
- const APP$1 = "timelinegenerator", RESOURCE$1 = "timelinegenerator";
1732
- class TimelineGeneratorResourceService extends ResourceService {
1733
- async create(e) {
1734
- const t = e.thumbnail ? await this.getThumbnailPath(e.thumbnail) : "", s = await this.http.post(
1735
- "/timelinegenerator/timelines",
1736
- {
1737
- headline: e.name,
1738
- text: e.description,
1739
- icon: t,
1740
- type: "default",
1741
- folder: e.folder
1742
- }
1743
- );
1744
- return this.checkHttpResponse(s), s;
1736
+ const APP$1 = "scrapbook", RESOURCE$1 = "scrapbook";
1737
+ class ScrapbookResourceService extends ResourceService {
1738
+ create(e) {
1739
+ throw new Error("Method not implemented.");
1745
1740
  }
1746
1741
  async update(e) {
1747
1742
  const t = await this.getThumbnailPath(e.thumbnail), s = await this.http.put(
1748
- `/timelinegenerator/timeline/${e.entId}`,
1743
+ `/scrapbook/${e.entId}`,
1749
1744
  {
1750
- headline: e.name,
1751
- text: e.description,
1745
+ trashed: e.trashed ? 1 : 0,
1746
+ title: e.name,
1752
1747
  icon: t,
1753
- trashed: !!e.trashed,
1754
- _id: e.entId,
1755
- type: "default"
1748
+ subTitle: e.description
1756
1749
  }
1757
1750
  );
1758
1751
  return this.checkHttpResponse(s), { thumbnail: t, entId: e.entId };
@@ -1763,47 +1756,54 @@ class TimelineGeneratorResourceService extends ResourceService {
1763
1756
  getApplication() {
1764
1757
  return APP$1;
1765
1758
  }
1766
- getFormUrl() {
1767
- throw new Error("Method not implemented.");
1759
+ getFormUrl(e) {
1760
+ return e ? `/scrapbook?folderid=${e}#/create-scrapbook/` : "/scrapbook#/create-scrapbook/";
1768
1761
  }
1769
1762
  getViewUrl(e) {
1770
- return `/timelinegenerator#/view/${e}`;
1763
+ return `/scrapbook#/view-scrapbook/${e}`;
1771
1764
  }
1772
1765
  getPrintUrl(e) {
1773
- return `/timelinegenerator/print#/print/${e}`;
1766
+ return `/scrapbook/print#/print-scrapbook/${e}`;
1774
1767
  }
1775
- getEditUrl() {
1776
- throw new Error("Method not implemented.");
1768
+ getEditUrl(e) {
1769
+ return `/scrapbook#/edit-scrapbook/${e}`;
1777
1770
  }
1778
- getExportUrl() {
1779
- throw new Error("Method not implemented.");
1771
+ getExportUrl(e) {
1772
+ return `/scrapbook/exportHtml/${e}`;
1780
1773
  }
1781
1774
  }
1782
1775
  ResourceService.register(
1783
1776
  { application: RESOURCE$1, resourceType: RESOURCE$1 },
1784
- (n) => new TimelineGeneratorResourceService(n)
1777
+ (n) => new ScrapbookResourceService(n)
1785
1778
  );
1786
- const APP = "collaborativeeditor", RESOURCE = "collaborativeeditor";
1787
- class CollaborativeEditorResourceService extends ResourceService {
1779
+ const APP = "timelinegenerator", RESOURCE = "timelinegenerator";
1780
+ class TimelineGeneratorResourceService extends ResourceService {
1788
1781
  async create(e) {
1789
- const { name: t, description: s, thumbnail: r, folder: i } = e, o = r ? await this.getThumbnailPath(r) : "", a = await this.http.post("/collaborativeeditor", {
1790
- name: t,
1791
- description: s,
1792
- thumbnail: o,
1793
- folder: i
1794
- });
1795
- return this.checkHttpResponse(a), a;
1782
+ const t = e.thumbnail ? await this.getThumbnailPath(e.thumbnail) : "", s = await this.http.post(
1783
+ "/timelinegenerator/timelines",
1784
+ {
1785
+ headline: e.name,
1786
+ text: e.description,
1787
+ icon: t,
1788
+ type: "default",
1789
+ folder: e.folder
1790
+ }
1791
+ );
1792
+ return this.checkHttpResponse(s), s;
1796
1793
  }
1797
1794
  async update(e) {
1798
- const { name: t, description: s, thumbnail: r, entId: i } = e, o = await this.getThumbnailPath(r), a = await this.http.put(
1799
- `/collaborativeeditor/${i}`,
1795
+ const t = await this.getThumbnailPath(e.thumbnail), s = await this.http.put(
1796
+ `/timelinegenerator/timeline/${e.entId}`,
1800
1797
  {
1801
- name: t,
1802
- description: s,
1803
- thumbnail: o
1798
+ headline: e.name,
1799
+ text: e.description,
1800
+ icon: t,
1801
+ trashed: !!e.trashed,
1802
+ _id: e.entId,
1803
+ type: "default"
1804
1804
  }
1805
1805
  );
1806
- return this.checkHttpResponse(a), { thumbnail: o, entId: i };
1806
+ return this.checkHttpResponse(s), { thumbnail: t, entId: e.entId };
1807
1807
  }
1808
1808
  getResourceType() {
1809
1809
  return RESOURCE;
@@ -1815,10 +1815,10 @@ class CollaborativeEditorResourceService extends ResourceService {
1815
1815
  throw new Error("Method not implemented.");
1816
1816
  }
1817
1817
  getViewUrl(e) {
1818
- return `/collaborativeeditor#/view/${e}`;
1818
+ return `/timelinegenerator#/view/${e}`;
1819
1819
  }
1820
- getPrintUrl() {
1821
- throw new Error("Method not implemented.");
1820
+ getPrintUrl(e) {
1821
+ return `/timelinegenerator/print#/print/${e}`;
1822
1822
  }
1823
1823
  getEditUrl() {
1824
1824
  throw new Error("Method not implemented.");
@@ -1829,77 +1829,283 @@ class CollaborativeEditorResourceService extends ResourceService {
1829
1829
  }
1830
1830
  ResourceService.register(
1831
1831
  { application: RESOURCE, resourceType: RESOURCE },
1832
- (n) => new CollaborativeEditorResourceService(n)
1832
+ (n) => new TimelineGeneratorResourceService(n)
1833
1833
  );
1834
- const globalCache = {}, mutexPromise = {};
1835
- class CacheService {
1836
- constructor(e) {
1837
- this.context = e;
1834
+ let ATTag;
1835
+ class AnalyticsService {
1836
+ constructor(n) {
1837
+ this.context = n;
1838
1838
  }
1839
1839
  get http() {
1840
1840
  return this.context.http();
1841
1841
  }
1842
- async fromCacheIfPossible(e, t, s) {
1843
- if (mutexPromise[e] !== void 0 && await mutexPromise[e], globalCache[e])
1844
- return globalCache[e];
1845
- try {
1846
- const r = t();
1847
- mutexPromise[e] = r;
1848
- const i = await r;
1849
- return s(i) && (globalCache[e] = i), i;
1850
- } catch (r) {
1851
- throw console.error(`Failed to retrieve value for: ${e}`, r), r;
1852
- }
1853
- }
1854
- clearCache(e) {
1855
- if (e)
1856
- delete globalCache[e];
1857
- else
1858
- for (const t in globalCache)
1859
- globalCache.hasOwnProperty(t) && delete globalCache[t];
1842
+ get session() {
1843
+ return this.context.session();
1860
1844
  }
1861
- async httpGet(e, t) {
1862
- return this.fromCacheIfPossible(
1863
- e,
1864
- async () => {
1865
- const s = await this.http.get(e, t), r = { ...this.http.latestResponse };
1866
- return { value: s, response: r };
1845
+ /**
1846
+ * Xiti tracker for page loading.
1847
+ * @param locationPath
1848
+ * @param app
1849
+ */
1850
+ async trackPageLoad(n, e) {
1851
+ const [t] = await Promise.all([
1852
+ // get Xiti configuration
1853
+ this.getXitiConfig(e.name.toLowerCase()),
1854
+ // load Xiti javascript file
1855
+ this.loadXitiScript()
1856
+ ]);
1857
+ if (!t || !ATInternet) return;
1858
+ let s = t.LIBELLE_SERVICE.default || null;
1859
+ for (const r in t.LIBELLE_SERVICE)
1860
+ if (r !== "default" && n.indexOf(r) >= 0) {
1861
+ s = t.LIBELLE_SERVICE[r];
1862
+ break;
1863
+ }
1864
+ ATTag = new ATInternet.Tracker.Tag({ site: t.STRUCT_ID }), ATTag.setProps(
1865
+ {
1866
+ SERVICE: s,
1867
+ TYPE: t.TYPE,
1868
+ OUTIL: t.OUTIL,
1869
+ UAI: t.STRUCT_UAI,
1870
+ PROJET: t.PROJET,
1871
+ EXPLOITANT: t.EXPLOITANT,
1872
+ PLATEFORME: t.PLATFORME,
1873
+ PROFIL: t.PROFILE
1867
1874
  },
1868
- ({ response: s }) => !(s.status < 200 || s.status >= 300)
1869
- );
1870
- }
1871
- async httpGetJson(e, t) {
1872
- const { response: s, value: r } = await this.httpGet(e, t);
1873
- if (s.status < 200 || s.status >= 300)
1874
- throw `Bad http status (${s.status}) for url: ${e}`;
1875
- return r;
1876
- }
1877
- }
1878
- class ConfService {
1879
- constructor(e) {
1880
- this.context = e;
1881
- }
1882
- get http() {
1883
- return this.context.http();
1884
- }
1885
- get cache() {
1886
- return this.context.cache();
1875
+ !0
1876
+ ), ATTag.identifiedVisitor.set({
1877
+ id: t.ID_PERSO,
1878
+ category: t.PROFILE
1879
+ }), ATTag.page.set({
1880
+ name: (e == null ? void 0 : e.prefix) === "userbook" ? "directory" : e == null ? void 0 : e.prefix,
1881
+ chapter1: "",
1882
+ chapter2: "",
1883
+ chapter3: "",
1884
+ level2: t.STRUCT_UAI
1885
+ }), ATTag.dispatch();
1887
1886
  }
1888
- get cdnDomain() {
1889
- return configure.Platform.cdnDomain;
1887
+ async getXitiConfig(n) {
1888
+ const [e, t] = await Promise.all([
1889
+ this.http.get("/analyticsConf"),
1890
+ //FIXME change servers config to only keep the "all-in-one" query to /analyticsConf.
1891
+ this.http.get("/xiti/config")
1892
+ ]);
1893
+ if (!(e != null && e.type))
1894
+ throw ERROR_CODE.MALFORMED_DATA;
1895
+ return t != null && t.active && (e.xiti = await this.getXitiTrackingParams(t, n)), e.xiti;
1890
1896
  }
1891
- get notify() {
1892
- return this.context.notify();
1897
+ async loadXitiScript() {
1898
+ if (typeof ATInternet > "u") {
1899
+ const scriptPath = "/xiti/public/js/lib/smarttag_ENT.js", response = await this.http.get(scriptPath, {
1900
+ headers: { Accept: "application/javascript" }
1901
+ });
1902
+ if (this.http.latestResponse.status != 200)
1903
+ throw "Error while loading XiTi script";
1904
+ eval(response);
1905
+ }
1893
1906
  }
1894
- async getConf(e) {
1895
- const [t, s] = await Promise.all([
1896
- this.getThemeConf(),
1897
- this.getApplicationsList()
1898
- ]), [r, i] = await Promise.all([
1899
- this.getTheme({ conf: t, publicTheme: s === void 0 }),
1900
- this.getWebAppConf({ app: e, applications: s ?? [] })
1901
- ]), o = {
1902
- app: e,
1907
+ async getXitiTrackingParams(n, e) {
1908
+ if (!n.structureMap || !e) return;
1909
+ const t = await this.session.getUser(), s = await this.session.getUserProfile();
1910
+ let r;
1911
+ if (!(t != null && t.structures)) return;
1912
+ for (const l of t.structures) {
1913
+ const h = n.structureMap[l];
1914
+ if (h && h.collectiviteId && h.UAI) {
1915
+ r = h;
1916
+ break;
1917
+ }
1918
+ }
1919
+ if (!r || !r.active) return;
1920
+ const i = await configure.Platform.apps.getPublicConf(e);
1921
+ if (!i) return;
1922
+ const o = i.xiti;
1923
+ if (!o || !o.LIBELLE_SERVICE || !r.UAI) return;
1924
+ function a(l) {
1925
+ let h = "";
1926
+ for (let E = 0; E < l.length; E++)
1927
+ h += l.charCodeAt(E);
1928
+ return h;
1929
+ }
1930
+ const c = {
1931
+ Student: "ELEVE",
1932
+ Teacher: "ENSEIGNANT",
1933
+ Relative: "PARENT",
1934
+ Personnel: "ADMIN_VIE_SCOL_TECH",
1935
+ Guest: "AUTRE"
1936
+ };
1937
+ return {
1938
+ LIBELLE_SERVICE: o.LIBELLE_SERVICE,
1939
+ // Which property of LIBELLE_SERVICE to use depends on the frontend.
1940
+ TYPE: o.OUTIL ? "TIERS" : "NATIF",
1941
+ OUTIL: o.OUTIL ? o.OUTIL : "",
1942
+ STRUCT_ID: r.collectiviteId,
1943
+ STRUCT_UAI: r.UAI,
1944
+ PROJET: r.projetId ? r.projetId : n.ID_PROJET,
1945
+ EXPLOITANT: n.ID_EXPLOITANT,
1946
+ PLATFORME: r.plateformeId ? r.plateformeId : n.ID_PLATEFORME,
1947
+ ID_PERSO: a(t.userId),
1948
+ PROFILE: s && s.length > 0 ? c[s[0]] ?? "" : ""
1949
+ };
1950
+ }
1951
+ }
1952
+ class ReactionsService {
1953
+ constructor(e, t, s) {
1954
+ this.context = e, this.module = t, this.resourceType = s;
1955
+ }
1956
+ get http() {
1957
+ return this.context.http();
1958
+ }
1959
+ async loadAvailableReactions() {
1960
+ try {
1961
+ const { "reaction-types": e } = await this.context.conf().getPublicConf("audience");
1962
+ return Array.isArray(e) ? e : void 0;
1963
+ } catch {
1964
+ console.error("Audience configuration not found");
1965
+ return;
1966
+ }
1967
+ }
1968
+ async loadReactionSummaries(e) {
1969
+ const t = await this.http.get(
1970
+ `/audience/reactions/${this.module}/${this.resourceType}?resourceIds=${e.join(",")}`
1971
+ );
1972
+ return this.http.isResponseError() ? {} : t.reactionsByResource;
1973
+ }
1974
+ async loadReactionDetails(e, t, s) {
1975
+ const r = await this.http.get(
1976
+ `/audience/reactions/${this.module}/${this.resourceType}/${e}?page=${t}&size=${s}`
1977
+ );
1978
+ return this.http.isResponseError() ? void 0 : r;
1979
+ }
1980
+ async deleteReaction(e) {
1981
+ await this.http.delete(
1982
+ `/audience/reactions/${this.module}/${this.resourceType}/${e}`
1983
+ );
1984
+ }
1985
+ async updateReaction(e, t) {
1986
+ await this.http.putJson(
1987
+ `/audience/reactions/${this.module}/${this.resourceType}`,
1988
+ {
1989
+ resourceId: e,
1990
+ reactionType: t
1991
+ }
1992
+ );
1993
+ }
1994
+ async createReaction(e, t) {
1995
+ await this.http.postJson(
1996
+ `/audience/reactions/${this.module}/${this.resourceType}`,
1997
+ {
1998
+ resourceId: e,
1999
+ reactionType: t
2000
+ }
2001
+ );
2002
+ }
2003
+ }
2004
+ class ViewsService {
2005
+ constructor(e, t, s) {
2006
+ this.context = e, this.module = t, this.resourceType = s;
2007
+ }
2008
+ get http() {
2009
+ return this.context.http();
2010
+ }
2011
+ async getCounters(e) {
2012
+ const t = await this.http.get(
2013
+ `/audience/views/count/${this.module}/${this.resourceType}?resourceIds=${e.join(",")}`
2014
+ );
2015
+ return this.http.isResponseError() ? {} : t;
2016
+ }
2017
+ async getDetails(e) {
2018
+ const t = await this.http.get(
2019
+ `/audience/views/details/${this.module}/${this.resourceType}/${e}`
2020
+ );
2021
+ return this.http.isResponseError() ? void 0 : t;
2022
+ }
2023
+ trigger(e) {
2024
+ return this.http.post(
2025
+ `/audience/views/${this.module}/${this.resourceType}/${e}`
2026
+ );
2027
+ }
2028
+ }
2029
+ class AudienceService {
2030
+ constructor(e, t, s) {
2031
+ this.context = e, this.module = t, this.resourceType = s;
2032
+ }
2033
+ get views() {
2034
+ return new ViewsService(this.context, this.module, this.resourceType);
2035
+ }
2036
+ get reactions() {
2037
+ return new ReactionsService(this.context, this.module, this.resourceType);
2038
+ }
2039
+ }
2040
+ const globalCache = {}, mutexPromise = {};
2041
+ class CacheService {
2042
+ constructor(e) {
2043
+ this.context = e;
2044
+ }
2045
+ get http() {
2046
+ return this.context.http();
2047
+ }
2048
+ async fromCacheIfPossible(e, t, s) {
2049
+ if (mutexPromise[e] !== void 0 && await mutexPromise[e], globalCache[e])
2050
+ return globalCache[e];
2051
+ try {
2052
+ const r = t();
2053
+ mutexPromise[e] = r;
2054
+ const i = await r;
2055
+ return s(i) && (globalCache[e] = i), i;
2056
+ } catch (r) {
2057
+ throw console.error(`Failed to retrieve value for: ${e}`, r), r;
2058
+ }
2059
+ }
2060
+ clearCache(e) {
2061
+ if (e)
2062
+ delete globalCache[e];
2063
+ else
2064
+ for (const t in globalCache)
2065
+ globalCache.hasOwnProperty(t) && delete globalCache[t];
2066
+ }
2067
+ async httpGet(e, t) {
2068
+ return this.fromCacheIfPossible(
2069
+ e,
2070
+ async () => {
2071
+ const s = await this.http.get(e, t), r = { ...this.http.latestResponse };
2072
+ return { value: s, response: r };
2073
+ },
2074
+ ({ response: s }) => !(s.status < 200 || s.status >= 300)
2075
+ );
2076
+ }
2077
+ async httpGetJson(e, t) {
2078
+ const { response: s, value: r } = await this.httpGet(e, t);
2079
+ if (s.status < 200 || s.status >= 300)
2080
+ throw `Bad http status (${s.status}) for url: ${e}`;
2081
+ return r;
2082
+ }
2083
+ }
2084
+ class ConfService {
2085
+ constructor(e) {
2086
+ this.context = e;
2087
+ }
2088
+ get http() {
2089
+ return this.context.http();
2090
+ }
2091
+ get cache() {
2092
+ return this.context.cache();
2093
+ }
2094
+ get cdnDomain() {
2095
+ return configure.Platform.cdnDomain;
2096
+ }
2097
+ get notify() {
2098
+ return this.context.notify();
2099
+ }
2100
+ async getConf(e) {
2101
+ const [t, s] = await Promise.all([
2102
+ this.getThemeConf(),
2103
+ this.getApplicationsList()
2104
+ ]), [r, i] = await Promise.all([
2105
+ this.getTheme({ conf: t, publicTheme: s === void 0 }),
2106
+ this.getWebAppConf({ app: e, applications: s ?? [] })
2107
+ ]), o = {
2108
+ app: e,
1903
2109
  applications: s ?? [],
1904
2110
  conf: t,
1905
2111
  currentApp: i,
@@ -1959,17 +2165,17 @@ class ConfService {
1959
2165
  }) {
1960
2166
  var E;
1961
2167
  const r = await this.http.get("/theme"), i = (E = t == null ? void 0 : t.overriding) == null ? void 0 : E.find(
1962
- (h) => (
2168
+ (p) => (
1963
2169
  // Fix #WB2-2660:
1964
2170
  // If Public access => get the neo theme
1965
2171
  // Else get the theme from the user preference
1966
- s ? h.parent === "theme-open-ent" && h.bootstrapVersion === "ode-bootstrap-neo" : h.child === (r == null ? void 0 : r.themeName)
2172
+ s ? p.parent === "theme-open-ent" && p.bootstrapVersion === "ode-bootstrap-neo" : p.child === (r == null ? void 0 : r.themeName)
1967
2173
  )
1968
- ), o = s ? "default" : (r == null ? void 0 : r.skinName) || (i == null ? void 0 : i.skins[0]), a = (r == null ? void 0 : r.skin) || `/assets/themes/${i == null ? void 0 : i.child}/skins/${o}/`, c = i == null ? void 0 : i.skins, l = i == null ? void 0 : i.bootstrapVersion.split("-").slice(-1)[0], p = (i == null ? void 0 : i.parent) === "panda";
2174
+ ), o = s ? "default" : (r == null ? void 0 : r.skinName) || (i == null ? void 0 : i.skins[0]), a = (r == null ? void 0 : r.skin) || `/assets/themes/${i == null ? void 0 : i.child}/skins/${o}/`, c = i == null ? void 0 : i.skins, l = i == null ? void 0 : i.bootstrapVersion.split("-").slice(-1)[0], h = (i == null ? void 0 : i.parent) === "panda";
1969
2175
  return {
1970
2176
  basePath: `${this.cdnDomain}${a}../../`,
1971
2177
  bootstrapVersion: l,
1972
- is1d: p,
2178
+ is1d: h,
1973
2179
  logoutCallback: (r == null ? void 0 : r.logoutCallback) || "",
1974
2180
  skin: i == null ? void 0 : i.child,
1975
2181
  skinName: o,
@@ -1988,54 +2194,164 @@ class ConfService {
1988
2194
  return s.logoutCallback;
1989
2195
  }
1990
2196
  }
1991
- class DirectoryService {
2197
+ const SEND_ALL = "*";
2198
+ class WebBroker {
1992
2199
  constructor(e) {
2200
+ u(this, "subscription");
1993
2201
  this.odeServices = e;
1994
2202
  }
1995
2203
  get http() {
1996
2204
  return this.odeServices.http();
1997
2205
  }
1998
- get cache() {
1999
- return this.odeServices.cache();
2206
+ get events() {
2207
+ return this.odeServices.notify().events();
2000
2208
  }
2001
- getAvatarUrl(e, t, s = "100x100") {
2002
- return t === "user" ? `/userbook/avatar/${e}?thumbnail=${s}` : "/assets/img/illustrations/group-avatar.svg";
2209
+ dispatchEvent(e, t) {
2210
+ t.findIndex(
2211
+ (r) => SEND_ALL === r || e.data["event-type"] === r
2212
+ ) >= 0 && this.http.post("/infra/event/web/store", e.data, {
2213
+ disableNotifications: !0
2214
+ });
2003
2215
  }
2004
- getDirectoryUrl(e, t) {
2005
- return t === "user" ? `/userbook/annuaire#/${e}` : `/userbook/annuaire#/group-view/${e}`;
2216
+ initialize(e) {
2217
+ if (e === void 0 || e.send === void 0 || e.send.length > 0) {
2218
+ const t = (e == null ? void 0 : e.send) ?? [SEND_ALL];
2219
+ this.subscription = this.events.subscribe(
2220
+ LAYER_NAME.WEB_DATA,
2221
+ (s) => this.dispatchEvent(s, t)
2222
+ );
2223
+ }
2224
+ return this;
2006
2225
  }
2007
- async getBookMarks() {
2008
- return (await this.cache.httpGetJson(
2009
- "/directory/sharebookmark/all"
2010
- )).map(({ id: t, name: s }) => ({
2011
- id: t,
2012
- displayName: s,
2013
- notVisibleCount: 0,
2014
- members: []
2015
- // this api does not return members
2016
- }));
2226
+ destroy() {
2227
+ this.subscription && (this.subscription.revoke(), delete this.subscription);
2017
2228
  }
2018
- async getBookMarkById(e) {
2019
- const { groups: t, id: s, name: r, users: i, notVisibleCount: o } = await this.http.get(
2020
- `/directory/sharebookmark/${e}`
2021
- );
2022
- return {
2023
- id: s,
2024
- displayName: r,
2025
- notVisibleCount: o,
2026
- groups: t.map(({ name: a, id: c, nbUsers: l }) => ({
2027
- nbUsers: l,
2028
- displayName: a,
2029
- id: c
2030
- })),
2031
- users: i.map(({ displayName: a, id: c, profile: l }) => ({
2032
- profile: l,
2033
- displayName: a,
2034
- // these info are missing from api
2035
- firstName: "",
2036
- lastName: "",
2037
- login: "",
2038
- id: c
2229
+ }
2230
+ class DataService {
2231
+ constructor(e) {
2232
+ u(this, "_webBroker");
2233
+ u(this, "app");
2234
+ u(this, "user");
2235
+ u(this, "profile");
2236
+ this.odeServices = e;
2237
+ }
2238
+ get conf() {
2239
+ return this.odeServices.conf();
2240
+ }
2241
+ get notify() {
2242
+ return this.odeServices.notify();
2243
+ }
2244
+ // This method is called once, by the service container.
2245
+ async initialize() {
2246
+ try {
2247
+ const { app: e } = await this.notify.onAppConfReady().promise;
2248
+ this.app = e, this.user = await this.odeServices.session().getUser(), this.profile = await this.odeServices.session().getUserProfile();
2249
+ const { ["data-service"]: t } = await this.conf.getPublicConf(e);
2250
+ this._webBroker = new WebBroker(this.odeServices).initialize(t == null ? void 0 : t.web);
2251
+ } catch {
2252
+ console.log("DataService not initialized, usage data unavailable.");
2253
+ }
2254
+ }
2255
+ //FIXME When to call that ??
2256
+ predestroy() {
2257
+ this._webBroker && (this._webBroker.destroy(), delete this._webBroker);
2258
+ }
2259
+ /** Send a web-user-level event to the data pipeline. */
2260
+ trackWebEvent(e) {
2261
+ this.notify.events().publish(LAYER_NAME.WEB_DATA, {
2262
+ name: EVENT_NAME.DATA_TRACKED,
2263
+ data: e
2264
+ });
2265
+ }
2266
+ addUserInfos(e) {
2267
+ return this.user && (e.userId = this.user.userId, e.structure = this.user.structureNames[0]), this.profile && (e.profil = this.profile[0]), e;
2268
+ }
2269
+ trackVideoSave(e, t, s, r, i, o, a) {
2270
+ const c = this.addUserInfos({
2271
+ "event-type": "VIDEO_SAVE",
2272
+ module: this.app || "video",
2273
+ video_id: e,
2274
+ browser: o,
2275
+ duration: Math.round(t),
2276
+ weight: s,
2277
+ source: r ? "CAPTURED" : "UPLOADED",
2278
+ url: i
2279
+ });
2280
+ a && (c.device_type = a), this.trackWebEvent(c);
2281
+ }
2282
+ trackVideoRead(e, t, s, r, i) {
2283
+ const o = this.addUserInfos({
2284
+ "event-type": "VIDEO_READ",
2285
+ module: "video",
2286
+ video_id: e,
2287
+ browser: r,
2288
+ source: t ? "CAPTURED" : "UPLOADED",
2289
+ url: s
2290
+ });
2291
+ this.app && (o["override-module"] = this.app), i && (o.device_type = i), this.trackWebEvent(o);
2292
+ }
2293
+ trackSpeechAndText(e) {
2294
+ const t = this.addUserInfos({
2295
+ "event-type": "SPEECH_AND_TEXT",
2296
+ function: e
2297
+ });
2298
+ this.app && (t.module = this.app), this.trackWebEvent(t);
2299
+ }
2300
+ trackAccessLibraryFromExplorer() {
2301
+ const e = this.addUserInfos({
2302
+ "event-type": "ACCESS_LIBRARY_FROM_EXPLORER"
2303
+ });
2304
+ this.app && (e.module = this.app), this.trackWebEvent(e);
2305
+ }
2306
+ }
2307
+ class DirectoryService {
2308
+ constructor(e) {
2309
+ this.odeServices = e;
2310
+ }
2311
+ get http() {
2312
+ return this.odeServices.http();
2313
+ }
2314
+ get cache() {
2315
+ return this.odeServices.cache();
2316
+ }
2317
+ getAvatarUrl(e, t, s = "100x100") {
2318
+ return t === "user" ? `/userbook/avatar/${e}?thumbnail=${s}` : "/assets/img/illustrations/group-avatar.svg";
2319
+ }
2320
+ getDirectoryUrl(e, t) {
2321
+ return t === "user" ? `/userbook/annuaire#/${e}` : `/userbook/annuaire#/group-view/${e}`;
2322
+ }
2323
+ async getBookMarks() {
2324
+ return (await this.cache.httpGetJson(
2325
+ "/directory/sharebookmark/all"
2326
+ )).map(({ id: t, name: s }) => ({
2327
+ id: t,
2328
+ displayName: s,
2329
+ notVisibleCount: 0,
2330
+ members: []
2331
+ // this api does not return members
2332
+ }));
2333
+ }
2334
+ async getBookMarkById(e) {
2335
+ const { groups: t, id: s, name: r, users: i, notVisibleCount: o } = await this.http.get(
2336
+ `/directory/sharebookmark/${e}`
2337
+ );
2338
+ return {
2339
+ id: s,
2340
+ displayName: r,
2341
+ notVisibleCount: o,
2342
+ groups: t.map(({ name: a, id: c, nbUsers: l }) => ({
2343
+ nbUsers: l,
2344
+ displayName: a,
2345
+ id: c
2346
+ })),
2347
+ users: i.map(({ displayName: a, id: c, profile: l }) => ({
2348
+ profile: l,
2349
+ displayName: a,
2350
+ // these info are missing from api
2351
+ firstName: "",
2352
+ lastName: "",
2353
+ login: "",
2354
+ id: c
2039
2355
  }))
2040
2356
  };
2041
2357
  }
@@ -2045,9 +2361,9 @@ class DirectoryService {
2045
2361
  users: r
2046
2362
  }) {
2047
2363
  this.cache.clearCache("/directory/sharebookmark/all");
2048
- const i = r.map((h) => typeof h == "string" ? h : h.id), o = s.map((h) => typeof h == "string" ? h : h.id), a = t.map(async (h) => {
2049
- if (typeof h == "string") {
2050
- const { displayName: y, groups: d, id: g, notVisibleCount: A, users: f } = await this.getBookMarkById(h), w = f.map((D) => D.id), F = d.map((D) => D.id);
2364
+ const i = r.map((p) => typeof p == "string" ? p : p.id), o = s.map((p) => typeof p == "string" ? p : p.id), a = t.map(async (p) => {
2365
+ if (typeof p == "string") {
2366
+ const { displayName: y, groups: d, id: g, notVisibleCount: A, users: f } = await this.getBookMarkById(p), w = f.map((D) => D.id), F = d.map((D) => D.id);
2051
2367
  return {
2052
2368
  displayName: y,
2053
2369
  id: g,
@@ -2055,590 +2371,106 @@ class DirectoryService {
2055
2371
  members: [...F, ...w]
2056
2372
  };
2057
2373
  } else
2058
- return Promise.resolve(h);
2059
- }), l = (await Promise.all(a)).map((h) => h.members).reduce((h, y) => [...h, ...y], []), p = {
2374
+ return Promise.resolve(p);
2375
+ }), l = (await Promise.all(a)).map((p) => p.members).reduce((p, y) => [...p, ...y], []), h = {
2060
2376
  name: e,
2061
2377
  members: [...i, ...o, ...l]
2062
2378
  }, { id: E } = await this.http.postJson(
2063
2379
  "/directory/sharebookmark",
2064
- p
2380
+ h
2065
2381
  );
2066
2382
  return {
2067
2383
  id: E,
2068
2384
  displayName: e,
2069
2385
  notVisibleCount: 0,
2070
- members: p.members
2386
+ members: h.members
2071
2387
  };
2072
2388
  }
2073
2389
  }
2074
- const loadedScripts = {};
2075
- class HttpService {
2076
- constructor(e, t) {
2077
- // Axios automatically manages the XSRF-TOKEN cookie and the X-XSRF-TOKEN HTTP header.
2078
- u(this, "axios");
2079
- u(this, "baseUrl");
2080
- u(this, "headers", {});
2081
- u(this, "_latestResponse");
2082
- this.context = e, this.axios = axios.create(t);
2083
- }
2084
- fixBaseUrl(e) {
2085
- return e.startsWith("http://") || e.startsWith("https://") ? e : this.baseUrl ? this.baseUrl.endsWith("/") || e.startsWith("/") ? `${this.baseUrl}${e}` : `${this.baseUrl}/${e}` : e;
2086
- }
2087
- useBaseUrl(e) {
2088
- return this.baseUrl = e, this;
2390
+ class EmbedderService {
2391
+ constructor(e) {
2392
+ this.context = e;
2089
2393
  }
2090
- useHeaders(e) {
2091
- return this.headers = e, this;
2394
+ get http() {
2395
+ return this.context.http();
2092
2396
  }
2093
- setCdn(e) {
2094
- e && XMLHttpRequest && !XMLHttpRequest.prototype.cdnUrl && (XMLHttpRequest.prototype.cdnUrl = e, XMLHttpRequest.prototype.baseOpen = XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.open = function() {
2095
- const t = arguments[1];
2096
- return t.startsWith("/infra/public") && (arguments[1] = e + t), /^\/([^\/]*)\/public/.test(t) && (arguments[1] = e + t), t.startsWith("/assets") && (arguments[1] = e + t), t == "/conf/public" && (arguments[1] = t), t.startsWith("http") && (arguments[1] = t), this.baseOpen.apply(this, arguments);
2097
- });
2397
+ /**
2398
+ * Returns the default list of video embedder
2399
+ * @returns the default list of video embedder
2400
+ */
2401
+ async getDefault() {
2402
+ return this.http.get("/infra/embed/default");
2098
2403
  }
2099
- // private toAxiosConfig(params?: IHttpParams): AxiosRequestConfig {
2100
- toAxiosConfig(e) {
2101
- if (e) {
2102
- const t = Object.assign({}, this.axios.defaults);
2103
- e.headers && (t.headers = Object.assign({}, this.axios.defaults.headers), Object.assign(t.headers, e.headers)), e.responseType && (t.responseType = e.responseType), e.queryParams && (t.params = Object.assign({}, e.queryParams));
2104
- const s = t.headers ?? {};
2105
- return t.headers = { ...s, ...this.headers }, t;
2106
- } else
2107
- return this.axios.defaults;
2404
+ /**
2405
+ * Returns the custom list of video embedder
2406
+ * @returns the custom list of video embedder
2407
+ */
2408
+ async getCustom() {
2409
+ return this.http.get("/infra/embed/custom");
2108
2410
  }
2109
- toCdnUrl(e) {
2110
- e = this.fixBaseUrl(e);
2111
- const t = this.context.conf().getCdnUrl() || "";
2112
- if (t.length > 0 && e !== "/conf/public") {
2113
- const s = "" + e;
2114
- (s.startsWith("/infra/public") || s.startsWith("/assets") || /^\/([^\/]*)\/public/.test(s)) && (e = t + s);
2115
- }
2116
- return e;
2411
+ /**
2412
+ * The provider matching with the URL
2413
+ * @param {Embedder[]} embedderList - The list of video providers to test with
2414
+ * @param {String} url - The URL for the video
2415
+ * @returns The provider matching with the URL or undefined
2416
+ */
2417
+ getProviderFromUrl(e, t) {
2418
+ for (const s of e)
2419
+ if (this.isUrlFromProvider(t, s))
2420
+ return s;
2117
2421
  }
2118
- mapAxiosError(e, t) {
2119
- e.response ? this._latestResponse = e.response : e.request ? this._latestResponse = {
2120
- status: 408,
2121
- statusText: ERROR_CODE.TIME_OUT
2122
- } : this._latestResponse = {
2123
- status: 500,
2124
- statusText: ERROR_CODE.UNKNOWN
2125
- };
2126
- const { status: s, statusText: r, headers: i, data: o } = this._latestResponse;
2127
- return t != null && t.disableNotifications || notify.events().publish(LAYER_NAME.TRANSPORT, {
2128
- name: EVENT_NAME.ERROR_OCCURED,
2129
- data: {
2130
- params: t,
2131
- response: { status: s, statusText: r, headers: i },
2132
- payload: o
2422
+ urlIsFromPattern(e, t) {
2423
+ const s = new RegExp("[^{}]+(?=(?:[^{}]*{[^}]*})*[^}]*$)", "g"), r = new RegExp("{[^}]*}", "g");
2424
+ let i = !0;
2425
+ const o = t.match(s) || [], a = [];
2426
+ return (t.match(r) || []).forEach((l, h) => {
2427
+ l.includes("ignore") || a.push(o[h]);
2428
+ }), a.forEach((l) => {
2429
+ if (!e.includes(l)) {
2430
+ i = !1;
2431
+ return;
2133
2432
  }
2134
- }), o;
2433
+ }), i;
2135
2434
  }
2136
- mapAxiosResponse(e, t) {
2137
- return this._latestResponse = e, e.data;
2435
+ /**
2436
+ * Check if a given URL correspond to one of the URL pattern of the provider
2437
+ * @param {String} url - The URL for the video
2438
+ * @param {Embedder} embedder - The video provider to test with
2439
+ * @returns boolean depending if a given URL correspond to one of the URL pattern of the provider
2440
+ */
2441
+ isUrlFromProvider(e, t) {
2442
+ typeof t.url == "string" && (t.url = [t.url]);
2443
+ for (const s of t.url)
2444
+ if (this.urlIsFromPattern(e, s))
2445
+ return !0;
2446
+ return !1;
2138
2447
  }
2139
- get latestResponse() {
2140
- return this._latestResponse;
2141
- }
2142
- isResponseError() {
2143
- return this.latestResponse.status < 200 || this.latestResponse.status >= 300;
2144
- }
2145
- async get(e, t) {
2146
- try {
2147
- const s = await this.axios.get(
2148
- this.toCdnUrl(e),
2149
- this.toAxiosConfig(t)
2150
- );
2151
- return this.mapAxiosResponse(s, t);
2152
- } catch (s) {
2153
- throw this.mapAxiosError(s, t);
2154
- }
2155
- }
2156
- async post(e, t, s) {
2157
- try {
2158
- const r = await this.axios.post(
2159
- this.fixBaseUrl(e),
2160
- t,
2161
- this.toAxiosConfig(s)
2162
- );
2163
- return this.mapAxiosResponse(r, s);
2164
- } catch (r) {
2165
- throw this.mapAxiosError(r, s);
2166
- }
2167
- }
2168
- async postFile(e, t, s) {
2169
- const r = this.toAxiosConfig(s);
2170
- r.headers && r.headers["Content-Type"] && delete r.headers["Content-Type"];
2171
- try {
2172
- const i = await this.axios.post(this.fixBaseUrl(e), t, {
2173
- ...r,
2174
- headers: {
2175
- "Content-Type": "multipart/form-data"
2176
- }
2177
- });
2178
- return this.mapAxiosResponse(i, s);
2179
- } catch (i) {
2180
- throw this.mapAxiosError(i, s);
2181
- }
2182
- }
2183
- async postJson(e, t, s) {
2184
- const r = this.toAxiosConfig();
2185
- r.headers && (r.headers["Content-Type"] = "application/json");
2186
- try {
2187
- const i = await this.axios.post(
2188
- this.fixBaseUrl(e),
2189
- t,
2190
- this.toAxiosConfig(s)
2191
- );
2192
- return this.mapAxiosResponse(i, s);
2193
- } catch (i) {
2194
- throw this.mapAxiosError(i, s);
2195
- }
2196
- }
2197
- async put(e, t, s) {
2198
- try {
2199
- const r = await this.axios.put(
2200
- this.fixBaseUrl(e),
2201
- t,
2202
- this.toAxiosConfig(s)
2203
- );
2204
- return this.mapAxiosResponse(r, s);
2205
- } catch (r) {
2206
- throw this.mapAxiosError(r, s);
2207
- }
2208
- }
2209
- async putFile(e, t, s) {
2210
- try {
2211
- const r = this.toAxiosConfig(s);
2212
- r.headers && r.headers["Content-Type"] && delete r.headers["Content-Type"];
2213
- const i = await this.axios.put(this.fixBaseUrl(e), t, {
2214
- ...r,
2215
- headers: {
2216
- "Content-Type": "multipart/form-data"
2217
- }
2218
- });
2219
- return this.mapAxiosResponse(i, s);
2220
- } catch (r) {
2221
- throw this.mapAxiosError(r, s);
2222
- }
2223
- }
2224
- async putJson(e, t, s) {
2225
- const r = this.toAxiosConfig(s);
2226
- r.headers && (r.headers["Content-Type"] = "application/json");
2227
- try {
2228
- const i = await this.axios.put(this.fixBaseUrl(e), t, r);
2229
- return this.mapAxiosResponse(i, s);
2230
- } catch (i) {
2231
- throw this.mapAxiosError(i, s);
2232
- }
2233
- }
2234
- async patch(e, t, s) {
2235
- try {
2236
- const r = await this.axios.patch(
2237
- this.fixBaseUrl(e),
2238
- t,
2239
- this.toAxiosConfig(s)
2240
- );
2241
- return this.mapAxiosResponse(r, s);
2242
- } catch (r) {
2243
- throw this.mapAxiosError(r, s);
2244
- }
2245
- }
2246
- async patchFile(e, t, s) {
2247
- try {
2248
- const r = this.toAxiosConfig(s);
2249
- r.headers && r.headers["Content-Type"] && delete r.headers["Content-Type"];
2250
- const i = await this.axios.patch(this.fixBaseUrl(e), t, {
2251
- ...r,
2252
- headers: {
2253
- "Content-Type": "multipart/form-data"
2254
- }
2255
- });
2256
- return this.mapAxiosResponse(i, s);
2257
- } catch (r) {
2258
- throw this.mapAxiosError(r, s);
2259
- }
2260
- }
2261
- async patchJson(e, t, s) {
2262
- const r = this.toAxiosConfig(s);
2263
- r.headers && (r.headers["Content-Type"] = "application/json");
2264
- try {
2265
- const i = await this.axios.patch(this.fixBaseUrl(e), t, r);
2266
- return this.mapAxiosResponse(i, s);
2267
- } catch (i) {
2268
- throw this.mapAxiosError(i, s);
2269
- }
2270
- }
2271
- async delete(e, t) {
2272
- try {
2273
- const s = await this.axios.delete(
2274
- this.fixBaseUrl(e),
2275
- this.toAxiosConfig(t)
2276
- );
2277
- return this.mapAxiosResponse(s, t);
2278
- } catch (s) {
2279
- throw this.mapAxiosError(s, t);
2280
- }
2281
- }
2282
- async deleteJson(e, t) {
2283
- try {
2284
- const s = await this.axios.delete(this.fixBaseUrl(e), {
2285
- data: t
2286
- });
2287
- return this.mapAxiosResponse(s);
2288
- } catch (s) {
2289
- throw this.mapAxiosError(s);
2290
- }
2291
- }
2292
- getScript(e, t, s) {
2293
- const r = s ?? "exports", i = this.toAxiosConfig(t);
2294
- return i.headers && (i.headers.Accept = "application/javascript"), this.axios.get(this.toCdnUrl(e), i).then((o) => this.mapAxiosResponse(o, t)).then((o) => {
2295
- try {
2296
- const a = `"use strict";var ${r.split(".")[0]}={};${o};return ${r};`;
2297
- return Function(a)();
2298
- } catch {
2299
- return o;
2300
- }
2301
- }).catch((o) => {
2302
- throw this.mapAxiosError(o, t), o;
2303
- });
2304
- }
2305
- loadScript(e, t) {
2306
- return loadedScripts[e] ? Promise.resolve() : this.getScript(e, t).then((s) => {
2307
- loadedScripts[e] = !0;
2308
- });
2309
- }
2310
- }
2311
- class RightService {
2312
- constructor(e) {
2313
- this.context = e;
2314
- }
2315
- get session() {
2316
- return this.context.session();
2317
- }
2318
- /**
2319
- * Parse right concat as "$TYPE:$ID:$RIGHT"
2320
- * $TYPE = user | group | creator
2321
- * $ID: id of the resource
2322
- * $RIGHT: read | contrib | manage
2323
- *
2324
- * @param right a concat right
2325
- * @returns Right parsed
2326
- */
2327
- parseResourceRight(e) {
2328
- const t = e.split(":");
2329
- if (t.length === 2) {
2330
- if (t[0] === "creator")
2331
- return {
2332
- id: t[1],
2333
- right: "creator",
2334
- type: "creator"
2335
- };
2336
- } else return t.length === 3 ? {
2337
- id: t[1],
2338
- right: t[2],
2339
- type: t[0]
2340
- } : void 0;
2341
- }
2342
- /**
2343
- * Parse an array of rights concat as "$TYPE:$ID:$RIGHT"
2344
- * $TYPE = user | group | creator
2345
- * $ID: id of the resource
2346
- * $RIGHT: read | contrib | manage
2347
- *
2348
- * @param rights a list of concat rights
2349
- * @returns Array of Right parsed
2350
- */
2351
- parseResourceRights(e) {
2352
- return e.map((s) => this.parseResourceRight(s)).filter((s) => s !== void 0);
2353
- }
2354
- /**
2355
- * Check wether a user has the expected right for a resource
2356
- * @param user the userId and groupId concerned by the check
2357
- * @param expect the expected right to check
2358
- * @param rights array of Right for the resource
2359
- * @returns true if has rights
2360
- */
2361
- hasResourceRight({ id: e, groupIds: t }, s, r) {
2362
- const i = r.map((o) => typeof o == "string" ? this.parseResourceRight(o) : o).filter((o) => o !== void 0);
2363
- for (const o of i) {
2364
- if (o.id === e && o.type === "creator")
2365
- return !0;
2366
- if (o.id === e && o.type === "user" && o.right === s)
2367
- return !0;
2368
- if (t.includes(o.id) && o.type === "group" && o.right === s)
2369
- return !0;
2370
- }
2371
- return !1;
2372
- }
2373
- /**
2374
- * Check wether the current user have resource right
2375
- * @param expect the expected right to check
2376
- * @param rights array of Right for the resource
2377
- * @returns true if has rights
2378
- */
2379
- async sessionHasResourceRight(e, t) {
2380
- try {
2381
- const s = await this.session.getUser();
2382
- return !!s && this.hasResourceRight(
2383
- { groupIds: s.groupsIds, id: s.userId },
2384
- e,
2385
- t
2386
- );
2387
- } catch (s) {
2388
- return console.error(`Unexpected error ${s} in sessionHasResourceRight()`), !1;
2389
- }
2390
- }
2391
- /**
2392
- * Check wether the current user have at least one of resource right expected
2393
- * @param expects array of expected right to check
2394
- * @param rights array of Right for the resource
2395
- * @returns true if has rights
2396
- */
2397
- async sessionHasAtLeastOneResourceRight(e, t) {
2398
- for (const s of e)
2399
- if (await this.sessionHasResourceRight(s, t))
2400
- return !0;
2401
- return !1;
2402
- }
2403
- /**
2404
- * Check wether the current user has resource right for each right list
2405
- * @param expect expected right to check
2406
- * @param rightsArray array of array of Right for multiple resources
2407
- * @returns true if has rights
2408
- */
2409
- async sessionHasResourceRightForEachList(e, t) {
2410
- let s = 0;
2411
- for (const r of t)
2412
- await this.sessionHasResourceRight(e, r) && s++;
2413
- return s === t.length;
2414
- }
2415
- /**
2416
- * Check wether the current user have at least one of resource right for each right list
2417
- * @param expects array of expected right to check
2418
- * @param rightsArray array of array of Right for multiple resources
2419
- * @returns true if has rights
2420
- */
2421
- async sessionHasAtLeastOneResourceRightForEachList(e, t) {
2422
- for (const s of e) {
2423
- let r = 0;
2424
- for (const i of t)
2425
- await this.sessionHasResourceRight(s, i) && r++;
2426
- if (r === t.length)
2427
- return !0;
2428
- }
2429
- return !1;
2430
- }
2431
- hasWorkflowRight(e, t) {
2432
- return t.findIndex((s) => s === e) !== -1;
2433
- }
2434
- /**
2435
- * @param expect a workflow right
2436
- * @returns true if current session has right on it
2437
- */
2438
- async sessionHasWorkflowRight(e) {
2439
- try {
2440
- const t = await this.session.getUser();
2441
- return !!t && this.hasWorkflowRight(
2442
- e,
2443
- t.authorizedActions.map(
2444
- (s) => s.name
2445
- )
2446
- );
2447
- } catch (t) {
2448
- return console.error(`Unexpected error ${t} in sessionHasWorkflowRight()`), !1;
2449
- }
2450
- }
2451
- /**
2452
- * @param expect a workflow right
2453
- * @returns a record with right as key and boolean as value if current session has right on it
2454
- */
2455
- async sessionHasWorkflowRights(e) {
2456
- const t = {};
2457
- try {
2458
- const s = await this.session.getUser();
2459
- for (const r of e)
2460
- t[r] = !!s && this.hasWorkflowRight(
2461
- r,
2462
- s.authorizedActions.map(
2463
- (i) => i.name
2464
- )
2465
- );
2466
- } catch (s) {
2467
- console.error(`Unexpected error ${s} in sessionHasWorkflowRights()`);
2468
- for (const r of e)
2469
- t[r] = !1;
2470
- }
2471
- return t;
2472
- }
2473
- }
2474
- class SessionService {
2475
- constructor(e) {
2476
- this.context = e;
2477
- }
2478
- get http() {
2479
- return this.context.http();
2480
- }
2481
- get cache() {
2482
- return this.context.cache();
2483
- }
2484
- get conf() {
2485
- return this.context.conf();
2486
- }
2487
- /**
2488
- * Callback to call when user logout
2489
- */
2490
- onLogout() {
2491
- this.cache.clearCache();
2492
- }
2493
- /**
2494
- * Callback to call when session change
2495
- */
2496
- onRefreshSession() {
2497
- this.cache.clearCache();
2498
- }
2499
- async getSession() {
2500
- const e = await this.getUser(), [
2501
- t,
2502
- s,
2503
- r,
2504
- i,
2505
- o
2506
- ] = await Promise.all([
2507
- this.getCurrentLanguage(e),
2508
- this.latestQuotaAndUsage(e),
2509
- this.loadDescription(e),
2510
- this.getUserProfile(),
2511
- this.getBookmarks(e)
2512
- ]);
2513
- return {
2514
- user: e,
2515
- quotaAndUsage: s,
2516
- currentLanguage: t,
2517
- userDescription: r,
2518
- userProfile: i,
2519
- bookmarkedApps: o
2520
- };
2521
- }
2522
- login(e, t, s, r) {
2523
- const i = new FormData();
2524
- return i.append("email", e), i.append("password", t), typeof s < "u" && i.append("rememberMe", "" + s), typeof r < "u" && i.append("secureLocation", "" + r), this.http.post("/auth/login", i, {
2525
- headers: { "content-type": "application/x-www-form-urlencoded" }
2526
- }).finally(() => {
2527
- switch (this.http.latestResponse.status) {
2528
- case 200:
2529
- throw ERROR_CODE.MALFORMED_DATA;
2530
- }
2531
- });
2532
- }
2533
- async logout() {
2534
- const e = await this.conf.getLogoutCallback();
2535
- return this.http.get("/auth/logout?callback=" + e).finally(() => {
2536
- });
2537
- }
2538
- async latestQuotaAndUsage(e) {
2539
- const t = { quota: 0, storage: 0 };
2540
- if (!e) return t;
2541
- try {
2542
- return await this.http.get(
2543
- `/workspace/quota/user/${e == null ? void 0 : e.userId}`
2544
- );
2545
- } catch (s) {
2546
- return console.error(s), t;
2547
- }
2548
- }
2549
- async getCurrentLanguage(e) {
2550
- const t = (e == null ? void 0 : e.sessionMetadata) && (e == null ? void 0 : e.sessionMetadata.userId);
2551
- try {
2552
- let s;
2553
- return t ? s = await this.loadUserLanguage() : s = await this.loadDefaultLanguage(), s;
2554
- } catch (s) {
2555
- console.error(s);
2556
- }
2557
- }
2558
- async loadUserLanguage() {
2559
- try {
2560
- const e = await this.http.get(
2561
- "/userbook/preference/language"
2562
- );
2563
- return JSON.parse(e.preference)["default-domain"];
2564
- } catch {
2565
- return await this.loadDefaultLanguage();
2566
- }
2567
- }
2568
- async loadDefaultLanguage() {
2569
- return (await this.cache.httpGetJson(
2570
- "/locale"
2571
- )).locale;
2572
- }
2573
- async getUser() {
2574
- const { response: e, value: t } = await this.cache.httpGet(
2575
- "/auth/oauth2/userinfo"
2576
- );
2577
- if (!(e.status < 200 || e.status >= 300) && typeof t == "object")
2578
- return t;
2579
- throw ERROR_CODE.NOT_LOGGED_IN;
2580
- }
2581
- hasWorkflow({
2582
- workflowName: e,
2583
- user: t
2584
- }) {
2585
- return e === void 0 || (t == null ? void 0 : t.authorizedActions.findIndex((s) => s.name === e)) !== -1;
2586
- }
2587
- async loadDescription(e) {
2588
- if (!e) return {};
2589
- try {
2590
- const [t, s] = await Promise.all([
2591
- // FIXME The full user's description should be obtainable from a single endpoint in the backend.
2592
- this.getUserProfile({
2593
- options: { requestName: "refreshAvatar" }
2594
- }),
2595
- this.http.get("/directory/userbook/" + (e == null ? void 0 : e.userId))
2596
- ]);
2597
- return { ...s, profiles: t };
2598
- } catch (t) {
2599
- return console.error(t), {};
2600
- }
2601
- }
2602
- async getBookmarks(e) {
2603
- if (!e) return [];
2604
- const t = await this.http.get("/userbook/preference/apps");
2605
- t.preference || (t.preference = null);
2606
- const s = JSON.parse(t.preference);
2607
- let r;
2608
- r = s, r || (r = {
2609
- bookmarks: [],
2610
- applications: []
2611
- });
2612
- const i = [];
2613
- return r.bookmarks.forEach((o, a) => {
2614
- const c = ((e == null ? void 0 : e.apps) || []).find(
2615
- (l) => l.name === o
2616
- );
2617
- if (c) {
2618
- const l = Object.assign({}, c);
2619
- i.push(l);
2620
- }
2621
- }), i;
2622
- }
2623
- async getUserProfile(e = {}) {
2624
- var c, l;
2625
- const { options: t = {}, params: s = {} } = e, r = new URLSearchParams(s).toString(), i = `/userbook/api/person${r ? `?${r}` : ""}`, { response: o, value: a } = await this.cache.httpGet(i, t);
2626
- return o.status < 200 || o.status >= 300 || typeof a == "string" ? ["Guest"] : ((l = (c = a == null ? void 0 : a.result) == null ? void 0 : c[0]) == null ? void 0 : l.type) || ["Guest"];
2627
- }
2628
- async isAdml() {
2629
- const e = await this.getUser();
2630
- return (e == null ? void 0 : e.functions.ADMIN_LOCAL) !== void 0;
2631
- }
2632
- /**
2633
- * Get details of an application if the user can access it.
2634
- * @return undefined if no access, or app not found
2635
- */
2636
- async getWebApp(e) {
2637
- const t = await this.getUser();
2638
- return t == null ? void 0 : t.apps.find((s) => {
2639
- var r;
2640
- return s != null && s.prefix ? (s == null ? void 0 : s.prefix.replace("/", "")) === e || !1 : s != null && s.address && ((r = s.address) == null ? void 0 : r.split("/")[1]) === e || !1;
2641
- });
2448
+ /**
2449
+ * Get embed code to display the video for an URL and a provider
2450
+ * @param {Embedder} embedder - The video provider for the URL
2451
+ * @param {String} url - The URL for the video
2452
+ * @returns embed code to display the video for an URL and a provider
2453
+ */
2454
+ getEmbedCodeForProvider(e, t) {
2455
+ for (const s of e.url)
2456
+ if (this.urlIsFromPattern(t, s)) {
2457
+ const r = new RegExp("{[a-zA-Z0-9_.]+}", "g"), i = s.match(r) || [];
2458
+ let o = e.embed;
2459
+ for (const a of i) {
2460
+ let c = s.split(a)[0];
2461
+ const l = c.split("}");
2462
+ l.length > 1 && (c = l[l.length - 1]);
2463
+ let h = t.split(c)[1];
2464
+ if (!h)
2465
+ continue;
2466
+ const E = s.split(a)[1].split("{")[0];
2467
+ E && (h = h.split(E)[0]);
2468
+ const p = new RegExp("\\" + a.replace(/}/, "\\}"), "g");
2469
+ o = o.replace(p, h);
2470
+ }
2471
+ return o;
2472
+ }
2473
+ return "";
2642
2474
  }
2643
2475
  }
2644
2476
  const bundle = {}, promises = {}, defaultDiacriticsRemovalMap = [
@@ -2923,1504 +2755,1771 @@ class IdiomService {
2923
2755
  return e;
2924
2756
  }
2925
2757
  }
2926
- class StringUtils {
2927
- static removeAccents(e) {
2928
- for (let t = 0; t < defaultDiacriticsRemovalMap.length; t++)
2929
- e = e.replace(
2930
- defaultDiacriticsRemovalMap[t].letters,
2931
- defaultDiacriticsRemovalMap[t].base
2932
- );
2933
- return e;
2758
+ function toNextcloudDocument(n, e) {
2759
+ return {
2760
+ path: decodeURIComponent(n.path.split(e).pop() ?? n.path),
2761
+ name: decodeURIComponent(n.displayname),
2762
+ ownerDisplayName: n.ownerDisplayName,
2763
+ contentType: n.contentType,
2764
+ size: n.size,
2765
+ favorite: n.favorite,
2766
+ etag: n.etag,
2767
+ fileId: n.fileId,
2768
+ isFolder: n.isFolder,
2769
+ lastModified: n.lastModified
2770
+ };
2771
+ }
2772
+ class NextcloudService {
2773
+ constructor(e) {
2774
+ this.context = e;
2775
+ }
2776
+ get http() {
2777
+ return this.context.http();
2778
+ }
2779
+ /**
2780
+ * List a user's Nextcloud documents and folders at a given path.
2781
+ * @param userId - the id of the user whose files are listed.
2782
+ * @param path - path to list, relative to the user's Nextcloud root; root when omitted.
2783
+ */
2784
+ async listDocuments(e, t) {
2785
+ return (await this.http.get(
2786
+ `/nextcloud/files/user/${e}`,
2787
+ { queryParams: t ? { path: t } : void 0 }
2788
+ )).data.map((r) => toNextcloudDocument(r, e));
2789
+ }
2790
+ /**
2791
+ * Copy Nextcloud documents into the entcore workspace.
2792
+ * @param userId - the id of the user whose files are copied.
2793
+ * @param paths - paths of the documents to copy, relative to the user's Nextcloud root.
2794
+ * @param parentId - the workspace folder to copy into; user's root when omitted.
2795
+ */
2796
+ async copyDocumentToWorkspace(e, t, s) {
2797
+ const r = t.map((o) => `path=${encodeURIComponent(o)}`).join("&");
2798
+ return (await this.http.put(
2799
+ `/nextcloud/files/user/${e}/copy/workspace?${r}`,
2800
+ void 0,
2801
+ { queryParams: s ? { parentId: s } : void 0 }
2802
+ )).data.filter((o) => !!(o != null && o._id));
2803
+ }
2804
+ /**
2805
+ * Build the URL to download/preview a Nextcloud document.
2806
+ * There is no dedicated thumbnail endpoint on the backend, so this is also
2807
+ * used as an image preview source for image documents.
2808
+ * @param userId - the id of the user who owns the file.
2809
+ * @param doc - the document to build the URL for.
2810
+ */
2811
+ getFileUrl(e, t) {
2812
+ return `/nextcloud/files/user/${e}/file/${encodeURIComponent(
2813
+ t.name
2814
+ )}/download?path=${encodeURIComponent(
2815
+ t.path
2816
+ )}&contentType=${encodeURIComponent(t.contentType ?? "")}&isFolder=${t.isFolder}`;
2934
2817
  }
2935
2818
  }
2936
- class ShareService {
2819
+ class AbstractBehaviourService {
2937
2820
  //
2938
2821
  // IMPLEMENTATION
2939
2822
  //
2940
2823
  constructor(e) {
2941
- this.context = e;
2824
+ //-----------------
2825
+ //--- Utilities ---
2826
+ //-----------------
2827
+ u(this, "_cache");
2828
+ this.context = e, this._cache = new CacheService(this.context);
2942
2829
  }
2943
- get directory() {
2944
- return this.context.directory();
2830
+ getApplication() {
2831
+ return this.APP;
2945
2832
  }
2946
- get http() {
2947
- return this.context.http();
2833
+ getResourceType() {
2834
+ return this.RESOURCE;
2948
2835
  }
2949
- get cache() {
2950
- return this.context.cache();
2836
+ httpGet(e, t) {
2837
+ return this._cache.httpGetJson(e, t);
2951
2838
  }
2952
- getSearchUrl(e, t, s, r) {
2953
- if (!r)
2954
- return `/${e}/share/json/${t}?search=${s}`;
2955
- if (r.includes("?search=")) {
2956
- const [i] = r.split("?search=");
2957
- return `${i}?search=${s}`;
2958
- } else return r.includes("?") ? `${r}&search=${s}` : `${r}?search=${s}`;
2839
+ /* Utility to map data between linker model and search model. */
2840
+ dataToResource({
2841
+ modified: e,
2842
+ ...t
2843
+ }) {
2844
+ const s = typeof e == "string" ? e : e != null && e.$date ? "" + e.$date : "";
2845
+ return {
2846
+ application: this.RESOURCE,
2847
+ name: t.title,
2848
+ creatorId: t.owner,
2849
+ creatorName: t.ownerName,
2850
+ thumbnail: t.icon,
2851
+ assetId: t._id,
2852
+ modifiedAt: s,
2853
+ shared: t.shared,
2854
+ path: t.path
2855
+ };
2959
2856
  }
2960
- async searchShareSubjects(e, t, s, r) {
2961
- const i = StringUtils.removeAccents(s).toLowerCase(), o = this.getSearchUrl(
2962
- e,
2963
- t,
2964
- s,
2965
- r
2966
- ), a = await this.cache.httpGetJson(o), c = a.users.visibles.filter(({ username: h, firstName: y, lastName: d, login: g }) => {
2967
- const A = StringUtils.removeAccents(
2968
- d || ""
2969
- ).toLowerCase(), f = StringUtils.removeAccents(
2970
- y || ""
2971
- ).toLowerCase(), w = StringUtils.removeAccents(
2972
- h || ""
2973
- ).toLowerCase(), F = StringUtils.removeAccents(g || "").toLowerCase();
2974
- return w.includes(i) || f.includes(i) || A.includes(i) || F.includes(i);
2975
- }).map((h) => ({
2976
- avatarUrl: this.directory.getAvatarUrl(h.id, "user"),
2977
- directoryUrl: this.directory.getDirectoryUrl(h.id, "user"),
2978
- displayName: h.username,
2979
- id: h.id,
2980
- profile: h.profile,
2981
- type: "user"
2982
- })), l = a.groups.visibles.filter(({ name: h }) => StringUtils.removeAccents(h || "").toLowerCase().includes(i)).map((h) => ({
2983
- avatarUrl: this.directory.getAvatarUrl(h.id, "group"),
2984
- directoryUrl: this.directory.getDirectoryUrl(h.id, "group"),
2985
- displayName: h.name,
2986
- id: h.id,
2987
- type: "group",
2988
- structureName: h.structureName
2989
- }));
2990
- return [...(await this.directory.getBookMarks()).filter(({ displayName: h }) => StringUtils.removeAccents(
2991
- h || ""
2992
- ).toLowerCase().includes(i)).map((h) => ({
2993
- avatarUrl: "",
2994
- directoryUrl: "",
2995
- profile: "",
2996
- displayName: h.displayName,
2997
- id: h.id,
2998
- type: "sharebookmark"
2999
- })), ...c, ...l];
2857
+ }
2858
+ class ActualitesBehaviour extends AbstractBehaviourService {
2859
+ constructor() {
2860
+ super(...arguments);
2861
+ u(this, "APP", "actualites");
2862
+ u(this, "RESOURCE", "actualites");
3000
2863
  }
3001
- async getShareMapping(e, t) {
3002
- const s = await this.cache.httpGetJson(
3003
- t || `/${e}/rights/sharing`
2864
+ async loadResources() {
2865
+ const [t, s] = await Promise.all([
2866
+ this.httpGet("/actualites/api/v1/infos/linker"),
2867
+ this.httpGet("/actualites/api/v1/threads")
2868
+ ]), r = s.reduce(
2869
+ (i, o) => i.set(o.id, o),
2870
+ /* @__PURE__ */ new Map()
3004
2871
  );
3005
- for (const r of Object.keys(s))
3006
- if (r.includes(".")) {
3007
- const i = r.split(".")[1], o = s[r];
3008
- delete s[r], s[i] = o;
3009
- }
3010
- return s;
3011
- }
3012
- getActionsAvailableFor({ id: e, type: t }, s, r) {
3013
- const o = (t === "user" ? s.users.checked[e] : s.groups.checked[e]) || [], a = Object.keys(r), c = [];
3014
- for (const l of a)
3015
- r[l].filter(
3016
- (h) => o.includes(h)
3017
- ).length > 0 && c.push(l);
3018
- return c;
3019
- }
3020
- async getRightsForResource(e, t, s) {
3021
- const r = await this.directory.getBookMarks(), i = this.getSearchUrl(
3022
- e,
3023
- t,
3024
- "",
3025
- s == null ? void 0 : s.getResourceRights
3026
- ), o = await this.cache.httpGetJson(
3027
- i
3028
- ), a = await this.getShareMapping(
3029
- e,
3030
- s == null ? void 0 : s.getShareMapping
3031
- ), c = await this.cache.httpGetJson(
3032
- "/infra/public/json/sharing-rights.json"
3033
- ), l = Object.keys(o.users.checked).map((d) => o.users.visibles.find(
3034
- (A) => A.id === d
3035
- )).filter((d) => d !== void 0).map((d) => {
3036
- const g = this.getActionsAvailableFor(
3037
- { id: d.id, type: "user" },
3038
- o,
3039
- a
3040
- );
3041
- return {
3042
- id: d.id,
3043
- type: "user",
3044
- displayName: d.username,
3045
- profile: d.profile,
3046
- avatarUrl: this.directory.getAvatarUrl(d.id, "user"),
3047
- directoryUrl: this.directory.getDirectoryUrl(d.id, "user"),
3048
- actions: g.map((f) => {
3049
- const w = c[f];
3050
- return {
3051
- displayName: f,
3052
- id: f,
3053
- priority: w.priority
3054
- };
3055
- })
3056
- };
3057
- }).sort((d, g) => (d.displayName || "").localeCompare(g.displayName)), p = Object.keys(o.groups.checked).map((d) => o.groups.visibles.find(
3058
- (A) => A.id === d
3059
- )).filter((d) => d !== void 0).map((d) => {
3060
- const g = this.getActionsAvailableFor(
3061
- { id: d.id, type: "group" },
3062
- o,
3063
- a
3064
- );
3065
- return {
3066
- id: d.id,
3067
- type: "group",
3068
- displayName: d.name,
3069
- profile: void 0,
3070
- avatarUrl: this.directory.getAvatarUrl(d.id, "group"),
3071
- directoryUrl: this.directory.getDirectoryUrl(d.id, "group"),
3072
- actions: g.map((f) => {
3073
- const w = c[f];
3074
- return {
3075
- displayName: f,
3076
- id: f,
3077
- priority: w.priority
3078
- };
3079
- })
3080
- };
3081
- }).sort((d, g) => (d.displayName || "").localeCompare(g.displayName)), E = [...l, ...p], h = o.groups.visibles.map(
3082
- ({ groupDisplayName: d, id: g, name: A, labels: f }) => ({
3083
- labels: f,
3084
- displayName: d || A,
3085
- id: g
3086
- })
3087
- ), y = o.users.visibles.map(
3088
- ({ id: d, profile: g, username: A, firstName: f, lastName: w, login: F }) => ({
3089
- displayName: A,
3090
- firstName: f,
3091
- lastName: w,
3092
- login: F,
3093
- profile: g,
3094
- id: d
2872
+ return t.map((i) => {
2873
+ var a;
2874
+ let o;
2875
+ return i.threadIcon ? o = i.threadIcon + "?thumbnail=48x48" : o = "/img/icons/glyphicons_036_file.png", this.dataToResource({
2876
+ title: i.title + " [" + ((a = r.get(i.threadId)) == null ? void 0 : a.title) + "]",
2877
+ ownerName: i.owner.displayName,
2878
+ owner: i.owner.id,
2879
+ icon: o,
2880
+ path: "/actualites/threads/" + i.threadId + "?info=" + i.id,
2881
+ _id: `${i.threadId}#${i.id}`,
2882
+ shared: !!(i.shared && i.shared.length >= 0),
2883
+ modified: i.modified
2884
+ });
2885
+ });
2886
+ }
2887
+ }
2888
+ const hexToDataUrl = (n, e = 1, t = 1) => {
2889
+ const s = document.createElement("canvas");
2890
+ s.width = e, s.height = t;
2891
+ const r = s.getContext("2d");
2892
+ return r ? (r.fillStyle = n, r.fillRect(0, 0, e, t), s.toDataURL("image/png")) : "";
2893
+ };
2894
+ class AppointmentsBehaviour extends AbstractBehaviourService {
2895
+ constructor() {
2896
+ super(...arguments);
2897
+ u(this, "APP", "appointments");
2898
+ u(this, "RESOURCE", "appointments");
2899
+ }
2900
+ async loadResources() {
2901
+ return (await this.httpGet("/appointments/grids/linker")).map((s) => this.dataToResource({
2902
+ _id: s.id.toString(),
2903
+ icon: hexToDataUrl(s.color, 100, 100),
2904
+ title: s.name,
2905
+ ownerName: s.ownerName,
2906
+ owner: s.ownerId,
2907
+ path: `${window.location.origin}/appointments#?gridId=${s.id}`,
2908
+ shared: !1,
2909
+ modified: s.updatingDate
2910
+ }));
2911
+ }
2912
+ }
2913
+ class BlogBehaviour extends AbstractBehaviourService {
2914
+ constructor() {
2915
+ super(...arguments);
2916
+ u(this, "APP", "blog");
2917
+ u(this, "RESOURCE", "blog");
2918
+ }
2919
+ loadResources() {
2920
+ return new Promise(async (t, s) => {
2921
+ try {
2922
+ const r = await this.httpGet("/blog/linker"), i = [];
2923
+ r.forEach((o) => {
2924
+ o.thumbnail ? o.thumbnail = o.thumbnail + "?thumbnail=48x48" : o.thumbnail = "/img/illustrations/blog.svg";
2925
+ const a = o.fetchPosts.map((c) => this.dataToResource({
2926
+ owner: o.author.userId,
2927
+ ownerName: o.author.username,
2928
+ title: c.title + " [" + o.title + "]",
2929
+ _id: `${o._id}#${c._id}`,
2930
+ icon: o.thumbnail,
2931
+ path: `/blog/id/${o._id}/post/${c._id}`,
2932
+ shared: !!(o.shared && o.shared.length >= 0),
2933
+ modified: o.modified
2934
+ }));
2935
+ i.push(...a);
2936
+ }), t(i);
2937
+ } catch (r) {
2938
+ s(r);
2939
+ }
2940
+ });
2941
+ }
2942
+ }
2943
+ class CollaborativewallBehaviour extends AbstractBehaviourService {
2944
+ constructor() {
2945
+ super(...arguments);
2946
+ u(this, "APP", "collaborativewall");
2947
+ u(this, "RESOURCE", "collaborativewall");
2948
+ }
2949
+ async loadResources() {
2950
+ return (await this.httpGet(
2951
+ "/collaborativewall/list/all"
2952
+ )).map(
2953
+ (s) => this.dataToResource({
2954
+ title: s.name,
2955
+ ownerName: s.owner.displayName,
2956
+ owner: s.owner.userId,
2957
+ icon: s.icon ? s.icon : "/img/illustrations/collaborative-wall-default.png",
2958
+ path: "/collaborativewall#/view/" + s._id,
2959
+ _id: s._id,
2960
+ shared: !!(s.shared && s.shared.length >= 0),
2961
+ modified: s.modified
3095
2962
  })
3096
2963
  );
3097
- return {
3098
- rights: E,
3099
- visibleBookmarks: r,
3100
- visibleGroups: h,
3101
- visibleUsers: y
3102
- };
3103
2964
  }
3104
- async getPutSharePayload(e, t, s) {
3105
- const r = {
3106
- users: {},
3107
- groups: {},
3108
- bookmarks: {}
3109
- }, i = await this.getShareMapping(e, s);
3110
- for (const o of t) {
3111
- const a = o.actions.map((l) => i[l.id]).reduce((l, p) => Array.isArray(p) ? [...l, ...p] : l, []), c = [...new Set(a)];
3112
- c.length > 0 && (o.type === "user" ? r.users[o.id] = c : o.type === "group" ? r.groups[o.id] = c : r.bookmarks[o.id] = c);
3113
- }
3114
- return r;
2965
+ }
2966
+ class CommunityBehaviour extends AbstractBehaviourService {
2967
+ constructor() {
2968
+ super(...arguments);
2969
+ u(this, "APP", "community");
2970
+ u(this, "RESOURCE", "community");
3115
2971
  }
3116
- async saveRights(e, t, s, r) {
3117
- const i = await this.getPutSharePayload(
3118
- e,
3119
- s,
3120
- r == null ? void 0 : r.getShareMapping
3121
- ), o = (r == null ? void 0 : r.saveResourceRights) || `/${e}/share/resource/${t}`, a = this.getSearchUrl(
3122
- e,
3123
- t,
3124
- "",
3125
- r == null ? void 0 : r.getResourceRights
3126
- );
3127
- return this.cache.clearCache(a), await this.http.putJson(o, i);
2972
+ async loadResources() {
2973
+ return (await this.httpGet(
2974
+ "/community/listallpages"
2975
+ )).map((s) => {
2976
+ let r;
2977
+ return typeof s.thumbnail > "u" || s.thumbnail === "" ? r = "/img/icons/glyphicons_036_file.png" : r = s.thumbnail + "?thumbnail=48x48", this.dataToResource({
2978
+ title: s.name,
2979
+ icon: r,
2980
+ path: "/community#/view/" + s.id,
2981
+ _id: s.id,
2982
+ owner: "",
2983
+ ownerName: "",
2984
+ shared: !!(s.shared && s.shared.length >= 0),
2985
+ modified: s.name
2986
+ // FIXME date ?
2987
+ });
2988
+ });
3128
2989
  }
3129
- async getActionsForApp(e, t) {
3130
- const s = await this.cache.httpGetJson(
3131
- "/infra/public/json/sharing-rights.json"
3132
- ), r = await this.getShareMapping(e, t);
3133
- return Object.keys(s).map((o) => {
3134
- const a = s[o];
3135
- return {
3136
- displayName: o,
3137
- id: o,
3138
- priority: a.priority,
3139
- requires: a.requires
3140
- };
3141
- }).filter((o) => {
3142
- var a;
3143
- return ((a = r[o.id]) == null ? void 0 : a.length) > 0;
3144
- }).sort((o, a) => o.priority - a.priority);
2990
+ }
2991
+ class ExercizerBehaviour extends AbstractBehaviourService {
2992
+ constructor() {
2993
+ super(...arguments);
2994
+ u(this, "APP", "exercizer");
2995
+ u(this, "RESOURCE", "exercizer");
2996
+ }
2997
+ async loadResources() {
2998
+ return (await this.httpGet(
2999
+ "/exercizer/subjects-scheduled"
3000
+ )).map((s) => {
3001
+ const r = s.picture ? s.picture + "?thumbnail=48x48" : "/img/illustrations/exercizer.svg";
3002
+ let i, o = !1;
3003
+ const a = JSON.parse(s.scheduled_at);
3004
+ return a.groupList.length > 0 ? (o = !0, i = a.groupList[0].name) : a.userList.length > 0 ? (o = !0, i = a.userList[0].name) : i = "", a.groupList.length + a.userList.length > 1 && (i += "..."), this.dataToResource({
3005
+ title: s.title,
3006
+ owner: s.owner,
3007
+ ownerName: i,
3008
+ icon: r,
3009
+ path: "/exercizer#/linker/" + s.id,
3010
+ _id: "" + s.id,
3011
+ shared: o,
3012
+ modified: s.modified
3013
+ });
3014
+ });
3145
3015
  }
3146
3016
  }
3147
- const defaultMappers = {
3148
- csv: function({ type: n, extension: e }) {
3149
- return MimeTypeUtils.INSTANCE.isCsvLike(n, e);
3150
- },
3151
- doc: function({ type: n, extension: e }) {
3152
- return MimeTypeUtils.INSTANCE.isWordLike(n, e) ? !0 : n.indexOf("document") !== -1 && n.indexOf("wordprocessing") !== -1;
3153
- },
3154
- xls: function({ type: n, extension: e }) {
3155
- return MimeTypeUtils.INSTANCE.isExcelLike(n, e) ? !0 : n.indexOf("document") !== -1 && n.indexOf("spreadsheet") !== -1 || n.indexOf("ms-excel") !== -1;
3156
- },
3157
- img: function({ type: n }) {
3158
- return n.indexOf("image") !== -1;
3159
- },
3160
- pdf: function({ type: n }) {
3161
- return n.indexOf("pdf") !== -1 || n === "application/x-download";
3162
- },
3163
- ppt: function({ type: n, extension: e }) {
3164
- return MimeTypeUtils.INSTANCE.isPowerpointLike(n, e) ? !0 : n.indexOf("document") !== -1 && n.indexOf("presentation") !== -1 || n.indexOf("powerpoint") !== -1;
3165
- },
3166
- txt: function({ type: n, extension: e }) {
3167
- return MimeTypeUtils.INSTANCE.isTxtLike(n, e);
3168
- },
3169
- md: function({ type: n, extension: e }) {
3170
- return MimeTypeUtils.INSTANCE.isMdLike(n, e);
3171
- },
3172
- video: function({ type: n }) {
3173
- return n.indexOf("video") !== -1;
3174
- },
3175
- audio: function({ type: n }) {
3176
- return n.indexOf("audio") !== -1;
3177
- },
3178
- zip: function({ type: n }) {
3179
- return n.indexOf("zip") !== -1 || n.indexOf("rar") !== -1 || n.indexOf("tar") !== -1 || n.indexOf("7z") !== -1;
3017
+ class FormulaireBehaviour extends AbstractBehaviourService {
3018
+ constructor() {
3019
+ super(...arguments);
3020
+ u(this, "APP", "formulaire");
3021
+ u(this, "RESOURCE", "formulaire");
3180
3022
  }
3181
- }, v = class v {
3182
- /* Similar role notion as in infra-front > workspace > Model.ts */
3183
- static getRole(e) {
3184
- var t, s;
3185
- return v.role(
3186
- (t = e.metadata) == null ? void 0 : t["content-type"],
3187
- !1,
3188
- (s = e.metadata) == null ? void 0 : s.extension
3189
- );
3023
+ async loadResources() {
3024
+ return (await this.httpGet(
3025
+ "/formulaire/forms/linker"
3026
+ )).map((s) => (s.picture || (s.picture = "/formulaire/public/img/logo.svg"), this.dataToResource({
3027
+ _id: "" + s.id,
3028
+ icon: s.picture,
3029
+ title: s.title,
3030
+ ownerName: s.owner_name,
3031
+ owner: s.owner_id,
3032
+ path: s.is_public ? `${window.location.origin}/formulaire-public#/form/${s.public_key}` : `${window.location.origin}/formulaire#/form/${s.id}/${s.rgpd ? "rgpd" : "new"}`,
3033
+ shared: !!(s.shared && s.shared.length >= 0),
3034
+ modified: "" + s.date_modification
3035
+ })));
3190
3036
  }
3191
- /* Similar role notion as in infra-front > workspace > Model.ts */
3192
- static role(e, t = !1, s) {
3193
- if (s && (s = s.trim()), !e) return "unknown";
3194
- this.roleMappers || console.warn("[DocumentHelper.role] should not have empty roles", this);
3195
- const r = { type: e, previewRole: t, extension: s };
3196
- for (const i of this.roleMappers) {
3197
- const o = i(r);
3198
- if (o)
3199
- return o;
3200
- }
3201
- return "unknown";
3037
+ }
3038
+ class ForumBehaviour extends AbstractBehaviourService {
3039
+ constructor() {
3040
+ super(...arguments);
3041
+ u(this, "APP", "forum");
3042
+ u(this, "RESOURCE", "forum");
3043
+ }
3044
+ async loadResources() {
3045
+ return (await this.httpGet("/forum/categories")).map(
3046
+ (s) => this.dataToResource({
3047
+ _id: s._id,
3048
+ title: s.name,
3049
+ icon: s.icon || "/img/illustrations/forum.svg",
3050
+ path: "/forum#/view/" + s._id,
3051
+ ownerName: s.owner.displayName,
3052
+ owner: s.owner.userId,
3053
+ shared: !!(s.shared && s.shared.length >= 0),
3054
+ modified: s.modified
3055
+ })
3056
+ );
3202
3057
  }
3203
- };
3204
- // FIXME add edumedia support
3205
- u(v, "roleMappers", [
3206
- (e) => Object.keys(defaultMappers).find((s) => defaultMappers[s](e))
3207
- ]);
3208
- let DocumentHelper = v;
3209
- class WorkspaceService {
3210
- constructor(e) {
3211
- this.context = e;
3058
+ }
3059
+ class HomeworksBehaviour extends AbstractBehaviourService {
3060
+ constructor() {
3061
+ super(...arguments);
3062
+ u(this, "APP", "homeworks");
3063
+ u(this, "RESOURCE", "homeworks");
3212
3064
  }
3213
- get http() {
3214
- return this.context.http();
3065
+ async loadResources() {
3066
+ return (await this.httpGet("/homeworks/list")).filter((t) => t.owner && t.trashed === 0).map((t) => this.dataToResource({
3067
+ title: t.title,
3068
+ ownerName: t.owner.displayName,
3069
+ owner: t.owner.userId,
3070
+ icon: t.thumbnail || "/img/illustrations/homeworks.svg",
3071
+ path: "/homeworks#/view-homeworks/" + t._id,
3072
+ _id: "" + t._id,
3073
+ shared: typeof t.shared < "u",
3074
+ modified: t.modified
3075
+ }));
3215
3076
  }
3216
- extractMetadata(e) {
3217
- const t = e.name || "", s = t.split("."), r = e.type || "application/octet-stream", i = s.length > 1 ? s[s.length - 1] : "", o = {
3218
- "content-type": r,
3219
- filename: t,
3220
- size: e.size,
3221
- extension: i,
3222
- role: DocumentHelper.role(r, !1, i)
3223
- }, a = t.replace("." + o.extension, ""), c = o.extension ? a + "." + o.extension : a;
3224
- return { basename: a, fullname: c, metadata: o };
3077
+ }
3078
+ class MagnetoBehaviour extends AbstractBehaviourService {
3079
+ constructor() {
3080
+ super(...arguments);
3081
+ u(this, "APP", "magneto");
3082
+ u(this, "RESOURCE", "magneto");
3225
3083
  }
3226
- async saveFile(e, t) {
3227
- const { fullname: s, metadata: r } = this.extractMetadata(e), i = new FormData();
3228
- i.append("file", e, s);
3229
- const o = [];
3230
- ((t == null ? void 0 : t.visibility) === "public" || (t == null ? void 0 : t.visibility) === "protected") && o.push(`${t.visibility}=true`), t != null && t.application && o.push(`application=${t.application}`), r.role === "img" && o.push("quality=1"), t != null && t.parentId && o.push(`parentId=${t.parentId}`);
3231
- const a = await this.http.postFile(
3232
- `/workspace/document?${o.join("&")}`,
3233
- i
3084
+ async loadResources() {
3085
+ const { all: t } = await this.httpGet(
3086
+ "/magneto/boards/editable"
3234
3087
  );
3235
- if (this.http.isResponseError())
3236
- throw this.http.latestResponse.statusText;
3237
- return a;
3088
+ return t.map((s) => this.dataToResource({
3089
+ _id: s._id,
3090
+ title: s.title,
3091
+ icon: s.imageUrl,
3092
+ owner: s.ownerId,
3093
+ ownerName: s.ownerName,
3094
+ path: `/magneto#/board/${s._id}/view`,
3095
+ shared: !!(s.shared && s.shared.length >= 0),
3096
+ modified: "" + s.modificationDate
3097
+ }));
3238
3098
  }
3239
- async updateFile(e, t, s) {
3240
- const { fullname: r, metadata: i } = this.extractMetadata(t), o = new FormData();
3241
- o.append("file", t, r);
3242
- const a = [];
3243
- i.role === "img" && a.push("quality=1"), s != null && s.alt && a.push(`alt=${s.alt}`), s != null && s.legend && a.push(`legend=${s.legend}`), s != null && s.name && a.push(`name=${s.name}`);
3244
- const c = await this.http.putFile(
3245
- `/workspace/document/${e}?${a.join("&")}`,
3246
- o
3247
- );
3248
- if (this.http.isResponseError())
3249
- throw this.http.latestResponse.statusText;
3250
- return c;
3099
+ }
3100
+ class MindmapBehaviour extends AbstractBehaviourService {
3101
+ constructor() {
3102
+ super(...arguments);
3103
+ u(this, "APP", "mindmap");
3104
+ u(this, "RESOURCE", "mindmap");
3251
3105
  }
3252
- async deleteFile(e) {
3253
- const t = e.map((s) => s._id);
3254
- if (t.length == 0)
3255
- Promise.resolve(null);
3256
- else if (await this.http.deleteJson("/workspace/documents", {
3257
- ids: t
3258
- }), this.http.isResponseError())
3259
- throw this.http.latestResponse.statusText;
3106
+ async loadResources() {
3107
+ return (await this.httpGet("/mindmap/list/all")).map(
3108
+ (s) => this.dataToResource({
3109
+ title: s.name,
3110
+ ownerName: s.owner.displayName,
3111
+ owner: s.owner.userId,
3112
+ icon: s.thumbnail || "/img/illustrations/mindmap-default.png",
3113
+ path: "/mindmap#/view/" + s._id,
3114
+ _id: s._id,
3115
+ shared: !!(s.shared && s.shared.length >= 0),
3116
+ modified: s.modified
3117
+ })
3118
+ );
3260
3119
  }
3261
- async acceptDocuments(e) {
3262
- const t = await this.context.session().getUser();
3263
- return (s) => s.deleted && s.trasher ? (t == null ? void 0 : t.userId) == s.trasher : !0;
3120
+ }
3121
+ class PagesBehaviour extends AbstractBehaviourService {
3122
+ constructor() {
3123
+ super(...arguments);
3124
+ u(this, "APP", "pages");
3125
+ u(this, "RESOURCE", "pages");
3264
3126
  }
3265
- async searchDocuments(e) {
3266
- const t = e.filter !== "external" || e.parentId ? await this.http.get("/workspace/documents", {
3267
- queryParams: { ...e, _: (/* @__PURE__ */ new Date()).getTime() }
3268
- }) : [], s = await this.acceptDocuments(e);
3269
- return t.filter(s);
3127
+ async loadResources() {
3128
+ const t = await this.httpGet("/pages/list/all"), s = [];
3129
+ return t.forEach((r) => {
3130
+ var o;
3131
+ const i = r.thumbnail ? r.thumbnail + "?thumbnail=48x48" : "/img/illustrations/pages.svg";
3132
+ s.push(
3133
+ this.dataToResource({
3134
+ title: r.title,
3135
+ owner: r.owner.userId,
3136
+ ownerName: r.owner.displayName,
3137
+ icon: i,
3138
+ path: "/pages#/website/" + r._id,
3139
+ _id: r._id,
3140
+ shared: typeof r.shared < "u",
3141
+ modified: r.modified
3142
+ })
3143
+ ), (o = r.pages) == null || o.forEach((a) => {
3144
+ s.push(
3145
+ this.dataToResource({
3146
+ title: a.title,
3147
+ owner: r.owner.userId,
3148
+ ownerName: r.owner.displayName,
3149
+ icon: i,
3150
+ path: "/pages#/website/" + r._id + "/" + a.titleLink,
3151
+ _id: r._id + "/" + a.titleLink,
3152
+ shared: typeof r.shared < "u",
3153
+ modified: r.modified
3154
+ })
3155
+ );
3156
+ });
3157
+ }), s;
3270
3158
  }
3271
- async listDocuments(e, t) {
3272
- return this.searchDocuments({ filter: e, parentId: t, includeall: !0 });
3159
+ }
3160
+ class PollBehaviour extends AbstractBehaviourService {
3161
+ constructor() {
3162
+ super(...arguments);
3163
+ u(this, "APP", "poll");
3164
+ u(this, "RESOURCE", "poll");
3273
3165
  }
3274
- /**
3275
- * Duplicate and transfers documents if needed to a different folder with the specified application and visibility.
3276
- * @param documents - The array of documents to transfer.
3277
- * @param application - The application to associate with the transferred documents.
3278
- * @param visibility - The visibility of the transferred documents. Defaults to "protected".
3279
- * @returns A Promise that resolves to an array of transferred WorkspaceElements.
3280
- */
3281
- async transferDocuments(e, t, s = "protected") {
3282
- const r = [];
3283
- if (e.forEach((i) => {
3284
- (s === "public" && !i.public || !i.public && !i.protected) && r.push(i);
3285
- }), r.length > 0) {
3286
- const i = await this.http.post(
3287
- "/workspace/documents/transfer",
3288
- {
3289
- application: t,
3290
- visibility: s,
3291
- ids: r.map((o) => o._id)
3292
- }
3293
- );
3294
- if (this.http.isResponseError())
3295
- throw this.http.latestResponse.statusText;
3296
- return r.forEach((o, a) => {
3297
- const c = e.findIndex(
3298
- (l) => l._id === o._id
3299
- );
3300
- 0 <= c && c < e.length && (e[c] = i[a]);
3301
- }), e.filter((o) => !!o);
3302
- }
3303
- return e;
3166
+ async loadResources() {
3167
+ return (await this.httpGet("/poll/list/all")).map((s) => {
3168
+ const r = s.icon ? s.icon + "?thumbnail=48x48" : "/img/icons/glyphicons_036_file.png";
3169
+ return this.dataToResource({
3170
+ title: s.question,
3171
+ ownerName: s.owner.displayName,
3172
+ icon: r,
3173
+ path: "/poll#/view/" + s._id,
3174
+ _id: s._id,
3175
+ owner: s.owner.userId,
3176
+ shared: !!(s.shared && s.shared.length >= 0),
3177
+ modified: s.modified
3178
+ });
3179
+ });
3304
3180
  }
3305
- /**
3306
- * Get the URL of the thumbnail of a workspace element (or its URL),
3307
- * or `null` if none exists or can be created.
3308
- */
3309
- getThumbnailUrl(e, t = 0, s = 0) {
3310
- var i, o;
3311
- const r = t > 0 || s > 0 ? `${t}x${s}` : "120x120";
3312
- if (typeof e == "string")
3313
- return e.includes("data:image") || e.includes("thumbnail") ? e : `${e}${e.includes("?") ? "&" : "?"}thumbnail=${r}`;
3314
- {
3315
- const a = `/workspace/${e.public ? "pub/" : ""}document/${e._id}?thumbnail=`, c = e.thumbnails;
3316
- if ((o = (i = e.metadata) == null ? void 0 : i["content-type"]) != null && o.includes("video")) {
3317
- const l = c && Object.keys(c).length > 0 ? Object.keys(c)[0] : null;
3318
- return l ? a + l : null;
3319
- } else
3320
- return a + r;
3321
- }
3181
+ }
3182
+ class ScrapbookBehaviour extends AbstractBehaviourService {
3183
+ constructor() {
3184
+ super(...arguments);
3185
+ u(this, "APP", "scrapbook");
3186
+ u(this, "RESOURCE", "scrapbook");
3322
3187
  }
3323
- /**
3324
- * Get the URL of the file of a workspace element (or its URL),
3325
- * or `null` if none exists or can be created.
3326
- * @param filter - The filter to apply to the workspace element.
3327
- * @param withChildren - If true, include all children folders.
3328
- * @param parentId - The ID of the parent folder to list.
3329
- * @param directShared - If true, include only elements directly shared with the user.
3330
- *
3331
- */
3332
- listFolder(e, t = !1, s, r) {
3333
- const i = {
3334
- filter: e,
3335
- hierarchical: t,
3336
- parentId: s,
3337
- directShared: r
3338
- };
3339
- return this.http.get("/workspace/folders/list", {
3340
- queryParams: i
3188
+ async loadResources() {
3189
+ return (await this.httpGet(
3190
+ "/scrapbook/list/all"
3191
+ )).map((s) => {
3192
+ const r = s.icon || "/img/illustrations/scrapbook.svg";
3193
+ return this.dataToResource({
3194
+ title: s.name,
3195
+ owner: s.owner.userId,
3196
+ ownerName: s.owner.displayName,
3197
+ icon: r,
3198
+ path: "/scrapbook#/view-scrapbook/" + s._id,
3199
+ _id: s._id,
3200
+ shared: !!(s.shared && s.shared.length >= 0),
3201
+ modified: s.modified
3202
+ });
3341
3203
  });
3342
3204
  }
3343
- /**
3344
- * List all folders in the workspace.
3345
- * @param withChildren - If true, include all children folders.
3346
- * @param parentId - The ID of the parent folder to list.
3347
- * @returns A promise that resolves to an array of WorkspaceElement objects.
3348
- */
3349
- listOwnerFolders(e, t) {
3350
- return this.listFolder("owner", e, t);
3351
- }
3352
- /**
3353
- * List all shared folders in the workspace.
3354
- * @param withChildren - If true, include all children folders.
3355
- * @param parentId - The ID of the parent folder to list.
3356
- * @returns A promise that resolves to an array of WorkspaceElement objects.
3357
- */
3358
- listSharedFolders(e, t) {
3359
- return this.listFolder("shared", e, t, !0);
3205
+ }
3206
+ class TimelinegeneratorBehaviour extends AbstractBehaviourService {
3207
+ constructor() {
3208
+ super(...arguments);
3209
+ u(this, "APP", "timelinegenerator");
3210
+ u(this, "RESOURCE", "timelinegenerator");
3360
3211
  }
3361
- /**
3362
- * Create a new folder in the workspace.
3363
- * @param name - The name of the new folder.
3364
- * @param parentId - The ID of the parent folder where the new folder will be created.
3365
- * @returns void
3366
- */
3367
- createFolder(e, t) {
3368
- const s = new FormData();
3369
- return s.append("name", e), t && s.append("parentFolderId", t), this.http.postFile("/workspace/folder", s);
3212
+ loadResources() {
3213
+ return new Promise(async (t, s) => {
3214
+ try {
3215
+ const i = (await this.httpGet(
3216
+ "/timelinegenerator/timelines"
3217
+ )).map((o) => {
3218
+ const a = o.icon || "/img/illustrations/timeline-default.png";
3219
+ return this.dataToResource({
3220
+ title: o.headline,
3221
+ ownerName: o.owner.displayName,
3222
+ owner: o.owner.userId,
3223
+ icon: a,
3224
+ path: "/timelinegenerator#/view/" + o._id,
3225
+ _id: o._id,
3226
+ shared: typeof o.shared < "u",
3227
+ modified: o.modified
3228
+ });
3229
+ });
3230
+ t(i);
3231
+ } catch (r) {
3232
+ s(r);
3233
+ }
3234
+ });
3370
3235
  }
3371
3236
  }
3372
- let ATTag;
3373
- class AnalyticsService {
3374
- constructor(n) {
3375
- this.context = n;
3237
+ class WikiBehaviour extends AbstractBehaviourService {
3238
+ constructor() {
3239
+ super(...arguments);
3240
+ u(this, "APP", "wiki");
3241
+ u(this, "RESOURCE", "wiki");
3376
3242
  }
3377
- get http() {
3378
- return this.context.http();
3243
+ async loadResources() {
3244
+ return (await this.httpGet(
3245
+ "/wiki/listallpages?visible=true"
3246
+ )).map((s) => s.pages.map((r) => {
3247
+ let i;
3248
+ return typeof s.thumbnail > "u" || s.thumbnail === "" ? i = "/img/icons/glyphicons_036_file.png" : i = s.thumbnail + "?thumbnail=48x48", this.dataToResource({
3249
+ title: r.title + " [" + s.title + "]",
3250
+ ownerName: s.owner.displayName,
3251
+ owner: s.owner.userId,
3252
+ icon: i,
3253
+ path: "/wiki#/view/" + s._id + "/" + r._id,
3254
+ _id: `${s._id}#${r._id}`,
3255
+ shared: typeof s.shared < "u",
3256
+ modified: r.modified
3257
+ });
3258
+ })).flat();
3379
3259
  }
3380
- get session() {
3381
- return this.context.session();
3260
+ }
3261
+ class WorkspaceBehaviour extends AbstractBehaviourService {
3262
+ constructor() {
3263
+ super(...arguments);
3264
+ u(this, "APP", "workspace");
3265
+ u(this, "RESOURCE", "workspace");
3382
3266
  }
3383
- /**
3384
- * Xiti tracker for page loading.
3385
- * @param locationPath
3386
- * @param app
3387
- */
3388
- async trackPageLoad(n, e) {
3389
- const [t] = await Promise.all([
3390
- // get Xiti configuration
3391
- this.getXitiConfig(e.name.toLowerCase()),
3392
- // load Xiti javascript file
3393
- this.loadXitiScript()
3394
- ]);
3395
- if (!t || !ATInternet) return;
3396
- let s = t.LIBELLE_SERVICE.default || null;
3397
- for (const r in t.LIBELLE_SERVICE)
3398
- if (r !== "default" && n.indexOf(r) >= 0) {
3399
- s = t.LIBELLE_SERVICE[r];
3400
- break;
3267
+ loadResources({ search: t, asset_id: s }) {
3268
+ return new Promise(async (r, i) => {
3269
+ try {
3270
+ let o = "/workspace/documents?filter=all&hierarchical=true";
3271
+ s && s.length ? o += `&search=${t}` : t && t.length && (o += `&search=${t}`);
3272
+ const c = (await this.httpGet(o)).filter((l) => !l.deleted).map((l) => {
3273
+ const h = l.metadata["content-type"] && l.metadata["content-type"].indexOf("image") !== -1 ? `/workspace/document/${l._id}?thumbnail=120x120` : "/img/icons/unknown-large.png";
3274
+ return this.dataToResource({
3275
+ title: l.name,
3276
+ ownerName: l.ownerName,
3277
+ owner: l.owner,
3278
+ icon: h,
3279
+ path: `/workspace/document/${l._id}`,
3280
+ _id: l._id,
3281
+ shared: !!(l.shared && l.shared.length >= 0),
3282
+ modified: l.modified
3283
+ });
3284
+ });
3285
+ r(c);
3286
+ } catch (o) {
3287
+ i(o);
3401
3288
  }
3402
- ATTag = new ATInternet.Tracker.Tag({ site: t.STRUCT_ID }), ATTag.setProps(
3403
- {
3404
- SERVICE: s,
3405
- TYPE: t.TYPE,
3406
- OUTIL: t.OUTIL,
3407
- UAI: t.STRUCT_UAI,
3408
- PROJET: t.PROJET,
3409
- EXPLOITANT: t.EXPLOITANT,
3410
- PLATEFORME: t.PLATFORME,
3411
- PROFIL: t.PROFILE
3412
- },
3413
- !0
3414
- ), ATTag.identifiedVisitor.set({
3415
- id: t.ID_PERSO,
3416
- category: t.PROFILE
3417
- }), ATTag.page.set({
3418
- name: (e == null ? void 0 : e.prefix) === "userbook" ? "directory" : e == null ? void 0 : e.prefix,
3419
- chapter1: "",
3420
- chapter2: "",
3421
- chapter3: "",
3422
- level2: t.STRUCT_UAI
3423
- }), ATTag.dispatch();
3424
- }
3425
- async getXitiConfig(n) {
3426
- const [e, t] = await Promise.all([
3427
- this.http.get("/analyticsConf"),
3428
- //FIXME change servers config to only keep the "all-in-one" query to /analyticsConf.
3429
- this.http.get("/xiti/config")
3430
- ]);
3431
- if (!(e != null && e.type))
3432
- throw ERROR_CODE.MALFORMED_DATA;
3433
- return t != null && t.active && (e.xiti = await this.getXitiTrackingParams(t, n)), e.xiti;
3289
+ });
3434
3290
  }
3435
- async loadXitiScript() {
3436
- if (typeof ATInternet > "u") {
3437
- const scriptPath = "/xiti/public/js/lib/smarttag_ENT.js", response = await this.http.get(scriptPath, {
3438
- headers: { Accept: "application/javascript" }
3439
- });
3440
- if (this.http.latestResponse.status != 200)
3441
- throw "Error while loading XiTi script";
3442
- eval(response);
3291
+ }
3292
+ const b = class b {
3293
+ static async initialize(e, t) {
3294
+ const s = e.http();
3295
+ if (!this.resourceProducingApps.length) {
3296
+ this.resourceProducingApps = [t, "workspace"];
3297
+ try {
3298
+ const [r, i] = await Promise.all([
3299
+ s.get("/resources-applications"),
3300
+ e.session().getUser()
3301
+ ]);
3302
+ i != null && i.apps && (r != null && r.length) && (this.resourceProducingApps = r.filter(
3303
+ (o) => i.apps.some((a) => a.address.includes(o))
3304
+ ));
3305
+ } catch (r) {
3306
+ console.warn("Failed to load resource-producing apps:", r);
3307
+ }
3443
3308
  }
3309
+ return this.resourceProducingApps;
3444
3310
  }
3445
- async getXitiTrackingParams(n, e) {
3446
- if (!n.structureMap || !e) return;
3447
- const t = await this.session.getUser(), s = await this.session.getUserProfile();
3311
+ static registerCustomBehaviour(e, t, s) {
3312
+ this.registry.register({ application: e, resourceType: t }, s);
3313
+ }
3314
+ static async registerBehaviours(e) {
3315
+ this.resourceProducingApps.forEach((t) => {
3316
+ const s = { application: e, resourceType: t };
3317
+ this.registry.register(
3318
+ s,
3319
+ (r) => this.serviceFor(r, e, t)
3320
+ );
3321
+ });
3322
+ }
3323
+ static serviceFor(e, t, s) {
3448
3324
  let r;
3449
- if (!(t != null && t.structures)) return;
3450
- for (const l of t.structures) {
3451
- const p = n.structureMap[l];
3452
- if (p && p.collectiviteId && p.UAI) {
3453
- r = p;
3325
+ switch (s) {
3326
+ case "timelinegenerator":
3327
+ r = new TimelinegeneratorBehaviour(e);
3328
+ break;
3329
+ case "workspace":
3330
+ r = new WorkspaceBehaviour(e);
3331
+ break;
3332
+ case "blog":
3333
+ r = new BlogBehaviour(e);
3334
+ break;
3335
+ case "actualites":
3336
+ r = new ActualitesBehaviour(e);
3337
+ break;
3338
+ case "wiki":
3339
+ r = new WikiBehaviour(e);
3340
+ break;
3341
+ case "pages":
3342
+ r = new PagesBehaviour(e);
3343
+ break;
3344
+ case "poll":
3345
+ r = new PollBehaviour(e);
3346
+ break;
3347
+ case "community":
3348
+ r = new CommunityBehaviour(e);
3349
+ break;
3350
+ case "mindmap":
3351
+ r = new MindmapBehaviour(e);
3352
+ break;
3353
+ case "forum":
3354
+ r = new ForumBehaviour(e);
3355
+ break;
3356
+ case "homeworks":
3357
+ r = new HomeworksBehaviour(e);
3358
+ break;
3359
+ case "scrapbook":
3360
+ r = new ScrapbookBehaviour(e);
3361
+ break;
3362
+ case "collaborativewall":
3363
+ r = new CollaborativewallBehaviour(e);
3454
3364
  break;
3455
- }
3456
- }
3457
- if (!r || !r.active) return;
3458
- const i = await configure.Platform.apps.getPublicConf(e);
3459
- if (!i) return;
3460
- const o = i.xiti;
3461
- if (!o || !o.LIBELLE_SERVICE || !r.UAI) return;
3462
- function a(l) {
3463
- let p = "";
3464
- for (let E = 0; E < l.length; E++)
3465
- p += l.charCodeAt(E);
3466
- return p;
3365
+ case "exercizer":
3366
+ r = new ExercizerBehaviour(e);
3367
+ break;
3368
+ case "formulaire":
3369
+ r = new FormulaireBehaviour(e);
3370
+ break;
3371
+ case "magneto":
3372
+ r = new MagnetoBehaviour(e);
3373
+ break;
3374
+ case "appointments":
3375
+ r = new AppointmentsBehaviour(e);
3376
+ break;
3377
+ default:
3378
+ throw ERROR_CODE.NOT_SUPPORTED;
3467
3379
  }
3468
- const c = {
3469
- Student: "ELEVE",
3470
- Teacher: "ENSEIGNANT",
3471
- Relative: "PARENT",
3472
- Personnel: "ADMIN_VIE_SCOL_TECH",
3473
- Guest: "AUTRE"
3474
- };
3475
- return {
3476
- LIBELLE_SERVICE: o.LIBELLE_SERVICE,
3477
- // Which property of LIBELLE_SERVICE to use depends on the frontend.
3478
- TYPE: o.OUTIL ? "TIERS" : "NATIF",
3479
- OUTIL: o.OUTIL ? o.OUTIL : "",
3480
- STRUCT_ID: r.collectiviteId,
3481
- STRUCT_UAI: r.UAI,
3482
- PROJET: r.projetId ? r.projetId : n.ID_PROJET,
3483
- EXPLOITANT: n.ID_EXPLOITANT,
3484
- PLATFORME: r.plateformeId ? r.plateformeId : n.ID_PLATEFORME,
3485
- ID_PERSO: a(t.userId),
3486
- PROFILE: s && s.length > 0 ? c[s[0]] ?? "" : ""
3487
- };
3380
+ return r.APP = t, r;
3488
3381
  }
3489
- }
3490
- const R = class R {
3491
- // in minutes. Applies to recorded videos.
3382
+ };
3383
+ //
3384
+ // STATIC REGISTRY
3385
+ //
3386
+ u(b, "registry", new ServiceRegistry()), // Expose some useful functions
3387
+ u(b, "findBehaviour", b.registry.findService.bind(b.registry)), u(b, "hasBehaviour", b.registry.isRegistered.bind(b.registry)), u(b, "resourceProducingApps", []);
3388
+ let SnipletsService = b;
3389
+ class RightService {
3492
3390
  constructor(e) {
3493
3391
  this.context = e;
3494
3392
  }
3495
- get http() {
3496
- return this.context.http();
3497
- }
3498
- get conf() {
3499
- return this.context.conf();
3393
+ get session() {
3394
+ return this.context.session();
3500
3395
  }
3501
3396
  /**
3502
- * Returns the video app public conf (maxWeight, maxDuration and accepted extensions)
3503
- * @returns the Video app public conf
3397
+ * Parse right concat as "$TYPE:$ID:$RIGHT"
3398
+ * $TYPE = user | group | creator
3399
+ * $ID: id of the resource
3400
+ * $RIGHT: read | contrib | manage
3401
+ *
3402
+ * @param right a concat right
3403
+ * @returns Right parsed
3504
3404
  */
3505
- async getVideoConf() {
3506
- var t;
3507
- const e = await this.conf.getPublicConf(
3508
- APP$4.VIDEO
3509
- );
3510
- return {
3511
- maxWeight: (e == null ? void 0 : e["max-videosize-mbytes"]) ?? R.MAX_WEIGHT,
3512
- maxDuration: (e == null ? void 0 : e["max-videoduration-minutes"]) ?? R.MAX_DURATION,
3513
- acceptVideoUploadExtensions: ((t = e == null ? void 0 : e["accept-videoupload-extensions"]) == null ? void 0 : t.map(
3514
- (s) => s.toUpperCase()
3515
- )) ?? []
3516
- };
3405
+ parseResourceRight(e) {
3406
+ const t = e.split(":");
3407
+ if (t.length === 2) {
3408
+ if (t[0] === "creator")
3409
+ return {
3410
+ id: t[1],
3411
+ right: "creator",
3412
+ type: "creator"
3413
+ };
3414
+ } else return t.length === 3 ? {
3415
+ id: t[1],
3416
+ right: t[2],
3417
+ type: t[0]
3418
+ } : void 0;
3517
3419
  }
3518
3420
  /**
3519
- * Starts the encoding process and check when video is fully processed.
3520
- * @param params cf VideoUploadParams
3521
- * @returns a VideoCheckResponse
3421
+ * Parse an array of rights concat as "$TYPE:$ID:$RIGHT"
3422
+ * $TYPE = user | group | creator
3423
+ * $ID: id of the resource
3424
+ * $RIGHT: read | contrib | manage
3425
+ *
3426
+ * @param rights a list of concat rights
3427
+ * @returns Array of Right parsed
3522
3428
  */
3523
- async upload({
3524
- data: e,
3525
- appCode: t,
3526
- captation: s,
3527
- duration: r
3528
- }) {
3529
- if (!e.file)
3530
- throw new Error("Invalid video file.");
3531
- if (!e.filename)
3532
- throw new Error("Invalid video filename");
3533
- const i = `${e.browser.name} ${e.browser.version}`, o = new FormData();
3534
- o.append("device", e.device || ""), o.append("browser", i), o.append("url", e.url), o.append("app", t), o.append("file", e.file, e.filename), o.append("weight", "" + e.file.size), o.append("captation", "" + s);
3535
- let a = `/video/encode?captation=${s}`;
3536
- r && (a += `&duration=${r}`);
3537
- const c = await this.http.post(
3538
- a,
3539
- o,
3540
- { headers: { "Content-Type": "multipart/form-data" } }
3541
- );
3542
- if (c.state == "running") {
3543
- let l = 0, p = 1;
3544
- do {
3545
- const E = p + l;
3546
- await new Promise(
3547
- (y) => setTimeout(y, E * 1e3)
3548
- ), l = p, p = Math.min(8, E);
3549
- const h = await this.http.get(
3550
- `/video/status/${c.processid}`
3551
- );
3552
- if (h.state == "succeed")
3553
- return h.videoworkspaceid && h.videosize && this.context.data().trackVideoSave(
3554
- h.videoworkspaceid,
3555
- Math.round(r),
3556
- h.videosize,
3557
- s,
3558
- e.url,
3559
- i,
3560
- e.device
3561
- ), h;
3562
- if (h.state == "error")
3563
- break;
3564
- } while (!0);
3565
- }
3566
- throw new Error("Video cannot be uploaded.");
3567
- }
3568
- };
3569
- u(R, "MAX_WEIGHT", 50), // in Mbytes. Applies to uploaded videos.
3570
- u(R, "MAX_DURATION", 3);
3571
- let VideoService = R;
3572
- class EmbedderService {
3573
- constructor(e) {
3574
- this.context = e;
3575
- }
3576
- get http() {
3577
- return this.context.http();
3429
+ parseResourceRights(e) {
3430
+ return e.map((s) => this.parseResourceRight(s)).filter((s) => s !== void 0);
3578
3431
  }
3579
3432
  /**
3580
- * Returns the default list of video embedder
3581
- * @returns the default list of video embedder
3433
+ * Check wether a user has the expected right for a resource
3434
+ * @param user the userId and groupId concerned by the check
3435
+ * @param expect the expected right to check
3436
+ * @param rights array of Right for the resource
3437
+ * @returns true if has rights
3582
3438
  */
3583
- async getDefault() {
3584
- return this.http.get("/infra/embed/default");
3439
+ hasResourceRight({ id: e, groupIds: t }, s, r) {
3440
+ const i = r.map((o) => typeof o == "string" ? this.parseResourceRight(o) : o).filter((o) => o !== void 0);
3441
+ for (const o of i) {
3442
+ if (o.id === e && o.type === "creator")
3443
+ return !0;
3444
+ if (o.id === e && o.type === "user" && o.right === s)
3445
+ return !0;
3446
+ if (t.includes(o.id) && o.type === "group" && o.right === s)
3447
+ return !0;
3448
+ }
3449
+ return !1;
3585
3450
  }
3586
3451
  /**
3587
- * Returns the custom list of video embedder
3588
- * @returns the custom list of video embedder
3452
+ * Check wether the current user have resource right
3453
+ * @param expect the expected right to check
3454
+ * @param rights array of Right for the resource
3455
+ * @returns true if has rights
3589
3456
  */
3590
- async getCustom() {
3591
- return this.http.get("/infra/embed/custom");
3457
+ async sessionHasResourceRight(e, t) {
3458
+ try {
3459
+ const s = await this.session.getUser();
3460
+ return !!s && this.hasResourceRight(
3461
+ { groupIds: s.groupsIds, id: s.userId },
3462
+ e,
3463
+ t
3464
+ );
3465
+ } catch (s) {
3466
+ return console.error(`Unexpected error ${s} in sessionHasResourceRight()`), !1;
3467
+ }
3592
3468
  }
3593
3469
  /**
3594
- * The provider matching with the URL
3595
- * @param {Embedder[]} embedderList - The list of video providers to test with
3596
- * @param {String} url - The URL for the video
3597
- * @returns The provider matching with the URL or undefined
3470
+ * Check wether the current user have at least one of resource right expected
3471
+ * @param expects array of expected right to check
3472
+ * @param rights array of Right for the resource
3473
+ * @returns true if has rights
3598
3474
  */
3599
- getProviderFromUrl(e, t) {
3475
+ async sessionHasAtLeastOneResourceRight(e, t) {
3600
3476
  for (const s of e)
3601
- if (this.isUrlFromProvider(t, s))
3602
- return s;
3477
+ if (await this.sessionHasResourceRight(s, t))
3478
+ return !0;
3479
+ return !1;
3603
3480
  }
3604
- urlIsFromPattern(e, t) {
3605
- const s = new RegExp("[^{}]+(?=(?:[^{}]*{[^}]*})*[^}]*$)", "g"), r = new RegExp("{[^}]*}", "g");
3606
- let i = !0;
3607
- const o = t.match(s) || [], a = [];
3608
- return (t.match(r) || []).forEach((l, p) => {
3609
- l.includes("ignore") || a.push(o[p]);
3610
- }), a.forEach((l) => {
3611
- if (!e.includes(l)) {
3612
- i = !1;
3613
- return;
3614
- }
3615
- }), i;
3481
+ /**
3482
+ * Check wether the current user has resource right for each right list
3483
+ * @param expect expected right to check
3484
+ * @param rightsArray array of array of Right for multiple resources
3485
+ * @returns true if has rights
3486
+ */
3487
+ async sessionHasResourceRightForEachList(e, t) {
3488
+ let s = 0;
3489
+ for (const r of t)
3490
+ await this.sessionHasResourceRight(e, r) && s++;
3491
+ return s === t.length;
3616
3492
  }
3617
3493
  /**
3618
- * Check if a given URL correspond to one of the URL pattern of the provider
3619
- * @param {String} url - The URL for the video
3620
- * @param {Embedder} embedder - The video provider to test with
3621
- * @returns boolean depending if a given URL correspond to one of the URL pattern of the provider
3494
+ * Check wether the current user have at least one of resource right for each right list
3495
+ * @param expects array of expected right to check
3496
+ * @param rightsArray array of array of Right for multiple resources
3497
+ * @returns true if has rights
3622
3498
  */
3623
- isUrlFromProvider(e, t) {
3624
- typeof t.url == "string" && (t.url = [t.url]);
3625
- for (const s of t.url)
3626
- if (this.urlIsFromPattern(e, s))
3499
+ async sessionHasAtLeastOneResourceRightForEachList(e, t) {
3500
+ for (const s of e) {
3501
+ let r = 0;
3502
+ for (const i of t)
3503
+ await this.sessionHasResourceRight(s, i) && r++;
3504
+ if (r === t.length)
3627
3505
  return !0;
3506
+ }
3628
3507
  return !1;
3629
3508
  }
3509
+ hasWorkflowRight(e, t) {
3510
+ return t.findIndex((s) => s === e) !== -1;
3511
+ }
3512
+ /**
3513
+ * @param expect a workflow right
3514
+ * @returns true if current session has right on it
3515
+ */
3516
+ async sessionHasWorkflowRight(e) {
3517
+ try {
3518
+ const t = await this.session.getUser();
3519
+ return !!t && this.hasWorkflowRight(
3520
+ e,
3521
+ t.authorizedActions.map(
3522
+ (s) => s.name
3523
+ )
3524
+ );
3525
+ } catch (t) {
3526
+ return console.error(`Unexpected error ${t} in sessionHasWorkflowRight()`), !1;
3527
+ }
3528
+ }
3630
3529
  /**
3631
- * Get embed code to display the video for an URL and a provider
3632
- * @param {Embedder} embedder - The video provider for the URL
3633
- * @param {String} url - The URL for the video
3634
- * @returns embed code to display the video for an URL and a provider
3530
+ * @param expect a workflow right
3531
+ * @returns a record with right as key and boolean as value if current session has right on it
3635
3532
  */
3636
- getEmbedCodeForProvider(e, t) {
3637
- for (const s of e.url)
3638
- if (this.urlIsFromPattern(t, s)) {
3639
- const r = new RegExp("{[a-zA-Z0-9_.]+}", "g"), i = s.match(r) || [];
3640
- let o = e.embed;
3641
- for (const a of i) {
3642
- let c = s.split(a)[0];
3643
- const l = c.split("}");
3644
- l.length > 1 && (c = l[l.length - 1]);
3645
- let p = t.split(c)[1];
3646
- if (!p)
3647
- continue;
3648
- const E = s.split(a)[1].split("{")[0];
3649
- E && (p = p.split(E)[0]);
3650
- const h = new RegExp("\\" + a.replace(/}/, "\\}"), "g");
3651
- o = o.replace(h, p);
3652
- }
3653
- return o;
3654
- }
3655
- return "";
3533
+ async sessionHasWorkflowRights(e) {
3534
+ const t = {};
3535
+ try {
3536
+ const s = await this.session.getUser();
3537
+ for (const r of e)
3538
+ t[r] = !!s && this.hasWorkflowRight(
3539
+ r,
3540
+ s.authorizedActions.map(
3541
+ (i) => i.name
3542
+ )
3543
+ );
3544
+ } catch (s) {
3545
+ console.error(`Unexpected error ${s} in sessionHasWorkflowRights()`);
3546
+ for (const r of e)
3547
+ t[r] = !1;
3548
+ }
3549
+ return t;
3656
3550
  }
3657
3551
  }
3658
- class AbstractBehaviourService {
3659
- //
3660
- // IMPLEMENTATION
3661
- //
3552
+ class SessionService {
3662
3553
  constructor(e) {
3663
- //-----------------
3664
- //--- Utilities ---
3665
- //-----------------
3666
- u(this, "_cache");
3667
- this.context = e, this._cache = new CacheService(this.context);
3554
+ this.context = e;
3668
3555
  }
3669
- getApplication() {
3670
- return this.APP;
3556
+ get http() {
3557
+ return this.context.http();
3671
3558
  }
3672
- getResourceType() {
3673
- return this.RESOURCE;
3559
+ get cache() {
3560
+ return this.context.cache();
3674
3561
  }
3675
- httpGet(e, t) {
3676
- return this._cache.httpGetJson(e, t);
3562
+ get conf() {
3563
+ return this.context.conf();
3677
3564
  }
3678
- /* Utility to map data between linker model and search model. */
3679
- dataToResource({
3680
- modified: e,
3681
- ...t
3682
- }) {
3683
- const s = typeof e == "string" ? e : e != null && e.$date ? "" + e.$date : "";
3565
+ /**
3566
+ * Callback to call when user logout
3567
+ */
3568
+ onLogout() {
3569
+ this.cache.clearCache();
3570
+ }
3571
+ /**
3572
+ * Callback to call when session change
3573
+ */
3574
+ onRefreshSession() {
3575
+ this.cache.clearCache();
3576
+ }
3577
+ async getSession() {
3578
+ const [e, t] = await Promise.all([
3579
+ this.getUser(),
3580
+ this.getPerson()
3581
+ ]), [
3582
+ s,
3583
+ r,
3584
+ i,
3585
+ o,
3586
+ a
3587
+ ] = await Promise.all([
3588
+ this.getCurrentLanguage(e),
3589
+ this.latestQuotaAndUsage(e),
3590
+ this.loadDescription(e),
3591
+ this.getUserProfile(),
3592
+ this.getBookmarks(e)
3593
+ ]), { type: c, ...l } = t || {}, h = {
3594
+ ...l,
3595
+ profiles: c || ["Guest"],
3596
+ // "type" field from /userbook/api/person becomes "profiles"
3597
+ ...i
3598
+ // Inject other fields (also the correct "type")
3599
+ };
3684
3600
  return {
3685
- application: this.RESOURCE,
3686
- name: t.title,
3687
- creatorId: t.owner,
3688
- creatorName: t.ownerName,
3689
- thumbnail: t.icon,
3690
- assetId: t._id,
3691
- modifiedAt: s,
3692
- shared: t.shared,
3693
- path: t.path
3601
+ user: e,
3602
+ quotaAndUsage: r,
3603
+ currentLanguage: s,
3604
+ userDescription: h,
3605
+ userProfile: o,
3606
+ bookmarkedApps: a
3694
3607
  };
3695
3608
  }
3696
- }
3697
- class ActualitesBehaviour extends AbstractBehaviourService {
3698
- constructor() {
3699
- super(...arguments);
3700
- u(this, "APP", "actualites");
3701
- u(this, "RESOURCE", "actualites");
3609
+ login(e, t, s, r) {
3610
+ const i = new FormData();
3611
+ return i.append("email", e), i.append("password", t), typeof s < "u" && i.append("rememberMe", "" + s), typeof r < "u" && i.append("secureLocation", "" + r), this.http.post("/auth/login", i, {
3612
+ headers: { "content-type": "application/x-www-form-urlencoded" }
3613
+ }).finally(() => {
3614
+ switch (this.http.latestResponse.status) {
3615
+ case 200:
3616
+ throw ERROR_CODE.MALFORMED_DATA;
3617
+ }
3618
+ });
3702
3619
  }
3703
- async loadResources() {
3704
- const [t, s] = await Promise.all([
3705
- this.httpGet("/actualites/api/v1/infos/linker"),
3706
- this.httpGet("/actualites/api/v1/threads")
3707
- ]), r = s.reduce(
3708
- (i, o) => i.set(o.id, o),
3709
- /* @__PURE__ */ new Map()
3710
- );
3711
- return t.map((i) => {
3712
- var a;
3713
- let o;
3714
- return i.threadIcon ? o = i.threadIcon + "?thumbnail=48x48" : o = "/img/icons/glyphicons_036_file.png", this.dataToResource({
3715
- title: i.title + " [" + ((a = r.get(i.threadId)) == null ? void 0 : a.title) + "]",
3716
- ownerName: i.owner.displayName,
3717
- owner: i.owner.id,
3718
- icon: o,
3719
- path: "/actualites/threads/" + i.threadId + "?info=" + i.id,
3720
- _id: `${i.threadId}#${i.id}`,
3721
- shared: !!(i.shared && i.shared.length >= 0),
3722
- modified: i.modified
3723
- });
3620
+ async logout() {
3621
+ const e = await this.conf.getLogoutCallback();
3622
+ return this.http.get("/auth/logout?callback=" + e).finally(() => {
3724
3623
  });
3725
3624
  }
3726
- }
3727
- const hexToDataUrl = (n, e = 1, t = 1) => {
3728
- const s = document.createElement("canvas");
3729
- s.width = e, s.height = t;
3730
- const r = s.getContext("2d");
3731
- return r ? (r.fillStyle = n, r.fillRect(0, 0, e, t), s.toDataURL("image/png")) : "";
3732
- };
3733
- class AppointmentsBehaviour extends AbstractBehaviourService {
3734
- constructor() {
3735
- super(...arguments);
3736
- u(this, "APP", "appointments");
3737
- u(this, "RESOURCE", "appointments");
3625
+ async latestQuotaAndUsage(e) {
3626
+ const t = { quota: 0, storage: 0 };
3627
+ if (!e) return t;
3628
+ try {
3629
+ return await this.http.get(
3630
+ `/workspace/quota/user/${e == null ? void 0 : e.userId}`
3631
+ );
3632
+ } catch (s) {
3633
+ return console.error(s), t;
3634
+ }
3738
3635
  }
3739
- async loadResources() {
3740
- return (await this.httpGet("/appointments/grids/linker")).map((s) => this.dataToResource({
3741
- _id: s.id.toString(),
3742
- icon: hexToDataUrl(s.color, 100, 100),
3743
- title: s.name,
3744
- ownerName: s.ownerName,
3745
- owner: s.ownerId,
3746
- path: `${window.location.origin}/appointments#?gridId=${s.id}`,
3747
- shared: !1,
3748
- modified: s.updatingDate
3749
- }));
3636
+ async getCurrentLanguage(e) {
3637
+ const t = (e == null ? void 0 : e.sessionMetadata) && (e == null ? void 0 : e.sessionMetadata.userId);
3638
+ try {
3639
+ let s;
3640
+ return t ? s = await this.loadUserLanguage() : s = await this.loadDefaultLanguage(), s;
3641
+ } catch (s) {
3642
+ console.error(s);
3643
+ }
3750
3644
  }
3751
- }
3752
- class BlogBehaviour extends AbstractBehaviourService {
3753
- constructor() {
3754
- super(...arguments);
3755
- u(this, "APP", "blog");
3756
- u(this, "RESOURCE", "blog");
3645
+ async loadUserLanguage() {
3646
+ try {
3647
+ const e = await this.http.get(
3648
+ "/userbook/preference/language"
3649
+ );
3650
+ return JSON.parse(e.preference)["default-domain"];
3651
+ } catch {
3652
+ return await this.loadDefaultLanguage();
3653
+ }
3757
3654
  }
3758
- loadResources() {
3759
- return new Promise(async (t, s) => {
3760
- try {
3761
- const r = await this.httpGet("/blog/linker"), i = [];
3762
- r.forEach((o) => {
3763
- o.thumbnail ? o.thumbnail = o.thumbnail + "?thumbnail=48x48" : o.thumbnail = "/img/illustrations/blog.svg";
3764
- const a = o.fetchPosts.map((c) => this.dataToResource({
3765
- owner: o.author.userId,
3766
- ownerName: o.author.username,
3767
- title: c.title + " [" + o.title + "]",
3768
- _id: `${o._id}#${c._id}`,
3769
- icon: o.thumbnail,
3770
- path: `/blog/id/${o._id}/post/${c._id}`,
3771
- shared: !!(o.shared && o.shared.length >= 0),
3772
- modified: o.modified
3773
- }));
3774
- i.push(...a);
3775
- }), t(i);
3776
- } catch (r) {
3777
- s(r);
3778
- }
3655
+ async loadDefaultLanguage() {
3656
+ return (await this.cache.httpGetJson(
3657
+ "/locale"
3658
+ )).locale;
3659
+ }
3660
+ async getUser() {
3661
+ const { response: e, value: t } = await this.cache.httpGet(
3662
+ "/auth/oauth2/userinfo"
3663
+ );
3664
+ if (!(e.status < 200 || e.status >= 300) && typeof t == "object")
3665
+ return t;
3666
+ throw ERROR_CODE.NOT_LOGGED_IN;
3667
+ }
3668
+ hasWorkflow({
3669
+ workflowName: e,
3670
+ user: t
3671
+ }) {
3672
+ return e === void 0 || (t == null ? void 0 : t.authorizedActions.findIndex((s) => s.name === e)) !== -1;
3673
+ }
3674
+ async loadDescription(e) {
3675
+ if (!e) return {};
3676
+ try {
3677
+ const [t, s] = await Promise.all([
3678
+ // FIXME The full user's description should be obtainable from a single endpoint in the backend.
3679
+ this.getUserProfile({
3680
+ options: { requestName: "refreshAvatar" }
3681
+ }),
3682
+ this.http.get("/directory/userbook/" + (e == null ? void 0 : e.userId))
3683
+ ]);
3684
+ return { ...s, profiles: t };
3685
+ } catch (t) {
3686
+ return console.error(t), {};
3687
+ }
3688
+ }
3689
+ async getBookmarks(e) {
3690
+ if (!e) return [];
3691
+ const t = await this.http.get("/userbook/preference/apps");
3692
+ t.preference || (t.preference = null);
3693
+ const s = JSON.parse(t.preference);
3694
+ let r;
3695
+ r = s, r || (r = {
3696
+ bookmarks: [],
3697
+ applications: []
3779
3698
  });
3699
+ const i = [];
3700
+ return r.bookmarks.forEach((o, a) => {
3701
+ const c = ((e == null ? void 0 : e.apps) || []).find(
3702
+ (l) => l.name === o
3703
+ );
3704
+ if (c) {
3705
+ const l = Object.assign({}, c);
3706
+ i.push(l);
3707
+ }
3708
+ }), i;
3780
3709
  }
3781
- }
3782
- class CollaborativewallBehaviour extends AbstractBehaviourService {
3783
- constructor() {
3784
- super(...arguments);
3785
- u(this, "APP", "collaborativewall");
3786
- u(this, "RESOURCE", "collaborativewall");
3710
+ async getUserProfile(e = {}) {
3711
+ const t = await this.getPerson(e);
3712
+ return (t == null ? void 0 : t.type) || ["Guest"];
3787
3713
  }
3788
- async loadResources() {
3789
- return (await this.httpGet(
3790
- "/collaborativewall/list/all"
3791
- )).map(
3792
- (s) => this.dataToResource({
3793
- title: s.name,
3794
- ownerName: s.owner.displayName,
3795
- owner: s.owner.userId,
3796
- icon: s.icon ? s.icon : "/img/illustrations/collaborative-wall-default.png",
3797
- path: "/collaborativewall#/view/" + s._id,
3798
- _id: s._id,
3799
- shared: !!(s.shared && s.shared.length >= 0),
3800
- modified: s.modified
3801
- })
3714
+ async getPerson(e = {}) {
3715
+ var c;
3716
+ const { options: t = {}, params: s = {} } = e, r = new URLSearchParams(s).toString(), i = `/userbook/api/person${r ? `?${r}` : ""}`, { response: o, value: a } = await this.cache.httpGet(
3717
+ i,
3718
+ t
3802
3719
  );
3720
+ return o.status < 200 || o.status >= 300 || typeof a == "string" ? null : ((c = a == null ? void 0 : a.result) == null ? void 0 : c[0]) || null;
3803
3721
  }
3804
- }
3805
- class CommunityBehaviour extends AbstractBehaviourService {
3806
- constructor() {
3807
- super(...arguments);
3808
- u(this, "APP", "community");
3809
- u(this, "RESOURCE", "community");
3722
+ async isAdml() {
3723
+ const e = await this.getUser();
3724
+ return (e == null ? void 0 : e.functions.ADMIN_LOCAL) !== void 0;
3810
3725
  }
3811
- async loadResources() {
3812
- return (await this.httpGet(
3813
- "/community/listallpages"
3814
- )).map((s) => {
3815
- let r;
3816
- return typeof s.thumbnail > "u" || s.thumbnail === "" ? r = "/img/icons/glyphicons_036_file.png" : r = s.thumbnail + "?thumbnail=48x48", this.dataToResource({
3817
- title: s.name,
3818
- icon: r,
3819
- path: "/community#/view/" + s.id,
3820
- _id: s.id,
3821
- owner: "",
3822
- ownerName: "",
3823
- shared: !!(s.shared && s.shared.length >= 0),
3824
- modified: s.name
3825
- // FIXME date ?
3826
- });
3726
+ /**
3727
+ * Get details of an application if the user can access it.
3728
+ * @return undefined if no access, or app not found
3729
+ */
3730
+ async getWebApp(e) {
3731
+ const t = await this.getUser();
3732
+ return t == null ? void 0 : t.apps.find((s) => {
3733
+ var r;
3734
+ return s != null && s.prefix ? (s == null ? void 0 : s.prefix.replace("/", "")) === e || !1 : s != null && s.address && ((r = s.address) == null ? void 0 : r.split("/")[1]) === e || !1;
3827
3735
  });
3828
3736
  }
3829
3737
  }
3830
- class ExercizerBehaviour extends AbstractBehaviourService {
3831
- constructor() {
3832
- super(...arguments);
3833
- u(this, "APP", "exercizer");
3834
- u(this, "RESOURCE", "exercizer");
3835
- }
3836
- async loadResources() {
3837
- return (await this.httpGet(
3838
- "/exercizer/subjects-scheduled"
3839
- )).map((s) => {
3840
- const r = s.picture ? s.picture + "?thumbnail=48x48" : "/img/illustrations/exercizer.svg";
3841
- let i, o = !1;
3842
- const a = JSON.parse(s.scheduled_at);
3843
- return a.groupList.length > 0 ? (o = !0, i = a.groupList[0].name) : a.userList.length > 0 ? (o = !0, i = a.userList[0].name) : i = "", a.groupList.length + a.userList.length > 1 && (i += "..."), this.dataToResource({
3844
- title: s.title,
3845
- owner: s.owner,
3846
- ownerName: i,
3847
- icon: r,
3848
- path: "/exercizer#/linker/" + s.id,
3849
- _id: "" + s.id,
3850
- shared: o,
3851
- modified: s.modified
3852
- });
3853
- });
3738
+ class StringUtils {
3739
+ static removeAccents(e) {
3740
+ for (let t = 0; t < defaultDiacriticsRemovalMap.length; t++)
3741
+ e = e.replace(
3742
+ defaultDiacriticsRemovalMap[t].letters,
3743
+ defaultDiacriticsRemovalMap[t].base
3744
+ );
3745
+ return e;
3854
3746
  }
3855
3747
  }
3856
- class FormulaireBehaviour extends AbstractBehaviourService {
3857
- constructor() {
3858
- super(...arguments);
3859
- u(this, "APP", "formulaire");
3860
- u(this, "RESOURCE", "formulaire");
3748
+ class ShareService {
3749
+ //
3750
+ // IMPLEMENTATION
3751
+ //
3752
+ constructor(e) {
3753
+ this.context = e;
3861
3754
  }
3862
- async loadResources() {
3863
- return (await this.httpGet(
3864
- "/formulaire/forms/linker"
3865
- )).map((s) => (s.picture || (s.picture = "/formulaire/public/img/logo.svg"), this.dataToResource({
3866
- _id: "" + s.id,
3867
- icon: s.picture,
3868
- title: s.title,
3869
- ownerName: s.owner_name,
3870
- owner: s.owner_id,
3871
- path: s.is_public ? `${window.location.origin}/formulaire-public#/form/${s.public_key}` : `${window.location.origin}/formulaire#/form/${s.id}/${s.rgpd ? "rgpd" : "new"}`,
3872
- shared: !!(s.shared && s.shared.length >= 0),
3873
- modified: "" + s.date_modification
3874
- })));
3755
+ get directory() {
3756
+ return this.context.directory();
3875
3757
  }
3876
- }
3877
- class ForumBehaviour extends AbstractBehaviourService {
3878
- constructor() {
3879
- super(...arguments);
3880
- u(this, "APP", "forum");
3881
- u(this, "RESOURCE", "forum");
3758
+ get http() {
3759
+ return this.context.http();
3882
3760
  }
3883
- async loadResources() {
3884
- return (await this.httpGet("/forum/categories")).map(
3885
- (s) => this.dataToResource({
3886
- _id: s._id,
3887
- title: s.name,
3888
- icon: s.icon || "/img/illustrations/forum.svg",
3889
- path: "/forum#/view/" + s._id,
3890
- ownerName: s.owner.displayName,
3891
- owner: s.owner.userId,
3892
- shared: !!(s.shared && s.shared.length >= 0),
3893
- modified: s.modified
3761
+ get cache() {
3762
+ return this.context.cache();
3763
+ }
3764
+ getSearchUrl(e, t, s, r) {
3765
+ if (!r)
3766
+ return `/${e}/share/json/${t}?search=${s}`;
3767
+ if (r.includes("?search=")) {
3768
+ const [i] = r.split("?search=");
3769
+ return `${i}?search=${s}`;
3770
+ } else return r.includes("?") ? `${r}&search=${s}` : `${r}?search=${s}`;
3771
+ }
3772
+ async searchShareSubjects(e, t, s, r) {
3773
+ const i = StringUtils.removeAccents(s).toLowerCase(), o = this.getSearchUrl(
3774
+ e,
3775
+ t,
3776
+ s,
3777
+ r
3778
+ ), a = await this.cache.httpGetJson(o), c = a.users.visibles.filter(({ username: p, firstName: y, lastName: d, login: g }) => {
3779
+ const A = StringUtils.removeAccents(
3780
+ d || ""
3781
+ ).toLowerCase(), f = StringUtils.removeAccents(
3782
+ y || ""
3783
+ ).toLowerCase(), w = StringUtils.removeAccents(
3784
+ p || ""
3785
+ ).toLowerCase(), F = StringUtils.removeAccents(g || "").toLowerCase();
3786
+ return w.includes(i) || f.includes(i) || A.includes(i) || F.includes(i);
3787
+ }).map((p) => ({
3788
+ avatarUrl: this.directory.getAvatarUrl(p.id, "user"),
3789
+ directoryUrl: this.directory.getDirectoryUrl(p.id, "user"),
3790
+ displayName: p.username,
3791
+ id: p.id,
3792
+ profile: p.profile,
3793
+ type: "user"
3794
+ })), l = a.groups.visibles.filter(({ name: p }) => StringUtils.removeAccents(p || "").toLowerCase().includes(i)).map((p) => ({
3795
+ avatarUrl: this.directory.getAvatarUrl(p.id, "group"),
3796
+ directoryUrl: this.directory.getDirectoryUrl(p.id, "group"),
3797
+ displayName: p.name,
3798
+ id: p.id,
3799
+ type: "group",
3800
+ structureName: p.structureName
3801
+ }));
3802
+ return [...(await this.directory.getBookMarks()).filter(({ displayName: p }) => StringUtils.removeAccents(
3803
+ p || ""
3804
+ ).toLowerCase().includes(i)).map((p) => ({
3805
+ avatarUrl: "",
3806
+ directoryUrl: "",
3807
+ profile: "",
3808
+ displayName: p.displayName,
3809
+ id: p.id,
3810
+ type: "sharebookmark"
3811
+ })), ...c, ...l];
3812
+ }
3813
+ async getShareMapping(e, t) {
3814
+ const s = await this.cache.httpGetJson(
3815
+ t || `/${e}/rights/sharing`
3816
+ );
3817
+ for (const r of Object.keys(s))
3818
+ if (r.includes(".")) {
3819
+ const i = r.split(".")[1], o = s[r];
3820
+ delete s[r], s[i] = o;
3821
+ }
3822
+ return s;
3823
+ }
3824
+ getActionsAvailableFor({ id: e, type: t }, s, r) {
3825
+ const o = (t === "user" ? s.users.checked[e] : s.groups.checked[e]) || [], a = Object.keys(r), c = [];
3826
+ for (const l of a)
3827
+ r[l].filter(
3828
+ (p) => o.includes(p)
3829
+ ).length > 0 && c.push(l);
3830
+ return c;
3831
+ }
3832
+ async getRightsForResource(e, t, s) {
3833
+ const r = await this.directory.getBookMarks(), i = this.getSearchUrl(
3834
+ e,
3835
+ t,
3836
+ "",
3837
+ s == null ? void 0 : s.getResourceRights
3838
+ ), o = await this.cache.httpGetJson(
3839
+ i
3840
+ ), a = await this.getShareMapping(
3841
+ e,
3842
+ s == null ? void 0 : s.getShareMapping
3843
+ ), c = await this.cache.httpGetJson(
3844
+ "/infra/public/json/sharing-rights.json"
3845
+ ), l = Object.keys(o.users.checked).map((d) => o.users.visibles.find(
3846
+ (A) => A.id === d
3847
+ )).filter((d) => d !== void 0).map((d) => {
3848
+ const g = this.getActionsAvailableFor(
3849
+ { id: d.id, type: "user" },
3850
+ o,
3851
+ a
3852
+ );
3853
+ return {
3854
+ id: d.id,
3855
+ type: "user",
3856
+ displayName: d.username,
3857
+ profile: d.profile,
3858
+ avatarUrl: this.directory.getAvatarUrl(d.id, "user"),
3859
+ directoryUrl: this.directory.getDirectoryUrl(d.id, "user"),
3860
+ actions: g.map((f) => {
3861
+ const w = c[f];
3862
+ return {
3863
+ displayName: f,
3864
+ id: f,
3865
+ priority: w.priority
3866
+ };
3867
+ })
3868
+ };
3869
+ }).sort((d, g) => (d.displayName || "").localeCompare(g.displayName)), h = Object.keys(o.groups.checked).map((d) => o.groups.visibles.find(
3870
+ (A) => A.id === d
3871
+ )).filter((d) => d !== void 0).map((d) => {
3872
+ const g = this.getActionsAvailableFor(
3873
+ { id: d.id, type: "group" },
3874
+ o,
3875
+ a
3876
+ );
3877
+ return {
3878
+ id: d.id,
3879
+ type: "group",
3880
+ displayName: d.name,
3881
+ profile: void 0,
3882
+ avatarUrl: this.directory.getAvatarUrl(d.id, "group"),
3883
+ directoryUrl: this.directory.getDirectoryUrl(d.id, "group"),
3884
+ actions: g.map((f) => {
3885
+ const w = c[f];
3886
+ return {
3887
+ displayName: f,
3888
+ id: f,
3889
+ priority: w.priority
3890
+ };
3891
+ })
3892
+ };
3893
+ }).sort((d, g) => (d.displayName || "").localeCompare(g.displayName)), E = [...l, ...h], p = o.groups.visibles.map(
3894
+ ({ groupDisplayName: d, id: g, name: A, labels: f }) => ({
3895
+ labels: f,
3896
+ displayName: d || A,
3897
+ id: g
3898
+ })
3899
+ ), y = o.users.visibles.map(
3900
+ ({ id: d, profile: g, username: A, firstName: f, lastName: w, login: F }) => ({
3901
+ displayName: A,
3902
+ firstName: f,
3903
+ lastName: w,
3904
+ login: F,
3905
+ profile: g,
3906
+ id: d
3894
3907
  })
3895
3908
  );
3909
+ return {
3910
+ rights: E,
3911
+ visibleBookmarks: r,
3912
+ visibleGroups: p,
3913
+ visibleUsers: y
3914
+ };
3896
3915
  }
3897
- }
3898
- class HomeworksBehaviour extends AbstractBehaviourService {
3899
- constructor() {
3900
- super(...arguments);
3901
- u(this, "APP", "homeworks");
3902
- u(this, "RESOURCE", "homeworks");
3903
- }
3904
- async loadResources() {
3905
- return (await this.httpGet("/homeworks/list")).filter((t) => t.owner && t.trashed === 0).map((t) => this.dataToResource({
3906
- title: t.title,
3907
- ownerName: t.owner.displayName,
3908
- owner: t.owner.userId,
3909
- icon: t.thumbnail || "/img/illustrations/homeworks.svg",
3910
- path: "/homeworks#/view-homeworks/" + t._id,
3911
- _id: "" + t._id,
3912
- shared: typeof t.shared < "u",
3913
- modified: t.modified
3914
- }));
3915
- }
3916
- }
3917
- class MagnetoBehaviour extends AbstractBehaviourService {
3918
- constructor() {
3919
- super(...arguments);
3920
- u(this, "APP", "magneto");
3921
- u(this, "RESOURCE", "magneto");
3916
+ async getPutSharePayload(e, t, s) {
3917
+ const r = {
3918
+ users: {},
3919
+ groups: {},
3920
+ bookmarks: {}
3921
+ }, i = await this.getShareMapping(e, s);
3922
+ for (const o of t) {
3923
+ const a = o.actions.map((l) => i[l.id]).reduce((l, h) => Array.isArray(h) ? [...l, ...h] : l, []), c = [...new Set(a)];
3924
+ c.length > 0 && (o.type === "user" ? r.users[o.id] = c : o.type === "group" ? r.groups[o.id] = c : r.bookmarks[o.id] = c);
3925
+ }
3926
+ return r;
3922
3927
  }
3923
- async loadResources() {
3924
- const { all: t } = await this.httpGet(
3925
- "/magneto/boards/editable"
3928
+ async saveRights(e, t, s, r) {
3929
+ const i = await this.getPutSharePayload(
3930
+ e,
3931
+ s,
3932
+ r == null ? void 0 : r.getShareMapping
3933
+ ), o = (r == null ? void 0 : r.saveResourceRights) || `/${e}/share/resource/${t}`, a = this.getSearchUrl(
3934
+ e,
3935
+ t,
3936
+ "",
3937
+ r == null ? void 0 : r.getResourceRights
3926
3938
  );
3927
- return t.map((s) => this.dataToResource({
3928
- _id: s._id,
3929
- title: s.title,
3930
- icon: s.imageUrl,
3931
- owner: s.ownerId,
3932
- ownerName: s.ownerName,
3933
- path: `/magneto#/board/${s._id}/view`,
3934
- shared: !!(s.shared && s.shared.length >= 0),
3935
- modified: "" + s.modificationDate
3936
- }));
3937
- }
3938
- }
3939
- class MindmapBehaviour extends AbstractBehaviourService {
3940
- constructor() {
3941
- super(...arguments);
3942
- u(this, "APP", "mindmap");
3943
- u(this, "RESOURCE", "mindmap");
3939
+ return this.cache.clearCache(a), await this.http.putJson(o, i);
3944
3940
  }
3945
- async loadResources() {
3946
- return (await this.httpGet("/mindmap/list/all")).map(
3947
- (s) => this.dataToResource({
3948
- title: s.name,
3949
- ownerName: s.owner.displayName,
3950
- owner: s.owner.userId,
3951
- icon: s.thumbnail || "/img/illustrations/mindmap-default.png",
3952
- path: "/mindmap#/view/" + s._id,
3953
- _id: s._id,
3954
- shared: !!(s.shared && s.shared.length >= 0),
3955
- modified: s.modified
3956
- })
3957
- );
3941
+ async getActionsForApp(e, t) {
3942
+ const s = await this.cache.httpGetJson(
3943
+ "/infra/public/json/sharing-rights.json"
3944
+ ), r = await this.getShareMapping(e, t);
3945
+ return Object.keys(s).map((o) => {
3946
+ const a = s[o];
3947
+ return {
3948
+ displayName: o,
3949
+ id: o,
3950
+ priority: a.priority,
3951
+ requires: a.requires
3952
+ };
3953
+ }).filter((o) => {
3954
+ var a;
3955
+ return ((a = r[o.id]) == null ? void 0 : a.length) > 0;
3956
+ }).sort((o, a) => o.priority - a.priority);
3958
3957
  }
3959
3958
  }
3960
- class PagesBehaviour extends AbstractBehaviourService {
3961
- constructor() {
3962
- super(...arguments);
3963
- u(this, "APP", "pages");
3964
- u(this, "RESOURCE", "pages");
3965
- }
3966
- async loadResources() {
3967
- const t = await this.httpGet("/pages/list/all"), s = [];
3968
- return t.forEach((r) => {
3969
- var o;
3970
- const i = r.thumbnail ? r.thumbnail + "?thumbnail=48x48" : "/img/illustrations/pages.svg";
3971
- s.push(
3972
- this.dataToResource({
3973
- title: r.title,
3974
- owner: r.owner.userId,
3975
- ownerName: r.owner.displayName,
3976
- icon: i,
3977
- path: "/pages#/website/" + r._id,
3978
- _id: r._id,
3979
- shared: typeof r.shared < "u",
3980
- modified: r.modified
3981
- })
3982
- ), (o = r.pages) == null || o.forEach((a) => {
3983
- s.push(
3984
- this.dataToResource({
3985
- title: a.title,
3986
- owner: r.owner.userId,
3987
- ownerName: r.owner.displayName,
3988
- icon: i,
3989
- path: "/pages#/website/" + r._id + "/" + a.titleLink,
3990
- _id: r._id + "/" + a.titleLink,
3991
- shared: typeof r.shared < "u",
3992
- modified: r.modified
3993
- })
3994
- );
3995
- });
3996
- }), s;
3959
+ const loadedScripts = {};
3960
+ class HttpService {
3961
+ constructor(e, t) {
3962
+ // Axios automatically manages the XSRF-TOKEN cookie and the X-XSRF-TOKEN HTTP header.
3963
+ u(this, "axios");
3964
+ u(this, "baseUrl");
3965
+ u(this, "headers", {});
3966
+ u(this, "_latestResponse");
3967
+ this.context = e, this.axios = axios.create(t);
3997
3968
  }
3998
- }
3999
- class PollBehaviour extends AbstractBehaviourService {
4000
- constructor() {
4001
- super(...arguments);
4002
- u(this, "APP", "poll");
4003
- u(this, "RESOURCE", "poll");
3969
+ fixBaseUrl(e) {
3970
+ return e.startsWith("http://") || e.startsWith("https://") ? e : this.baseUrl ? this.baseUrl.endsWith("/") || e.startsWith("/") ? `${this.baseUrl}${e}` : `${this.baseUrl}/${e}` : e;
4004
3971
  }
4005
- async loadResources() {
4006
- return (await this.httpGet("/poll/list/all")).map((s) => {
4007
- const r = s.icon ? s.icon + "?thumbnail=48x48" : "/img/icons/glyphicons_036_file.png";
4008
- return this.dataToResource({
4009
- title: s.question,
4010
- ownerName: s.owner.displayName,
4011
- icon: r,
4012
- path: "/poll#/view/" + s._id,
4013
- _id: s._id,
4014
- owner: s.owner.userId,
4015
- shared: !!(s.shared && s.shared.length >= 0),
4016
- modified: s.modified
4017
- });
4018
- });
3972
+ useBaseUrl(e) {
3973
+ return this.baseUrl = e, this;
4019
3974
  }
4020
- }
4021
- class ScrapbookBehaviour extends AbstractBehaviourService {
4022
- constructor() {
4023
- super(...arguments);
4024
- u(this, "APP", "scrapbook");
4025
- u(this, "RESOURCE", "scrapbook");
3975
+ useHeaders(e) {
3976
+ return this.headers = e, this;
4026
3977
  }
4027
- async loadResources() {
4028
- return (await this.httpGet(
4029
- "/scrapbook/list/all"
4030
- )).map((s) => {
4031
- const r = s.icon || "/img/illustrations/scrapbook.svg";
4032
- return this.dataToResource({
4033
- title: s.name,
4034
- owner: s.owner.userId,
4035
- ownerName: s.owner.displayName,
4036
- icon: r,
4037
- path: "/scrapbook#/view-scrapbook/" + s._id,
4038
- _id: s._id,
4039
- shared: !!(s.shared && s.shared.length >= 0),
4040
- modified: s.modified
4041
- });
3978
+ setCdn(e) {
3979
+ e && XMLHttpRequest && !XMLHttpRequest.prototype.cdnUrl && (XMLHttpRequest.prototype.cdnUrl = e, XMLHttpRequest.prototype.baseOpen = XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.open = function() {
3980
+ const t = arguments[1];
3981
+ return t.startsWith("/infra/public") && (arguments[1] = e + t), /^\/([^\/]*)\/public/.test(t) && (arguments[1] = e + t), t.startsWith("/assets") && (arguments[1] = e + t), t == "/conf/public" && (arguments[1] = t), t.startsWith("http") && (arguments[1] = t), this.baseOpen.apply(this, arguments);
4042
3982
  });
4043
3983
  }
4044
- }
4045
- class TimelinegeneratorBehaviour extends AbstractBehaviourService {
4046
- constructor() {
4047
- super(...arguments);
4048
- u(this, "APP", "timelinegenerator");
4049
- u(this, "RESOURCE", "timelinegenerator");
4050
- }
4051
- loadResources() {
4052
- return new Promise(async (t, s) => {
4053
- try {
4054
- const i = (await this.httpGet(
4055
- "/timelinegenerator/timelines"
4056
- )).map((o) => {
4057
- const a = o.icon || "/img/illustrations/timeline-default.png";
4058
- return this.dataToResource({
4059
- title: o.headline,
4060
- ownerName: o.owner.displayName,
4061
- owner: o.owner.userId,
4062
- icon: a,
4063
- path: "/timelinegenerator#/view/" + o._id,
4064
- _id: o._id,
4065
- shared: typeof o.shared < "u",
4066
- modified: o.modified
4067
- });
4068
- });
4069
- t(i);
4070
- } catch (r) {
4071
- s(r);
3984
+ // private toAxiosConfig(params?: IHttpParams): AxiosRequestConfig {
3985
+ toAxiosConfig(e) {
3986
+ if (e) {
3987
+ const t = Object.assign({}, this.axios.defaults);
3988
+ e.headers && (t.headers = Object.assign({}, this.axios.defaults.headers), Object.assign(t.headers, e.headers)), e.responseType && (t.responseType = e.responseType), e.queryParams && (t.params = Object.assign({}, e.queryParams));
3989
+ const s = t.headers ?? {};
3990
+ return t.headers = { ...s, ...this.headers }, t;
3991
+ } else
3992
+ return this.axios.defaults;
3993
+ }
3994
+ toCdnUrl(e) {
3995
+ e = this.fixBaseUrl(e);
3996
+ const t = this.context.conf().getCdnUrl() || "";
3997
+ if (t.length > 0 && e !== "/conf/public") {
3998
+ const s = "" + e;
3999
+ (s.startsWith("/infra/public") || s.startsWith("/assets") || /^\/([^\/]*)\/public/.test(s)) && (e = t + s);
4000
+ }
4001
+ return e;
4002
+ }
4003
+ mapAxiosError(e, t) {
4004
+ e.response ? this._latestResponse = e.response : e.request ? this._latestResponse = {
4005
+ status: 408,
4006
+ statusText: ERROR_CODE.TIME_OUT
4007
+ } : this._latestResponse = {
4008
+ status: 500,
4009
+ statusText: ERROR_CODE.UNKNOWN
4010
+ };
4011
+ const { status: s, statusText: r, headers: i, data: o } = this._latestResponse;
4012
+ return t != null && t.disableNotifications || notify.events().publish(LAYER_NAME.TRANSPORT, {
4013
+ name: EVENT_NAME.ERROR_OCCURED,
4014
+ data: {
4015
+ params: t,
4016
+ response: { status: s, statusText: r, headers: i },
4017
+ payload: o
4072
4018
  }
4073
- });
4019
+ }), o;
4074
4020
  }
4075
- }
4076
- class WikiBehaviour extends AbstractBehaviourService {
4077
- constructor() {
4078
- super(...arguments);
4079
- u(this, "APP", "wiki");
4080
- u(this, "RESOURCE", "wiki");
4021
+ mapAxiosResponse(e, t) {
4022
+ return this._latestResponse = e, e.data;
4081
4023
  }
4082
- async loadResources() {
4083
- return (await this.httpGet(
4084
- "/wiki/listallpages?visible=true"
4085
- )).map((s) => s.pages.map((r) => {
4086
- let i;
4087
- return typeof s.thumbnail > "u" || s.thumbnail === "" ? i = "/img/icons/glyphicons_036_file.png" : i = s.thumbnail + "?thumbnail=48x48", this.dataToResource({
4088
- title: r.title + " [" + s.title + "]",
4089
- ownerName: s.owner.displayName,
4090
- owner: s.owner.userId,
4091
- icon: i,
4092
- path: "/wiki#/view/" + s._id + "/" + r._id,
4093
- _id: `${s._id}#${r._id}`,
4094
- shared: typeof s.shared < "u",
4095
- modified: r.modified
4096
- });
4097
- })).flat();
4024
+ get latestResponse() {
4025
+ return this._latestResponse;
4098
4026
  }
4099
- }
4100
- class WorkspaceBehaviour extends AbstractBehaviourService {
4101
- constructor() {
4102
- super(...arguments);
4103
- u(this, "APP", "workspace");
4104
- u(this, "RESOURCE", "workspace");
4027
+ isResponseError() {
4028
+ return this.latestResponse.status < 200 || this.latestResponse.status >= 300;
4105
4029
  }
4106
- loadResources({ search: t, asset_id: s }) {
4107
- return new Promise(async (r, i) => {
4108
- try {
4109
- let o = "/workspace/documents?filter=all&hierarchical=true";
4110
- s && s.length ? o += `&search=${t}` : t && t.length && (o += `&search=${t}`);
4111
- const c = (await this.httpGet(o)).filter((l) => !l.deleted).map((l) => {
4112
- const p = l.metadata["content-type"] && l.metadata["content-type"].indexOf("image") !== -1 ? `/workspace/document/${l._id}?thumbnail=120x120` : "/img/icons/unknown-large.png";
4113
- return this.dataToResource({
4114
- title: l.name,
4115
- ownerName: l.ownerName,
4116
- owner: l.owner,
4117
- icon: p,
4118
- path: `/workspace/document/${l._id}`,
4119
- _id: l._id,
4120
- shared: !!(l.shared && l.shared.length >= 0),
4121
- modified: l.modified
4122
- });
4123
- });
4124
- r(c);
4125
- } catch (o) {
4126
- i(o);
4127
- }
4128
- });
4030
+ async get(e, t) {
4031
+ try {
4032
+ const s = await this.axios.get(
4033
+ this.toCdnUrl(e),
4034
+ this.toAxiosConfig(t)
4035
+ );
4036
+ return this.mapAxiosResponse(s, t);
4037
+ } catch (s) {
4038
+ throw this.mapAxiosError(s, t);
4039
+ }
4129
4040
  }
4130
- }
4131
- const b = class b {
4132
- static async initialize(e, t) {
4133
- const s = e.http();
4134
- if (!this.resourceProducingApps.length) {
4135
- this.resourceProducingApps = [t, "workspace"];
4136
- try {
4137
- const [r, i] = await Promise.all([
4138
- s.get("/resources-applications"),
4139
- e.session().getUser()
4140
- ]);
4141
- i != null && i.apps && (r != null && r.length) && (this.resourceProducingApps = r.filter(
4142
- (o) => i.apps.some((a) => a.address.includes(o))
4143
- ));
4144
- } catch (r) {
4145
- console.warn("Failed to load resource-producing apps:", r);
4146
- }
4041
+ async post(e, t, s) {
4042
+ try {
4043
+ const r = await this.axios.post(
4044
+ this.fixBaseUrl(e),
4045
+ t,
4046
+ this.toAxiosConfig(s)
4047
+ );
4048
+ return this.mapAxiosResponse(r, s);
4049
+ } catch (r) {
4050
+ throw this.mapAxiosError(r, s);
4147
4051
  }
4148
- return this.resourceProducingApps;
4149
4052
  }
4150
- static registerCustomBehaviour(e, t, s) {
4151
- this.registry.register({ application: e, resourceType: t }, s);
4053
+ async postFile(e, t, s) {
4054
+ const r = this.toAxiosConfig(s);
4055
+ r.headers && r.headers["Content-Type"] && delete r.headers["Content-Type"];
4056
+ try {
4057
+ const i = await this.axios.post(this.fixBaseUrl(e), t, {
4058
+ ...r,
4059
+ headers: {
4060
+ "Content-Type": "multipart/form-data"
4061
+ }
4062
+ });
4063
+ return this.mapAxiosResponse(i, s);
4064
+ } catch (i) {
4065
+ throw this.mapAxiosError(i, s);
4066
+ }
4152
4067
  }
4153
- static async registerBehaviours(e) {
4154
- this.resourceProducingApps.forEach((t) => {
4155
- const s = { application: e, resourceType: t };
4156
- this.registry.register(
4157
- s,
4158
- (r) => this.serviceFor(r, e, t)
4068
+ async postJson(e, t, s) {
4069
+ const r = this.toAxiosConfig();
4070
+ r.headers && (r.headers["Content-Type"] = "application/json");
4071
+ try {
4072
+ const i = await this.axios.post(
4073
+ this.fixBaseUrl(e),
4074
+ t,
4075
+ this.toAxiosConfig(s)
4159
4076
  );
4160
- });
4077
+ return this.mapAxiosResponse(i, s);
4078
+ } catch (i) {
4079
+ throw this.mapAxiosError(i, s);
4080
+ }
4161
4081
  }
4162
- static serviceFor(e, t, s) {
4163
- let r;
4164
- switch (s) {
4165
- case "timelinegenerator":
4166
- r = new TimelinegeneratorBehaviour(e);
4167
- break;
4168
- case "workspace":
4169
- r = new WorkspaceBehaviour(e);
4170
- break;
4171
- case "blog":
4172
- r = new BlogBehaviour(e);
4173
- break;
4174
- case "actualites":
4175
- r = new ActualitesBehaviour(e);
4176
- break;
4177
- case "wiki":
4178
- r = new WikiBehaviour(e);
4179
- break;
4180
- case "pages":
4181
- r = new PagesBehaviour(e);
4182
- break;
4183
- case "poll":
4184
- r = new PollBehaviour(e);
4185
- break;
4186
- case "community":
4187
- r = new CommunityBehaviour(e);
4188
- break;
4189
- case "mindmap":
4190
- r = new MindmapBehaviour(e);
4191
- break;
4192
- case "forum":
4193
- r = new ForumBehaviour(e);
4194
- break;
4195
- case "homeworks":
4196
- r = new HomeworksBehaviour(e);
4197
- break;
4198
- case "scrapbook":
4199
- r = new ScrapbookBehaviour(e);
4200
- break;
4201
- case "collaborativewall":
4202
- r = new CollaborativewallBehaviour(e);
4203
- break;
4204
- case "exercizer":
4205
- r = new ExercizerBehaviour(e);
4206
- break;
4207
- case "formulaire":
4208
- r = new FormulaireBehaviour(e);
4209
- break;
4210
- case "magneto":
4211
- r = new MagnetoBehaviour(e);
4212
- break;
4213
- case "appointments":
4214
- r = new AppointmentsBehaviour(e);
4215
- break;
4216
- default:
4217
- throw ERROR_CODE.NOT_SUPPORTED;
4082
+ async put(e, t, s) {
4083
+ try {
4084
+ const r = await this.axios.put(
4085
+ this.fixBaseUrl(e),
4086
+ t,
4087
+ this.toAxiosConfig(s)
4088
+ );
4089
+ return this.mapAxiosResponse(r, s);
4090
+ } catch (r) {
4091
+ throw this.mapAxiosError(r, s);
4218
4092
  }
4219
- return r.APP = t, r;
4220
4093
  }
4221
- };
4222
- //
4223
- // STATIC REGISTRY
4224
- //
4225
- u(b, "registry", new ServiceRegistry()), // Expose some useful functions
4226
- u(b, "findBehaviour", b.registry.findService.bind(b.registry)), u(b, "hasBehaviour", b.registry.isRegistered.bind(b.registry)), u(b, "resourceProducingApps", []);
4227
- let SnipletsService = b;
4228
- const SEND_ALL = "*";
4229
- class WebBroker {
4230
- constructor(e) {
4231
- u(this, "subscription");
4232
- this.odeServices = e;
4094
+ async putFile(e, t, s) {
4095
+ try {
4096
+ const r = this.toAxiosConfig(s);
4097
+ r.headers && r.headers["Content-Type"] && delete r.headers["Content-Type"];
4098
+ const i = await this.axios.put(this.fixBaseUrl(e), t, {
4099
+ ...r,
4100
+ headers: {
4101
+ "Content-Type": "multipart/form-data"
4102
+ }
4103
+ });
4104
+ return this.mapAxiosResponse(i, s);
4105
+ } catch (r) {
4106
+ throw this.mapAxiosError(r, s);
4107
+ }
4233
4108
  }
4234
- get http() {
4235
- return this.odeServices.http();
4109
+ async putJson(e, t, s) {
4110
+ const r = this.toAxiosConfig(s);
4111
+ r.headers && (r.headers["Content-Type"] = "application/json");
4112
+ try {
4113
+ const i = await this.axios.put(this.fixBaseUrl(e), t, r);
4114
+ return this.mapAxiosResponse(i, s);
4115
+ } catch (i) {
4116
+ throw this.mapAxiosError(i, s);
4117
+ }
4236
4118
  }
4237
- get events() {
4238
- return this.odeServices.notify().events();
4119
+ async patch(e, t, s) {
4120
+ try {
4121
+ const r = await this.axios.patch(
4122
+ this.fixBaseUrl(e),
4123
+ t,
4124
+ this.toAxiosConfig(s)
4125
+ );
4126
+ return this.mapAxiosResponse(r, s);
4127
+ } catch (r) {
4128
+ throw this.mapAxiosError(r, s);
4129
+ }
4239
4130
  }
4240
- dispatchEvent(e, t) {
4241
- t.findIndex(
4242
- (r) => SEND_ALL === r || e.data["event-type"] === r
4243
- ) >= 0 && this.http.post("/infra/event/web/store", e.data, {
4244
- disableNotifications: !0
4245
- });
4131
+ async patchFile(e, t, s) {
4132
+ try {
4133
+ const r = this.toAxiosConfig(s);
4134
+ r.headers && r.headers["Content-Type"] && delete r.headers["Content-Type"];
4135
+ const i = await this.axios.patch(this.fixBaseUrl(e), t, {
4136
+ ...r,
4137
+ headers: {
4138
+ "Content-Type": "multipart/form-data"
4139
+ }
4140
+ });
4141
+ return this.mapAxiosResponse(i, s);
4142
+ } catch (r) {
4143
+ throw this.mapAxiosError(r, s);
4144
+ }
4246
4145
  }
4247
- initialize(e) {
4248
- if (e === void 0 || e.send === void 0 || e.send.length > 0) {
4249
- const t = (e == null ? void 0 : e.send) ?? [SEND_ALL];
4250
- this.subscription = this.events.subscribe(
4251
- LAYER_NAME.WEB_DATA,
4252
- (s) => this.dispatchEvent(s, t)
4146
+ async patchJson(e, t, s) {
4147
+ const r = this.toAxiosConfig(s);
4148
+ r.headers && (r.headers["Content-Type"] = "application/json");
4149
+ try {
4150
+ const i = await this.axios.patch(this.fixBaseUrl(e), t, r);
4151
+ return this.mapAxiosResponse(i, s);
4152
+ } catch (i) {
4153
+ throw this.mapAxiosError(i, s);
4154
+ }
4155
+ }
4156
+ async delete(e, t) {
4157
+ try {
4158
+ const s = await this.axios.delete(
4159
+ this.fixBaseUrl(e),
4160
+ this.toAxiosConfig(t)
4253
4161
  );
4162
+ return this.mapAxiosResponse(s, t);
4163
+ } catch (s) {
4164
+ throw this.mapAxiosError(s, t);
4254
4165
  }
4255
- return this;
4256
4166
  }
4257
- destroy() {
4258
- this.subscription && (this.subscription.revoke(), delete this.subscription);
4167
+ async deleteJson(e, t) {
4168
+ try {
4169
+ const s = await this.axios.delete(this.fixBaseUrl(e), {
4170
+ data: t
4171
+ });
4172
+ return this.mapAxiosResponse(s);
4173
+ } catch (s) {
4174
+ throw this.mapAxiosError(s);
4175
+ }
4176
+ }
4177
+ getScript(e, t, s) {
4178
+ const r = s ?? "exports", i = this.toAxiosConfig(t);
4179
+ return i.headers && (i.headers.Accept = "application/javascript"), this.axios.get(this.toCdnUrl(e), i).then((o) => this.mapAxiosResponse(o, t)).then((o) => {
4180
+ try {
4181
+ const a = `"use strict";var ${r.split(".")[0]}={};${o};return ${r};`;
4182
+ return Function(a)();
4183
+ } catch {
4184
+ return o;
4185
+ }
4186
+ }).catch((o) => {
4187
+ throw this.mapAxiosError(o, t), o;
4188
+ });
4189
+ }
4190
+ loadScript(e, t) {
4191
+ return loadedScripts[e] ? Promise.resolve() : this.getScript(e, t).then((s) => {
4192
+ loadedScripts[e] = !0;
4193
+ });
4259
4194
  }
4260
4195
  }
4261
- class DataService {
4196
+ const R = class R {
4197
+ // in minutes. Applies to recorded videos.
4262
4198
  constructor(e) {
4263
- u(this, "_webBroker");
4264
- u(this, "app");
4265
- u(this, "user");
4266
- u(this, "profile");
4267
- this.odeServices = e;
4199
+ this.context = e;
4200
+ }
4201
+ get http() {
4202
+ return this.context.http();
4268
4203
  }
4269
4204
  get conf() {
4270
- return this.odeServices.conf();
4205
+ return this.context.conf();
4271
4206
  }
4272
- get notify() {
4273
- return this.odeServices.notify();
4207
+ /**
4208
+ * Returns the video app public conf (maxWeight, maxDuration and accepted extensions)
4209
+ * @returns the Video app public conf
4210
+ */
4211
+ async getVideoConf() {
4212
+ var t;
4213
+ const e = await this.conf.getPublicConf(
4214
+ APP$4.VIDEO
4215
+ );
4216
+ return {
4217
+ maxWeight: (e == null ? void 0 : e["max-videosize-mbytes"]) ?? R.MAX_WEIGHT,
4218
+ maxDuration: (e == null ? void 0 : e["max-videoduration-minutes"]) ?? R.MAX_DURATION,
4219
+ acceptVideoUploadExtensions: ((t = e == null ? void 0 : e["accept-videoupload-extensions"]) == null ? void 0 : t.map(
4220
+ (s) => s.toUpperCase()
4221
+ )) ?? []
4222
+ };
4274
4223
  }
4275
- // This method is called once, by the service container.
4276
- async initialize() {
4277
- try {
4278
- const { app: e } = await this.notify.onAppConfReady().promise;
4279
- this.app = e, this.user = await this.odeServices.session().getUser(), this.profile = await this.odeServices.session().getUserProfile();
4280
- const { ["data-service"]: t } = await this.conf.getPublicConf(e);
4281
- this._webBroker = new WebBroker(this.odeServices).initialize(t == null ? void 0 : t.web);
4282
- } catch {
4283
- console.log("DataService not initialized, usage data unavailable.");
4224
+ /**
4225
+ * Starts the encoding process and check when video is fully processed.
4226
+ * @param params cf VideoUploadParams
4227
+ * @returns a VideoCheckResponse
4228
+ */
4229
+ async upload({
4230
+ data: e,
4231
+ appCode: t,
4232
+ captation: s,
4233
+ duration: r
4234
+ }) {
4235
+ if (!e.file)
4236
+ throw new Error("Invalid video file.");
4237
+ if (!e.filename)
4238
+ throw new Error("Invalid video filename");
4239
+ const i = `${e.browser.name} ${e.browser.version}`, o = new FormData();
4240
+ o.append("device", e.device || ""), o.append("browser", i), o.append("url", e.url), o.append("app", t), o.append("file", e.file, e.filename), o.append("weight", "" + e.file.size), o.append("captation", "" + s);
4241
+ let a = `/video/encode?captation=${s}`;
4242
+ r && (a += `&duration=${r}`);
4243
+ const c = await this.http.post(
4244
+ a,
4245
+ o,
4246
+ { headers: { "Content-Type": "multipart/form-data" } }
4247
+ );
4248
+ if (c.state == "running") {
4249
+ let l = 0, h = 1;
4250
+ do {
4251
+ const E = h + l;
4252
+ await new Promise(
4253
+ (y) => setTimeout(y, E * 1e3)
4254
+ ), l = h, h = Math.min(8, E);
4255
+ const p = await this.http.get(
4256
+ `/video/status/${c.processid}`
4257
+ );
4258
+ if (p.state == "succeed")
4259
+ return p.videoworkspaceid && p.videosize && this.context.data().trackVideoSave(
4260
+ p.videoworkspaceid,
4261
+ Math.round(r),
4262
+ p.videosize,
4263
+ s,
4264
+ e.url,
4265
+ i,
4266
+ e.device
4267
+ ), p;
4268
+ if (p.state == "error")
4269
+ break;
4270
+ } while (!0);
4284
4271
  }
4272
+ throw new Error("Video cannot be uploaded.");
4285
4273
  }
4286
- //FIXME When to call that ??
4287
- predestroy() {
4288
- this._webBroker && (this._webBroker.destroy(), delete this._webBroker);
4274
+ };
4275
+ u(R, "MAX_WEIGHT", 50), // in Mbytes. Applies to uploaded videos.
4276
+ u(R, "MAX_DURATION", 3);
4277
+ let VideoService = R;
4278
+ class WidgetService {
4279
+ constructor(e) {
4280
+ this.context = e;
4289
4281
  }
4290
- /** Send a web-user-level event to the data pipeline. */
4291
- trackWebEvent(e) {
4292
- this.notify.events().publish(LAYER_NAME.WEB_DATA, {
4293
- name: EVENT_NAME.DATA_TRACKED,
4294
- data: e
4295
- });
4282
+ get session() {
4283
+ return this.context.session();
4296
4284
  }
4297
- addUserInfos(e) {
4298
- return this.user && (e.userId = this.user.userId, e.structure = this.user.structureNames[0]), this.profile && (e.profil = this.profile[0]), e;
4285
+ async getSystemWidgets() {
4286
+ try {
4287
+ const e = await this.session.getUser();
4288
+ return e == null ? void 0 : e.widgets;
4289
+ } catch (e) {
4290
+ throw console.error("[WidgetService] getSystemWidgets failed", e), e;
4291
+ }
4299
4292
  }
4300
- trackVideoSave(e, t, s, r, i, o, a) {
4301
- const c = this.addUserInfos({
4302
- "event-type": "VIDEO_SAVE",
4303
- module: this.app || "video",
4304
- video_id: e,
4305
- browser: o,
4306
- duration: Math.round(t),
4307
- weight: s,
4308
- source: r ? "CAPTURED" : "UPLOADED",
4309
- url: i
4310
- });
4311
- a && (c.device_type = a), this.trackWebEvent(c);
4293
+ async getPreferences() {
4294
+ return await this.context.conf().getPreference("widgets");
4312
4295
  }
4313
- trackVideoRead(e, t, s, r, i) {
4314
- const o = this.addUserInfos({
4315
- "event-type": "VIDEO_READ",
4316
- module: "video",
4317
- video_id: e,
4318
- browser: r,
4319
- source: t ? "CAPTURED" : "UPLOADED",
4320
- url: s
4321
- });
4322
- this.app && (o["override-module"] = this.app), i && (o.device_type = i), this.trackWebEvent(o);
4296
+ async setPreferences(e) {
4297
+ await this.context.conf().savePreference("widgets", e);
4323
4298
  }
4324
- trackSpeechAndText(e) {
4325
- const t = this.addUserInfos({
4326
- "event-type": "SPEECH_AND_TEXT",
4327
- function: e
4328
- });
4329
- this.app && (t.module = this.app), this.trackWebEvent(t);
4299
+ }
4300
+ const defaultMappers = {
4301
+ csv: function({ type: n, extension: e }) {
4302
+ return MimeTypeUtils.INSTANCE.isCsvLike(n, e);
4303
+ },
4304
+ doc: function({ type: n, extension: e }) {
4305
+ return MimeTypeUtils.INSTANCE.isWordLike(n, e) ? !0 : n.indexOf("document") !== -1 && n.indexOf("wordprocessing") !== -1;
4306
+ },
4307
+ xls: function({ type: n, extension: e }) {
4308
+ return MimeTypeUtils.INSTANCE.isExcelLike(n, e) ? !0 : n.indexOf("document") !== -1 && n.indexOf("spreadsheet") !== -1 || n.indexOf("ms-excel") !== -1;
4309
+ },
4310
+ img: function({ type: n }) {
4311
+ return n.indexOf("image") !== -1;
4312
+ },
4313
+ pdf: function({ type: n }) {
4314
+ return n.indexOf("pdf") !== -1 || n === "application/x-download";
4315
+ },
4316
+ ppt: function({ type: n, extension: e }) {
4317
+ return MimeTypeUtils.INSTANCE.isPowerpointLike(n, e) ? !0 : n.indexOf("document") !== -1 && n.indexOf("presentation") !== -1 || n.indexOf("powerpoint") !== -1;
4318
+ },
4319
+ txt: function({ type: n, extension: e }) {
4320
+ return MimeTypeUtils.INSTANCE.isTxtLike(n, e);
4321
+ },
4322
+ md: function({ type: n, extension: e }) {
4323
+ return MimeTypeUtils.INSTANCE.isMdLike(n, e);
4324
+ },
4325
+ video: function({ type: n }) {
4326
+ return n.indexOf("video") !== -1;
4327
+ },
4328
+ audio: function({ type: n }) {
4329
+ return n.indexOf("audio") !== -1;
4330
+ },
4331
+ zip: function({ type: n }) {
4332
+ return n.indexOf("zip") !== -1 || n.indexOf("rar") !== -1 || n.indexOf("tar") !== -1 || n.indexOf("7z") !== -1;
4330
4333
  }
4331
- trackAccessLibraryFromExplorer() {
4332
- const e = this.addUserInfos({
4333
- "event-type": "ACCESS_LIBRARY_FROM_EXPLORER"
4334
- });
4335
- this.app && (e.module = this.app), this.trackWebEvent(e);
4334
+ }, v = class v {
4335
+ /* Similar role notion as in infra-front > workspace > Model.ts */
4336
+ static getRole(e) {
4337
+ var t, s;
4338
+ return v.role(
4339
+ (t = e.metadata) == null ? void 0 : t["content-type"],
4340
+ !1,
4341
+ (s = e.metadata) == null ? void 0 : s.extension
4342
+ );
4336
4343
  }
4337
- }
4338
- class ReactionsService {
4339
- constructor(e, t, s) {
4340
- this.context = e, this.module = t, this.resourceType = s;
4344
+ /* Similar role notion as in infra-front > workspace > Model.ts */
4345
+ static role(e, t = !1, s) {
4346
+ if (s && (s = s.trim()), !e) return "unknown";
4347
+ this.roleMappers || console.warn("[DocumentHelper.role] should not have empty roles", this);
4348
+ const r = { type: e, previewRole: t, extension: s };
4349
+ for (const i of this.roleMappers) {
4350
+ const o = i(r);
4351
+ if (o)
4352
+ return o;
4353
+ }
4354
+ return "unknown";
4355
+ }
4356
+ };
4357
+ // FIXME add edumedia support
4358
+ u(v, "roleMappers", [
4359
+ (e) => Object.keys(defaultMappers).find((s) => defaultMappers[s](e))
4360
+ ]);
4361
+ let DocumentHelper = v;
4362
+ class WorkspaceService {
4363
+ constructor(e) {
4364
+ this.context = e;
4341
4365
  }
4342
4366
  get http() {
4343
4367
  return this.context.http();
4344
4368
  }
4345
- async loadAvailableReactions() {
4346
- try {
4347
- const { "reaction-types": e } = await this.context.conf().getPublicConf("audience");
4348
- return Array.isArray(e) ? e : void 0;
4349
- } catch {
4350
- console.error("Audience configuration not found");
4351
- return;
4352
- }
4353
- }
4354
- async loadReactionSummaries(e) {
4355
- const t = await this.http.get(
4356
- `/audience/reactions/${this.module}/${this.resourceType}?resourceIds=${e.join(",")}`
4357
- );
4358
- return this.http.isResponseError() ? {} : t.reactionsByResource;
4369
+ extractMetadata(e) {
4370
+ const t = e.name || "", s = t.split("."), r = e.type || "application/octet-stream", i = s.length > 1 ? s[s.length - 1] : "", o = {
4371
+ "content-type": r,
4372
+ filename: t,
4373
+ size: e.size,
4374
+ extension: i,
4375
+ role: DocumentHelper.role(r, !1, i)
4376
+ }, a = t.replace("." + o.extension, ""), c = o.extension ? a + "." + o.extension : a;
4377
+ return { basename: a, fullname: c, metadata: o };
4359
4378
  }
4360
- async loadReactionDetails(e, t, s) {
4361
- const r = await this.http.get(
4362
- `/audience/reactions/${this.module}/${this.resourceType}/${e}?page=${t}&size=${s}`
4379
+ async saveFile(e, t) {
4380
+ const { fullname: s, metadata: r } = this.extractMetadata(e), i = new FormData();
4381
+ i.append("file", e, s);
4382
+ const o = [];
4383
+ ((t == null ? void 0 : t.visibility) === "public" || (t == null ? void 0 : t.visibility) === "protected") && o.push(`${t.visibility}=true`), t != null && t.application && o.push(`application=${t.application}`), r.role === "img" && o.push("quality=1"), t != null && t.parentId && o.push(`parentId=${t.parentId}`);
4384
+ const a = await this.http.postFile(
4385
+ `/workspace/document?${o.join("&")}`,
4386
+ i
4363
4387
  );
4364
- return this.http.isResponseError() ? void 0 : r;
4388
+ if (this.http.isResponseError())
4389
+ throw this.http.latestResponse.statusText;
4390
+ return a;
4365
4391
  }
4366
- async deleteReaction(e) {
4367
- await this.http.delete(
4368
- `/audience/reactions/${this.module}/${this.resourceType}/${e}`
4392
+ async updateFile(e, t, s) {
4393
+ const { fullname: r, metadata: i } = this.extractMetadata(t), o = new FormData();
4394
+ o.append("file", t, r);
4395
+ const a = [];
4396
+ i.role === "img" && a.push("quality=1"), s != null && s.alt && a.push(`alt=${s.alt}`), s != null && s.legend && a.push(`legend=${s.legend}`), s != null && s.name && a.push(`name=${s.name}`);
4397
+ const c = await this.http.putFile(
4398
+ `/workspace/document/${e}?${a.join("&")}`,
4399
+ o
4369
4400
  );
4401
+ if (this.http.isResponseError())
4402
+ throw this.http.latestResponse.statusText;
4403
+ return c;
4370
4404
  }
4371
- async updateReaction(e, t) {
4372
- await this.http.putJson(
4373
- `/audience/reactions/${this.module}/${this.resourceType}`,
4374
- {
4375
- resourceId: e,
4376
- reactionType: t
4377
- }
4378
- );
4405
+ async deleteFile(e) {
4406
+ const t = e.map((s) => s._id);
4407
+ if (t.length == 0)
4408
+ Promise.resolve(null);
4409
+ else if (await this.http.deleteJson("/workspace/documents", {
4410
+ ids: t
4411
+ }), this.http.isResponseError())
4412
+ throw this.http.latestResponse.statusText;
4379
4413
  }
4380
- async createReaction(e, t) {
4381
- await this.http.postJson(
4382
- `/audience/reactions/${this.module}/${this.resourceType}`,
4383
- {
4384
- resourceId: e,
4385
- reactionType: t
4386
- }
4387
- );
4414
+ async acceptDocuments(e) {
4415
+ const t = await this.context.session().getUser();
4416
+ return (s) => s.deleted && s.trasher ? (t == null ? void 0 : t.userId) == s.trasher : !0;
4388
4417
  }
4389
- }
4390
- class ViewsService {
4391
- constructor(e, t, s) {
4392
- this.context = e, this.module = t, this.resourceType = s;
4418
+ async searchDocuments(e) {
4419
+ const t = e.filter !== "external" || e.parentId ? await this.http.get("/workspace/documents", {
4420
+ queryParams: { ...e, _: (/* @__PURE__ */ new Date()).getTime() }
4421
+ }) : [], s = await this.acceptDocuments(e);
4422
+ return t.filter(s);
4393
4423
  }
4394
- get http() {
4395
- return this.context.http();
4424
+ async listDocuments(e, t) {
4425
+ return this.searchDocuments({ filter: e, parentId: t, includeall: !0 });
4396
4426
  }
4397
- async getCounters(e) {
4398
- const t = await this.http.get(
4399
- `/audience/views/count/${this.module}/${this.resourceType}?resourceIds=${e.join(",")}`
4400
- );
4401
- return this.http.isResponseError() ? {} : t;
4427
+ /**
4428
+ * Duplicate and transfers documents if needed to a different folder with the specified application and visibility.
4429
+ * @param documents - The array of documents to transfer.
4430
+ * @param application - The application to associate with the transferred documents.
4431
+ * @param visibility - The visibility of the transferred documents. Defaults to "protected".
4432
+ * @returns A Promise that resolves to an array of transferred WorkspaceElements.
4433
+ */
4434
+ async transferDocuments(e, t, s = "protected") {
4435
+ const r = [];
4436
+ if (e.forEach((i) => {
4437
+ (s === "public" && !i.public || !i.public && !i.protected) && r.push(i);
4438
+ }), r.length > 0) {
4439
+ const i = await this.http.post(
4440
+ "/workspace/documents/transfer",
4441
+ {
4442
+ application: t,
4443
+ visibility: s,
4444
+ ids: r.map((o) => o._id)
4445
+ }
4446
+ );
4447
+ if (this.http.isResponseError())
4448
+ throw this.http.latestResponse.statusText;
4449
+ return r.forEach((o, a) => {
4450
+ const c = e.findIndex(
4451
+ (l) => l._id === o._id
4452
+ );
4453
+ 0 <= c && c < e.length && (e[c] = i[a]);
4454
+ }), e.filter((o) => !!o);
4455
+ }
4456
+ return e;
4402
4457
  }
4403
- async getDetails(e) {
4404
- const t = await this.http.get(
4405
- `/audience/views/details/${this.module}/${this.resourceType}/${e}`
4406
- );
4407
- return this.http.isResponseError() ? void 0 : t;
4458
+ /**
4459
+ * Get the URL of the thumbnail of a workspace element (or its URL),
4460
+ * or `null` if none exists or can be created.
4461
+ */
4462
+ getThumbnailUrl(e, t = 0, s = 0) {
4463
+ var i, o;
4464
+ const r = t > 0 || s > 0 ? `${t}x${s}` : "120x120";
4465
+ if (typeof e == "string")
4466
+ return e.includes("data:image") || e.includes("thumbnail") ? e : `${e}${e.includes("?") ? "&" : "?"}thumbnail=${r}`;
4467
+ {
4468
+ const a = `/workspace/${e.public ? "pub/" : ""}document/${e._id}?thumbnail=`, c = e.thumbnails;
4469
+ if ((o = (i = e.metadata) == null ? void 0 : i["content-type"]) != null && o.includes("video")) {
4470
+ const l = c && Object.keys(c).length > 0 ? Object.keys(c)[0] : null;
4471
+ return l ? a + l : null;
4472
+ } else
4473
+ return a + r;
4474
+ }
4408
4475
  }
4409
- trigger(e) {
4410
- return this.http.post(
4411
- `/audience/views/${this.module}/${this.resourceType}/${e}`
4412
- );
4476
+ /**
4477
+ * Get the URL of the file of a workspace element (or its URL),
4478
+ * or `null` if none exists or can be created.
4479
+ * @param filter - The filter to apply to the workspace element.
4480
+ * @param withChildren - If true, include all children folders.
4481
+ * @param parentId - The ID of the parent folder to list.
4482
+ * @param directShared - If true, include only elements directly shared with the user.
4483
+ *
4484
+ */
4485
+ listFolder(e, t = !1, s, r) {
4486
+ const i = {
4487
+ filter: e,
4488
+ hierarchical: t,
4489
+ parentId: s,
4490
+ directShared: r
4491
+ };
4492
+ return this.http.get("/workspace/folders/list", {
4493
+ queryParams: i
4494
+ });
4413
4495
  }
4414
- }
4415
- class AudienceService {
4416
- constructor(e, t, s) {
4417
- this.context = e, this.module = t, this.resourceType = s;
4496
+ /**
4497
+ * List all folders in the workspace.
4498
+ * @param withChildren - If true, include all children folders.
4499
+ * @param parentId - The ID of the parent folder to list.
4500
+ * @returns A promise that resolves to an array of WorkspaceElement objects.
4501
+ */
4502
+ listOwnerFolders(e, t) {
4503
+ return this.listFolder("owner", e, t);
4418
4504
  }
4419
- get views() {
4420
- return new ViewsService(this.context, this.module, this.resourceType);
4505
+ /**
4506
+ * List all shared folders in the workspace.
4507
+ * @param withChildren - If true, include all children folders.
4508
+ * @param parentId - The ID of the parent folder to list.
4509
+ * @returns A promise that resolves to an array of WorkspaceElement objects.
4510
+ */
4511
+ listSharedFolders(e, t) {
4512
+ return this.listFolder("shared", e, t, !0);
4421
4513
  }
4422
- get reactions() {
4423
- return new ReactionsService(this.context, this.module, this.resourceType);
4514
+ /**
4515
+ * Create a new folder in the workspace.
4516
+ * @param name - The name of the new folder.
4517
+ * @param parentId - The ID of the parent folder where the new folder will be created.
4518
+ * @returns void
4519
+ */
4520
+ createFolder(e, t) {
4521
+ const s = new FormData();
4522
+ return s.append("name", e), t && s.append("parentFolderId", t), this.http.postFile("/workspace/folder", s);
4424
4523
  }
4425
4524
  }
4426
4525
  class OdeServices {
@@ -4432,14 +4531,16 @@ class OdeServices {
4432
4531
  u(this, "_directory");
4433
4532
  u(this, "_http");
4434
4533
  u(this, "_idiom");
4534
+ u(this, "_nextcloud");
4435
4535
  u(this, "_notify");
4436
4536
  u(this, "_rights");
4437
4537
  u(this, "_session");
4438
4538
  u(this, "_share");
4439
4539
  u(this, "_video");
4540
+ u(this, "_widget");
4440
4541
  u(this, "_workspace");
4441
4542
  u(this, "_embedder");
4442
- this._analytics = new AnalyticsService(this), this._cache = new CacheService(this), this._conf = new ConfService(this), this._data = new DataService(this), this._directory = new DirectoryService(this), this._http = new HttpService(this), this._idiom = new IdiomService(this), this._notify = NotifyFrameworkFactory.instance(), this._rights = new RightService(this), this._session = new SessionService(this), this._share = new ShareService(this), this._video = new VideoService(this), this._workspace = new WorkspaceService(this), this._embedder = new EmbedderService(this);
4543
+ this._analytics = new AnalyticsService(this), this._cache = new CacheService(this), this._conf = new ConfService(this), this._data = new DataService(this), this._directory = new DirectoryService(this), this._http = new HttpService(this), this._idiom = new IdiomService(this), this._nextcloud = new NextcloudService(this), this._notify = NotifyFrameworkFactory.instance(), this._rights = new RightService(this), this._session = new SessionService(this), this._share = new ShareService(this), this._video = new VideoService(this), this._widget = new WidgetService(this), this._workspace = new WorkspaceService(this), this._embedder = new EmbedderService(this);
4443
4544
  }
4444
4545
  initialize() {
4445
4546
  return this._data.initialize(), this;
@@ -4468,6 +4569,9 @@ class OdeServices {
4468
4569
  idiom() {
4469
4570
  return this._idiom;
4470
4571
  }
4572
+ nextcloud() {
4573
+ return this._nextcloud;
4574
+ }
4471
4575
  notify() {
4472
4576
  return this._notify;
4473
4577
  }
@@ -4489,6 +4593,9 @@ class OdeServices {
4489
4593
  video() {
4490
4594
  return this._video;
4491
4595
  }
4596
+ widget() {
4597
+ return this._widget;
4598
+ }
4492
4599
  workspace() {
4493
4600
  return this._workspace;
4494
4601
  }
@@ -4689,17 +4796,17 @@ class WidgetFramework {
4689
4796
  var a;
4690
4797
  const i = ((a = r.find((c) => c.child === t.skin)) == null ? void 0 : a.parent) === "panda" ? secondLevelWidgets : firstLevelWidgets;
4691
4798
  this._widgets = this._widgets.filter((c, l) => {
4692
- const p = c.platformConf.name;
4693
- return i.indexOf(p) !== -1 ? !1 : (this._userPrefs[p] || (this._userPrefs[p] = {
4694
- index: defaultWidgetOrder[p] ?? 999,
4799
+ const h = c.platformConf.name;
4800
+ return i.indexOf(h) !== -1 ? !1 : (this._userPrefs[h] || (this._userPrefs[h] = {
4801
+ index: defaultWidgetOrder[h] ?? 999,
4695
4802
  show: !0,
4696
4803
  position: c.platformConf.position
4697
- }), c.platformConf.mandatory && (this._userPrefs[p].show = !0, this._userPrefs[p].index = defaultWidgetOrder[p] ?? 999), c.platformConf.i18n && s.push(c.platformConf.i18n), c.applyUserPref(this._userPrefs[p]), !0);
4804
+ }), c.platformConf.mandatory && (this._userPrefs[h].show = !0, this._userPrefs[h].index = defaultWidgetOrder[h] ?? 999), c.platformConf.i18n && s.push(c.platformConf.i18n), c.applyUserPref(this._userPrefs[h]), !0);
4698
4805
  });
4699
4806
  const o = new Idiom();
4700
4807
  this._widgets = this._widgets.sort((c, l) => {
4701
- const p = o.translate(`timeline.settings.${c.platformConf.name}`).toLowerCase(), E = o.translate(`timeline.settings.${l.platformConf.name}`).toLowerCase();
4702
- return p < E ? -1 : p > E ? 1 : 0;
4808
+ const h = o.translate(`timeline.settings.${c.platformConf.name}`).toLowerCase(), E = o.translate(`timeline.settings.${l.platformConf.name}`).toLowerCase();
4809
+ return h < E ? -1 : h > E ? 1 : 0;
4703
4810
  });
4704
4811
  });
4705
4812
  }
@@ -4724,22 +4831,7 @@ class Widget {
4724
4831
  this._userPref = e, this._userPref.position = this._userPref.position ?? widgets.lookupDefaultPosition(this._platformConf.name) ?? "left";
4725
4832
  }
4726
4833
  }
4727
- const widgets = new WidgetFramework();
4728
- class LastInfosWidget {
4729
- loadInfos(e) {
4730
- return transport.http.get("/actualites/infos/last/" + e);
4731
- }
4732
- getMaxResults() {
4733
- return transport.http.get("/userbook/preference/maxInfos").then((e) => e.preference ? parseInt(e.preference) : 4);
4734
- }
4735
- setMaxResults(e) {
4736
- return transport.http.putJson(
4737
- "/userbook/preference/maxInfos",
4738
- `"${e}"`
4739
- );
4740
- }
4741
- }
4742
- const WIDGET_NAME = {
4834
+ const widgets = new WidgetFramework(), WIDGET_NAME = {
4743
4835
  LAST_INFOS: "last-infos-widget",
4744
4836
  BIRTHDAY: "birthday",
4745
4837
  CALENDAR: "calendar-widget",
@@ -4776,7 +4868,6 @@ export {
4776
4868
  FOLDER,
4777
4869
  ITimelineFactory,
4778
4870
  LAYER_NAME,
4779
- LastInfosWidget,
4780
4871
  NotifyFrameworkFactory,
4781
4872
  ReactionTypes,
4782
4873
  ResourceService,