@edifice.io/client 2.5.23 → 2.5.24-develop.20260623184311

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,1710 @@ 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;
2934
- }
2935
- }
2936
- class ShareService {
2758
+ class AbstractBehaviourService {
2937
2759
  //
2938
2760
  // IMPLEMENTATION
2939
2761
  //
2940
2762
  constructor(e) {
2941
- this.context = e;
2763
+ //-----------------
2764
+ //--- Utilities ---
2765
+ //-----------------
2766
+ u(this, "_cache");
2767
+ this.context = e, this._cache = new CacheService(this.context);
2942
2768
  }
2943
- get directory() {
2944
- return this.context.directory();
2769
+ getApplication() {
2770
+ return this.APP;
2945
2771
  }
2946
- get http() {
2947
- return this.context.http();
2772
+ getResourceType() {
2773
+ return this.RESOURCE;
2948
2774
  }
2949
- get cache() {
2950
- return this.context.cache();
2775
+ httpGet(e, t) {
2776
+ return this._cache.httpGetJson(e, t);
2951
2777
  }
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}`;
2778
+ /* Utility to map data between linker model and search model. */
2779
+ dataToResource({
2780
+ modified: e,
2781
+ ...t
2782
+ }) {
2783
+ const s = typeof e == "string" ? e : e != null && e.$date ? "" + e.$date : "";
2784
+ return {
2785
+ application: this.RESOURCE,
2786
+ name: t.title,
2787
+ creatorId: t.owner,
2788
+ creatorName: t.ownerName,
2789
+ thumbnail: t.icon,
2790
+ assetId: t._id,
2791
+ modifiedAt: s,
2792
+ shared: t.shared,
2793
+ path: t.path
2794
+ };
2959
2795
  }
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];
2796
+ }
2797
+ class ActualitesBehaviour extends AbstractBehaviourService {
2798
+ constructor() {
2799
+ super(...arguments);
2800
+ u(this, "APP", "actualites");
2801
+ u(this, "RESOURCE", "actualites");
3000
2802
  }
3001
- async getShareMapping(e, t) {
3002
- const s = await this.cache.httpGetJson(
3003
- t || `/${e}/rights/sharing`
2803
+ async loadResources() {
2804
+ const [t, s] = await Promise.all([
2805
+ this.httpGet("/actualites/api/v1/infos/linker"),
2806
+ this.httpGet("/actualites/api/v1/threads")
2807
+ ]), r = s.reduce(
2808
+ (i, o) => i.set(o.id, o),
2809
+ /* @__PURE__ */ new Map()
3004
2810
  );
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
2811
+ return t.map((i) => {
2812
+ var a;
2813
+ let o;
2814
+ return i.threadIcon ? o = i.threadIcon + "?thumbnail=48x48" : o = "/img/icons/glyphicons_036_file.png", this.dataToResource({
2815
+ title: i.title + " [" + ((a = r.get(i.threadId)) == null ? void 0 : a.title) + "]",
2816
+ ownerName: i.owner.displayName,
2817
+ owner: i.owner.id,
2818
+ icon: o,
2819
+ path: "/actualites/threads/" + i.threadId + "?info=" + i.id,
2820
+ _id: `${i.threadId}#${i.id}`,
2821
+ shared: !!(i.shared && i.shared.length >= 0),
2822
+ modified: i.modified
2823
+ });
2824
+ });
2825
+ }
2826
+ }
2827
+ const hexToDataUrl = (n, e = 1, t = 1) => {
2828
+ const s = document.createElement("canvas");
2829
+ s.width = e, s.height = t;
2830
+ const r = s.getContext("2d");
2831
+ return r ? (r.fillStyle = n, r.fillRect(0, 0, e, t), s.toDataURL("image/png")) : "";
2832
+ };
2833
+ class AppointmentsBehaviour extends AbstractBehaviourService {
2834
+ constructor() {
2835
+ super(...arguments);
2836
+ u(this, "APP", "appointments");
2837
+ u(this, "RESOURCE", "appointments");
2838
+ }
2839
+ async loadResources() {
2840
+ return (await this.httpGet("/appointments/grids/linker")).map((s) => this.dataToResource({
2841
+ _id: s.id.toString(),
2842
+ icon: hexToDataUrl(s.color, 100, 100),
2843
+ title: s.name,
2844
+ ownerName: s.ownerName,
2845
+ owner: s.ownerId,
2846
+ path: `${window.location.origin}/appointments#?gridId=${s.id}`,
2847
+ shared: !1,
2848
+ modified: s.updatingDate
2849
+ }));
2850
+ }
2851
+ }
2852
+ class BlogBehaviour extends AbstractBehaviourService {
2853
+ constructor() {
2854
+ super(...arguments);
2855
+ u(this, "APP", "blog");
2856
+ u(this, "RESOURCE", "blog");
2857
+ }
2858
+ loadResources() {
2859
+ return new Promise(async (t, s) => {
2860
+ try {
2861
+ const r = await this.httpGet("/blog/linker"), i = [];
2862
+ r.forEach((o) => {
2863
+ o.thumbnail ? o.thumbnail = o.thumbnail + "?thumbnail=48x48" : o.thumbnail = "/img/illustrations/blog.svg";
2864
+ const a = o.fetchPosts.map((c) => this.dataToResource({
2865
+ owner: o.author.userId,
2866
+ ownerName: o.author.username,
2867
+ title: c.title + " [" + o.title + "]",
2868
+ _id: `${o._id}#${c._id}`,
2869
+ icon: o.thumbnail,
2870
+ path: `/blog/id/${o._id}/post/${c._id}`,
2871
+ shared: !!(o.shared && o.shared.length >= 0),
2872
+ modified: o.modified
2873
+ }));
2874
+ i.push(...a);
2875
+ }), t(i);
2876
+ } catch (r) {
2877
+ s(r);
2878
+ }
2879
+ });
2880
+ }
2881
+ }
2882
+ class CollaborativewallBehaviour extends AbstractBehaviourService {
2883
+ constructor() {
2884
+ super(...arguments);
2885
+ u(this, "APP", "collaborativewall");
2886
+ u(this, "RESOURCE", "collaborativewall");
2887
+ }
2888
+ async loadResources() {
2889
+ return (await this.httpGet(
2890
+ "/collaborativewall/list/all"
2891
+ )).map(
2892
+ (s) => this.dataToResource({
2893
+ title: s.name,
2894
+ ownerName: s.owner.displayName,
2895
+ owner: s.owner.userId,
2896
+ icon: s.icon ? s.icon : "/img/illustrations/collaborative-wall-default.png",
2897
+ path: "/collaborativewall#/view/" + s._id,
2898
+ _id: s._id,
2899
+ shared: !!(s.shared && s.shared.length >= 0),
2900
+ modified: s.modified
3095
2901
  })
3096
2902
  );
3097
- return {
3098
- rights: E,
3099
- visibleBookmarks: r,
3100
- visibleGroups: h,
3101
- visibleUsers: y
3102
- };
3103
2903
  }
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;
2904
+ }
2905
+ class CommunityBehaviour extends AbstractBehaviourService {
2906
+ constructor() {
2907
+ super(...arguments);
2908
+ u(this, "APP", "community");
2909
+ u(this, "RESOURCE", "community");
3115
2910
  }
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);
2911
+ async loadResources() {
2912
+ return (await this.httpGet(
2913
+ "/community/listallpages"
2914
+ )).map((s) => {
2915
+ let r;
2916
+ return typeof s.thumbnail > "u" || s.thumbnail === "" ? r = "/img/icons/glyphicons_036_file.png" : r = s.thumbnail + "?thumbnail=48x48", this.dataToResource({
2917
+ title: s.name,
2918
+ icon: r,
2919
+ path: "/community#/view/" + s.id,
2920
+ _id: s.id,
2921
+ owner: "",
2922
+ ownerName: "",
2923
+ shared: !!(s.shared && s.shared.length >= 0),
2924
+ modified: s.name
2925
+ // FIXME date ?
2926
+ });
2927
+ });
3128
2928
  }
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);
2929
+ }
2930
+ class ExercizerBehaviour extends AbstractBehaviourService {
2931
+ constructor() {
2932
+ super(...arguments);
2933
+ u(this, "APP", "exercizer");
2934
+ u(this, "RESOURCE", "exercizer");
2935
+ }
2936
+ async loadResources() {
2937
+ return (await this.httpGet(
2938
+ "/exercizer/subjects-scheduled"
2939
+ )).map((s) => {
2940
+ const r = s.picture ? s.picture + "?thumbnail=48x48" : "/img/illustrations/exercizer.svg";
2941
+ let i, o = !1;
2942
+ const a = JSON.parse(s.scheduled_at);
2943
+ 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({
2944
+ title: s.title,
2945
+ owner: s.owner,
2946
+ ownerName: i,
2947
+ icon: r,
2948
+ path: "/exercizer#/linker/" + s.id,
2949
+ _id: "" + s.id,
2950
+ shared: o,
2951
+ modified: s.modified
2952
+ });
2953
+ });
3145
2954
  }
3146
2955
  }
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;
2956
+ class FormulaireBehaviour extends AbstractBehaviourService {
2957
+ constructor() {
2958
+ super(...arguments);
2959
+ u(this, "APP", "formulaire");
2960
+ u(this, "RESOURCE", "formulaire");
3180
2961
  }
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
- );
2962
+ async loadResources() {
2963
+ return (await this.httpGet(
2964
+ "/formulaire/forms/linker"
2965
+ )).map((s) => (s.picture || (s.picture = "/formulaire/public/img/logo.svg"), this.dataToResource({
2966
+ _id: "" + s.id,
2967
+ icon: s.picture,
2968
+ title: s.title,
2969
+ ownerName: s.owner_name,
2970
+ owner: s.owner_id,
2971
+ path: s.is_public ? `${window.location.origin}/formulaire-public#/form/${s.public_key}` : `${window.location.origin}/formulaire#/form/${s.id}/${s.rgpd ? "rgpd" : "new"}`,
2972
+ shared: !!(s.shared && s.shared.length >= 0),
2973
+ modified: "" + s.date_modification
2974
+ })));
3190
2975
  }
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";
2976
+ }
2977
+ class ForumBehaviour extends AbstractBehaviourService {
2978
+ constructor() {
2979
+ super(...arguments);
2980
+ u(this, "APP", "forum");
2981
+ u(this, "RESOURCE", "forum");
2982
+ }
2983
+ async loadResources() {
2984
+ return (await this.httpGet("/forum/categories")).map(
2985
+ (s) => this.dataToResource({
2986
+ _id: s._id,
2987
+ title: s.name,
2988
+ icon: s.icon || "/img/illustrations/forum.svg",
2989
+ path: "/forum#/view/" + s._id,
2990
+ ownerName: s.owner.displayName,
2991
+ owner: s.owner.userId,
2992
+ shared: !!(s.shared && s.shared.length >= 0),
2993
+ modified: s.modified
2994
+ })
2995
+ );
3202
2996
  }
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;
2997
+ }
2998
+ class HomeworksBehaviour extends AbstractBehaviourService {
2999
+ constructor() {
3000
+ super(...arguments);
3001
+ u(this, "APP", "homeworks");
3002
+ u(this, "RESOURCE", "homeworks");
3212
3003
  }
3213
- get http() {
3214
- return this.context.http();
3004
+ async loadResources() {
3005
+ return (await this.httpGet("/homeworks/list")).filter((t) => t.owner && t.trashed === 0).map((t) => this.dataToResource({
3006
+ title: t.title,
3007
+ ownerName: t.owner.displayName,
3008
+ owner: t.owner.userId,
3009
+ icon: t.thumbnail || "/img/illustrations/homeworks.svg",
3010
+ path: "/homeworks#/view-homeworks/" + t._id,
3011
+ _id: "" + t._id,
3012
+ shared: typeof t.shared < "u",
3013
+ modified: t.modified
3014
+ }));
3215
3015
  }
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 };
3016
+ }
3017
+ class MagnetoBehaviour extends AbstractBehaviourService {
3018
+ constructor() {
3019
+ super(...arguments);
3020
+ u(this, "APP", "magneto");
3021
+ u(this, "RESOURCE", "magneto");
3225
3022
  }
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
3023
+ async loadResources() {
3024
+ const { all: t } = await this.httpGet(
3025
+ "/magneto/boards/editable"
3234
3026
  );
3235
- if (this.http.isResponseError())
3236
- throw this.http.latestResponse.statusText;
3237
- return a;
3027
+ return t.map((s) => this.dataToResource({
3028
+ _id: s._id,
3029
+ title: s.title,
3030
+ icon: s.imageUrl,
3031
+ owner: s.ownerId,
3032
+ ownerName: s.ownerName,
3033
+ path: `/magneto#/board/${s._id}/view`,
3034
+ shared: !!(s.shared && s.shared.length >= 0),
3035
+ modified: "" + s.modificationDate
3036
+ }));
3238
3037
  }
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;
3038
+ }
3039
+ class MindmapBehaviour extends AbstractBehaviourService {
3040
+ constructor() {
3041
+ super(...arguments);
3042
+ u(this, "APP", "mindmap");
3043
+ u(this, "RESOURCE", "mindmap");
3251
3044
  }
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;
3045
+ async loadResources() {
3046
+ return (await this.httpGet("/mindmap/list/all")).map(
3047
+ (s) => this.dataToResource({
3048
+ title: s.name,
3049
+ ownerName: s.owner.displayName,
3050
+ owner: s.owner.userId,
3051
+ icon: s.thumbnail || "/img/illustrations/mindmap-default.png",
3052
+ path: "/mindmap#/view/" + s._id,
3053
+ _id: s._id,
3054
+ shared: !!(s.shared && s.shared.length >= 0),
3055
+ modified: s.modified
3056
+ })
3057
+ );
3260
3058
  }
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;
3059
+ }
3060
+ class PagesBehaviour extends AbstractBehaviourService {
3061
+ constructor() {
3062
+ super(...arguments);
3063
+ u(this, "APP", "pages");
3064
+ u(this, "RESOURCE", "pages");
3264
3065
  }
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);
3066
+ async loadResources() {
3067
+ const t = await this.httpGet("/pages/list/all"), s = [];
3068
+ return t.forEach((r) => {
3069
+ var o;
3070
+ const i = r.thumbnail ? r.thumbnail + "?thumbnail=48x48" : "/img/illustrations/pages.svg";
3071
+ s.push(
3072
+ this.dataToResource({
3073
+ title: r.title,
3074
+ owner: r.owner.userId,
3075
+ ownerName: r.owner.displayName,
3076
+ icon: i,
3077
+ path: "/pages#/website/" + r._id,
3078
+ _id: r._id,
3079
+ shared: typeof r.shared < "u",
3080
+ modified: r.modified
3081
+ })
3082
+ ), (o = r.pages) == null || o.forEach((a) => {
3083
+ s.push(
3084
+ this.dataToResource({
3085
+ title: a.title,
3086
+ owner: r.owner.userId,
3087
+ ownerName: r.owner.displayName,
3088
+ icon: i,
3089
+ path: "/pages#/website/" + r._id + "/" + a.titleLink,
3090
+ _id: r._id + "/" + a.titleLink,
3091
+ shared: typeof r.shared < "u",
3092
+ modified: r.modified
3093
+ })
3094
+ );
3095
+ });
3096
+ }), s;
3270
3097
  }
3271
- async listDocuments(e, t) {
3272
- return this.searchDocuments({ filter: e, parentId: t, includeall: !0 });
3098
+ }
3099
+ class PollBehaviour extends AbstractBehaviourService {
3100
+ constructor() {
3101
+ super(...arguments);
3102
+ u(this, "APP", "poll");
3103
+ u(this, "RESOURCE", "poll");
3273
3104
  }
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;
3105
+ async loadResources() {
3106
+ return (await this.httpGet("/poll/list/all")).map((s) => {
3107
+ const r = s.icon ? s.icon + "?thumbnail=48x48" : "/img/icons/glyphicons_036_file.png";
3108
+ return this.dataToResource({
3109
+ title: s.question,
3110
+ ownerName: s.owner.displayName,
3111
+ icon: r,
3112
+ path: "/poll#/view/" + s._id,
3113
+ _id: s._id,
3114
+ owner: s.owner.userId,
3115
+ shared: !!(s.shared && s.shared.length >= 0),
3116
+ modified: s.modified
3117
+ });
3118
+ });
3304
3119
  }
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
- }
3120
+ }
3121
+ class ScrapbookBehaviour extends AbstractBehaviourService {
3122
+ constructor() {
3123
+ super(...arguments);
3124
+ u(this, "APP", "scrapbook");
3125
+ u(this, "RESOURCE", "scrapbook");
3322
3126
  }
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
3127
+ async loadResources() {
3128
+ return (await this.httpGet(
3129
+ "/scrapbook/list/all"
3130
+ )).map((s) => {
3131
+ const r = s.icon || "/img/illustrations/scrapbook.svg";
3132
+ return this.dataToResource({
3133
+ title: s.name,
3134
+ owner: s.owner.userId,
3135
+ ownerName: s.owner.displayName,
3136
+ icon: r,
3137
+ path: "/scrapbook#/view-scrapbook/" + s._id,
3138
+ _id: s._id,
3139
+ shared: !!(s.shared && s.shared.length >= 0),
3140
+ modified: s.modified
3141
+ });
3341
3142
  });
3342
3143
  }
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);
3144
+ }
3145
+ class TimelinegeneratorBehaviour extends AbstractBehaviourService {
3146
+ constructor() {
3147
+ super(...arguments);
3148
+ u(this, "APP", "timelinegenerator");
3149
+ u(this, "RESOURCE", "timelinegenerator");
3360
3150
  }
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);
3151
+ loadResources() {
3152
+ return new Promise(async (t, s) => {
3153
+ try {
3154
+ const i = (await this.httpGet(
3155
+ "/timelinegenerator/timelines"
3156
+ )).map((o) => {
3157
+ const a = o.icon || "/img/illustrations/timeline-default.png";
3158
+ return this.dataToResource({
3159
+ title: o.headline,
3160
+ ownerName: o.owner.displayName,
3161
+ owner: o.owner.userId,
3162
+ icon: a,
3163
+ path: "/timelinegenerator#/view/" + o._id,
3164
+ _id: o._id,
3165
+ shared: typeof o.shared < "u",
3166
+ modified: o.modified
3167
+ });
3168
+ });
3169
+ t(i);
3170
+ } catch (r) {
3171
+ s(r);
3172
+ }
3173
+ });
3370
3174
  }
3371
3175
  }
3372
- let ATTag;
3373
- class AnalyticsService {
3374
- constructor(n) {
3375
- this.context = n;
3176
+ class WikiBehaviour extends AbstractBehaviourService {
3177
+ constructor() {
3178
+ super(...arguments);
3179
+ u(this, "APP", "wiki");
3180
+ u(this, "RESOURCE", "wiki");
3376
3181
  }
3377
- get http() {
3378
- return this.context.http();
3182
+ async loadResources() {
3183
+ return (await this.httpGet(
3184
+ "/wiki/listallpages?visible=true"
3185
+ )).map((s) => s.pages.map((r) => {
3186
+ let i;
3187
+ return typeof s.thumbnail > "u" || s.thumbnail === "" ? i = "/img/icons/glyphicons_036_file.png" : i = s.thumbnail + "?thumbnail=48x48", this.dataToResource({
3188
+ title: r.title + " [" + s.title + "]",
3189
+ ownerName: s.owner.displayName,
3190
+ owner: s.owner.userId,
3191
+ icon: i,
3192
+ path: "/wiki#/view/" + s._id + "/" + r._id,
3193
+ _id: `${s._id}#${r._id}`,
3194
+ shared: typeof s.shared < "u",
3195
+ modified: r.modified
3196
+ });
3197
+ })).flat();
3379
3198
  }
3380
- get session() {
3381
- return this.context.session();
3199
+ }
3200
+ class WorkspaceBehaviour extends AbstractBehaviourService {
3201
+ constructor() {
3202
+ super(...arguments);
3203
+ u(this, "APP", "workspace");
3204
+ u(this, "RESOURCE", "workspace");
3382
3205
  }
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;
3206
+ loadResources({ search: t, asset_id: s }) {
3207
+ return new Promise(async (r, i) => {
3208
+ try {
3209
+ let o = "/workspace/documents?filter=all&hierarchical=true";
3210
+ s && s.length ? o += `&search=${t}` : t && t.length && (o += `&search=${t}`);
3211
+ const c = (await this.httpGet(o)).filter((l) => !l.deleted).map((l) => {
3212
+ const h = l.metadata["content-type"] && l.metadata["content-type"].indexOf("image") !== -1 ? `/workspace/document/${l._id}?thumbnail=120x120` : "/img/icons/unknown-large.png";
3213
+ return this.dataToResource({
3214
+ title: l.name,
3215
+ ownerName: l.ownerName,
3216
+ owner: l.owner,
3217
+ icon: h,
3218
+ path: `/workspace/document/${l._id}`,
3219
+ _id: l._id,
3220
+ shared: !!(l.shared && l.shared.length >= 0),
3221
+ modified: l.modified
3222
+ });
3223
+ });
3224
+ r(c);
3225
+ } catch (o) {
3226
+ i(o);
3401
3227
  }
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;
3228
+ });
3434
3229
  }
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);
3230
+ }
3231
+ const b = class b {
3232
+ static async initialize(e, t) {
3233
+ const s = e.http();
3234
+ if (!this.resourceProducingApps.length) {
3235
+ this.resourceProducingApps = [t, "workspace"];
3236
+ try {
3237
+ const [r, i] = await Promise.all([
3238
+ s.get("/resources-applications"),
3239
+ e.session().getUser()
3240
+ ]);
3241
+ i != null && i.apps && (r != null && r.length) && (this.resourceProducingApps = r.filter(
3242
+ (o) => i.apps.some((a) => a.address.includes(o))
3243
+ ));
3244
+ } catch (r) {
3245
+ console.warn("Failed to load resource-producing apps:", r);
3246
+ }
3443
3247
  }
3248
+ return this.resourceProducingApps;
3444
3249
  }
3445
- async getXitiTrackingParams(n, e) {
3446
- if (!n.structureMap || !e) return;
3447
- const t = await this.session.getUser(), s = await this.session.getUserProfile();
3250
+ static registerCustomBehaviour(e, t, s) {
3251
+ this.registry.register({ application: e, resourceType: t }, s);
3252
+ }
3253
+ static async registerBehaviours(e) {
3254
+ this.resourceProducingApps.forEach((t) => {
3255
+ const s = { application: e, resourceType: t };
3256
+ this.registry.register(
3257
+ s,
3258
+ (r) => this.serviceFor(r, e, t)
3259
+ );
3260
+ });
3261
+ }
3262
+ static serviceFor(e, t, s) {
3448
3263
  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;
3264
+ switch (s) {
3265
+ case "timelinegenerator":
3266
+ r = new TimelinegeneratorBehaviour(e);
3267
+ break;
3268
+ case "workspace":
3269
+ r = new WorkspaceBehaviour(e);
3270
+ break;
3271
+ case "blog":
3272
+ r = new BlogBehaviour(e);
3273
+ break;
3274
+ case "actualites":
3275
+ r = new ActualitesBehaviour(e);
3276
+ break;
3277
+ case "wiki":
3278
+ r = new WikiBehaviour(e);
3279
+ break;
3280
+ case "pages":
3281
+ r = new PagesBehaviour(e);
3282
+ break;
3283
+ case "poll":
3284
+ r = new PollBehaviour(e);
3285
+ break;
3286
+ case "community":
3287
+ r = new CommunityBehaviour(e);
3288
+ break;
3289
+ case "mindmap":
3290
+ r = new MindmapBehaviour(e);
3291
+ break;
3292
+ case "forum":
3293
+ r = new ForumBehaviour(e);
3294
+ break;
3295
+ case "homeworks":
3296
+ r = new HomeworksBehaviour(e);
3297
+ break;
3298
+ case "scrapbook":
3299
+ r = new ScrapbookBehaviour(e);
3300
+ break;
3301
+ case "collaborativewall":
3302
+ r = new CollaborativewallBehaviour(e);
3454
3303
  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;
3304
+ case "exercizer":
3305
+ r = new ExercizerBehaviour(e);
3306
+ break;
3307
+ case "formulaire":
3308
+ r = new FormulaireBehaviour(e);
3309
+ break;
3310
+ case "magneto":
3311
+ r = new MagnetoBehaviour(e);
3312
+ break;
3313
+ case "appointments":
3314
+ r = new AppointmentsBehaviour(e);
3315
+ break;
3316
+ default:
3317
+ throw ERROR_CODE.NOT_SUPPORTED;
3467
3318
  }
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
- };
3319
+ return r.APP = t, r;
3488
3320
  }
3489
- }
3490
- const R = class R {
3491
- // in minutes. Applies to recorded videos.
3321
+ };
3322
+ //
3323
+ // STATIC REGISTRY
3324
+ //
3325
+ u(b, "registry", new ServiceRegistry()), // Expose some useful functions
3326
+ u(b, "findBehaviour", b.registry.findService.bind(b.registry)), u(b, "hasBehaviour", b.registry.isRegistered.bind(b.registry)), u(b, "resourceProducingApps", []);
3327
+ let SnipletsService = b;
3328
+ class RightService {
3492
3329
  constructor(e) {
3493
3330
  this.context = e;
3494
3331
  }
3495
- get http() {
3496
- return this.context.http();
3497
- }
3498
- get conf() {
3499
- return this.context.conf();
3332
+ get session() {
3333
+ return this.context.session();
3500
3334
  }
3501
3335
  /**
3502
- * Returns the video app public conf (maxWeight, maxDuration and accepted extensions)
3503
- * @returns the Video app public conf
3336
+ * Parse right concat as "$TYPE:$ID:$RIGHT"
3337
+ * $TYPE = user | group | creator
3338
+ * $ID: id of the resource
3339
+ * $RIGHT: read | contrib | manage
3340
+ *
3341
+ * @param right a concat right
3342
+ * @returns Right parsed
3504
3343
  */
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
- };
3344
+ parseResourceRight(e) {
3345
+ const t = e.split(":");
3346
+ if (t.length === 2) {
3347
+ if (t[0] === "creator")
3348
+ return {
3349
+ id: t[1],
3350
+ right: "creator",
3351
+ type: "creator"
3352
+ };
3353
+ } else return t.length === 3 ? {
3354
+ id: t[1],
3355
+ right: t[2],
3356
+ type: t[0]
3357
+ } : void 0;
3517
3358
  }
3518
3359
  /**
3519
- * Starts the encoding process and check when video is fully processed.
3520
- * @param params cf VideoUploadParams
3521
- * @returns a VideoCheckResponse
3360
+ * Parse an array of rights concat as "$TYPE:$ID:$RIGHT"
3361
+ * $TYPE = user | group | creator
3362
+ * $ID: id of the resource
3363
+ * $RIGHT: read | contrib | manage
3364
+ *
3365
+ * @param rights a list of concat rights
3366
+ * @returns Array of Right parsed
3522
3367
  */
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();
3368
+ parseResourceRights(e) {
3369
+ return e.map((s) => this.parseResourceRight(s)).filter((s) => s !== void 0);
3578
3370
  }
3579
3371
  /**
3580
- * Returns the default list of video embedder
3581
- * @returns the default list of video embedder
3372
+ * Check wether a user has the expected right for a resource
3373
+ * @param user the userId and groupId concerned by the check
3374
+ * @param expect the expected right to check
3375
+ * @param rights array of Right for the resource
3376
+ * @returns true if has rights
3582
3377
  */
3583
- async getDefault() {
3584
- return this.http.get("/infra/embed/default");
3378
+ hasResourceRight({ id: e, groupIds: t }, s, r) {
3379
+ const i = r.map((o) => typeof o == "string" ? this.parseResourceRight(o) : o).filter((o) => o !== void 0);
3380
+ for (const o of i) {
3381
+ if (o.id === e && o.type === "creator")
3382
+ return !0;
3383
+ if (o.id === e && o.type === "user" && o.right === s)
3384
+ return !0;
3385
+ if (t.includes(o.id) && o.type === "group" && o.right === s)
3386
+ return !0;
3387
+ }
3388
+ return !1;
3585
3389
  }
3586
3390
  /**
3587
- * Returns the custom list of video embedder
3588
- * @returns the custom list of video embedder
3391
+ * Check wether the current user have resource right
3392
+ * @param expect the expected right to check
3393
+ * @param rights array of Right for the resource
3394
+ * @returns true if has rights
3589
3395
  */
3590
- async getCustom() {
3591
- return this.http.get("/infra/embed/custom");
3396
+ async sessionHasResourceRight(e, t) {
3397
+ try {
3398
+ const s = await this.session.getUser();
3399
+ return !!s && this.hasResourceRight(
3400
+ { groupIds: s.groupsIds, id: s.userId },
3401
+ e,
3402
+ t
3403
+ );
3404
+ } catch (s) {
3405
+ return console.error(`Unexpected error ${s} in sessionHasResourceRight()`), !1;
3406
+ }
3592
3407
  }
3593
3408
  /**
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
3409
+ * Check wether the current user have at least one of resource right expected
3410
+ * @param expects array of expected right to check
3411
+ * @param rights array of Right for the resource
3412
+ * @returns true if has rights
3598
3413
  */
3599
- getProviderFromUrl(e, t) {
3414
+ async sessionHasAtLeastOneResourceRight(e, t) {
3600
3415
  for (const s of e)
3601
- if (this.isUrlFromProvider(t, s))
3602
- return s;
3416
+ if (await this.sessionHasResourceRight(s, t))
3417
+ return !0;
3418
+ return !1;
3603
3419
  }
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;
3420
+ /**
3421
+ * Check wether the current user has resource right for each right list
3422
+ * @param expect expected right to check
3423
+ * @param rightsArray array of array of Right for multiple resources
3424
+ * @returns true if has rights
3425
+ */
3426
+ async sessionHasResourceRightForEachList(e, t) {
3427
+ let s = 0;
3428
+ for (const r of t)
3429
+ await this.sessionHasResourceRight(e, r) && s++;
3430
+ return s === t.length;
3616
3431
  }
3617
3432
  /**
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
3433
+ * Check wether the current user have at least one of resource right for each right list
3434
+ * @param expects array of expected right to check
3435
+ * @param rightsArray array of array of Right for multiple resources
3436
+ * @returns true if has rights
3622
3437
  */
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))
3438
+ async sessionHasAtLeastOneResourceRightForEachList(e, t) {
3439
+ for (const s of e) {
3440
+ let r = 0;
3441
+ for (const i of t)
3442
+ await this.sessionHasResourceRight(s, i) && r++;
3443
+ if (r === t.length)
3627
3444
  return !0;
3445
+ }
3628
3446
  return !1;
3629
3447
  }
3448
+ hasWorkflowRight(e, t) {
3449
+ return t.findIndex((s) => s === e) !== -1;
3450
+ }
3451
+ /**
3452
+ * @param expect a workflow right
3453
+ * @returns true if current session has right on it
3454
+ */
3455
+ async sessionHasWorkflowRight(e) {
3456
+ try {
3457
+ const t = await this.session.getUser();
3458
+ return !!t && this.hasWorkflowRight(
3459
+ e,
3460
+ t.authorizedActions.map(
3461
+ (s) => s.name
3462
+ )
3463
+ );
3464
+ } catch (t) {
3465
+ return console.error(`Unexpected error ${t} in sessionHasWorkflowRight()`), !1;
3466
+ }
3467
+ }
3630
3468
  /**
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
3469
+ * @param expect a workflow right
3470
+ * @returns a record with right as key and boolean as value if current session has right on it
3635
3471
  */
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 "";
3472
+ async sessionHasWorkflowRights(e) {
3473
+ const t = {};
3474
+ try {
3475
+ const s = await this.session.getUser();
3476
+ for (const r of e)
3477
+ t[r] = !!s && this.hasWorkflowRight(
3478
+ r,
3479
+ s.authorizedActions.map(
3480
+ (i) => i.name
3481
+ )
3482
+ );
3483
+ } catch (s) {
3484
+ console.error(`Unexpected error ${s} in sessionHasWorkflowRights()`);
3485
+ for (const r of e)
3486
+ t[r] = !1;
3487
+ }
3488
+ return t;
3656
3489
  }
3657
3490
  }
3658
- class AbstractBehaviourService {
3659
- //
3660
- // IMPLEMENTATION
3661
- //
3491
+ class SessionService {
3662
3492
  constructor(e) {
3663
- //-----------------
3664
- //--- Utilities ---
3665
- //-----------------
3666
- u(this, "_cache");
3667
- this.context = e, this._cache = new CacheService(this.context);
3493
+ this.context = e;
3668
3494
  }
3669
- getApplication() {
3670
- return this.APP;
3495
+ get http() {
3496
+ return this.context.http();
3671
3497
  }
3672
- getResourceType() {
3673
- return this.RESOURCE;
3498
+ get cache() {
3499
+ return this.context.cache();
3674
3500
  }
3675
- httpGet(e, t) {
3676
- return this._cache.httpGetJson(e, t);
3501
+ get conf() {
3502
+ return this.context.conf();
3677
3503
  }
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 : "";
3504
+ /**
3505
+ * Callback to call when user logout
3506
+ */
3507
+ onLogout() {
3508
+ this.cache.clearCache();
3509
+ }
3510
+ /**
3511
+ * Callback to call when session change
3512
+ */
3513
+ onRefreshSession() {
3514
+ this.cache.clearCache();
3515
+ }
3516
+ async getSession() {
3517
+ const [e, t] = await Promise.all([
3518
+ this.getUser(),
3519
+ this.getPerson()
3520
+ ]), [
3521
+ s,
3522
+ r,
3523
+ i,
3524
+ o,
3525
+ a
3526
+ ] = await Promise.all([
3527
+ this.getCurrentLanguage(e),
3528
+ this.latestQuotaAndUsage(e),
3529
+ this.loadDescription(e),
3530
+ this.getUserProfile(),
3531
+ this.getBookmarks(e)
3532
+ ]), { type: c, ...l } = t || {}, h = {
3533
+ ...l,
3534
+ profiles: c || ["Guest"],
3535
+ // "type" field from /userbook/api/person becomes "profiles"
3536
+ ...i
3537
+ // Inject other fields (also the correct "type")
3538
+ };
3684
3539
  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
3540
+ user: e,
3541
+ quotaAndUsage: r,
3542
+ currentLanguage: s,
3543
+ userDescription: h,
3544
+ userProfile: o,
3545
+ bookmarkedApps: a
3694
3546
  };
3695
3547
  }
3696
- }
3697
- class ActualitesBehaviour extends AbstractBehaviourService {
3698
- constructor() {
3699
- super(...arguments);
3700
- u(this, "APP", "actualites");
3701
- u(this, "RESOURCE", "actualites");
3548
+ login(e, t, s, r) {
3549
+ const i = new FormData();
3550
+ 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, {
3551
+ headers: { "content-type": "application/x-www-form-urlencoded" }
3552
+ }).finally(() => {
3553
+ switch (this.http.latestResponse.status) {
3554
+ case 200:
3555
+ throw ERROR_CODE.MALFORMED_DATA;
3556
+ }
3557
+ });
3702
3558
  }
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
- });
3559
+ async logout() {
3560
+ const e = await this.conf.getLogoutCallback();
3561
+ return this.http.get("/auth/logout?callback=" + e).finally(() => {
3724
3562
  });
3725
3563
  }
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");
3564
+ async latestQuotaAndUsage(e) {
3565
+ const t = { quota: 0, storage: 0 };
3566
+ if (!e) return t;
3567
+ try {
3568
+ return await this.http.get(
3569
+ `/workspace/quota/user/${e == null ? void 0 : e.userId}`
3570
+ );
3571
+ } catch (s) {
3572
+ return console.error(s), t;
3573
+ }
3738
3574
  }
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
- }));
3575
+ async getCurrentLanguage(e) {
3576
+ const t = (e == null ? void 0 : e.sessionMetadata) && (e == null ? void 0 : e.sessionMetadata.userId);
3577
+ try {
3578
+ let s;
3579
+ return t ? s = await this.loadUserLanguage() : s = await this.loadDefaultLanguage(), s;
3580
+ } catch (s) {
3581
+ console.error(s);
3582
+ }
3750
3583
  }
3751
- }
3752
- class BlogBehaviour extends AbstractBehaviourService {
3753
- constructor() {
3754
- super(...arguments);
3755
- u(this, "APP", "blog");
3756
- u(this, "RESOURCE", "blog");
3584
+ async loadUserLanguage() {
3585
+ try {
3586
+ const e = await this.http.get(
3587
+ "/userbook/preference/language"
3588
+ );
3589
+ return JSON.parse(e.preference)["default-domain"];
3590
+ } catch {
3591
+ return await this.loadDefaultLanguage();
3592
+ }
3757
3593
  }
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
- }
3594
+ async loadDefaultLanguage() {
3595
+ return (await this.cache.httpGetJson(
3596
+ "/locale"
3597
+ )).locale;
3598
+ }
3599
+ async getUser() {
3600
+ const { response: e, value: t } = await this.cache.httpGet(
3601
+ "/auth/oauth2/userinfo"
3602
+ );
3603
+ if (!(e.status < 200 || e.status >= 300) && typeof t == "object")
3604
+ return t;
3605
+ throw ERROR_CODE.NOT_LOGGED_IN;
3606
+ }
3607
+ hasWorkflow({
3608
+ workflowName: e,
3609
+ user: t
3610
+ }) {
3611
+ return e === void 0 || (t == null ? void 0 : t.authorizedActions.findIndex((s) => s.name === e)) !== -1;
3612
+ }
3613
+ async loadDescription(e) {
3614
+ if (!e) return {};
3615
+ try {
3616
+ const [t, s] = await Promise.all([
3617
+ // FIXME The full user's description should be obtainable from a single endpoint in the backend.
3618
+ this.getUserProfile({
3619
+ options: { requestName: "refreshAvatar" }
3620
+ }),
3621
+ this.http.get("/directory/userbook/" + (e == null ? void 0 : e.userId))
3622
+ ]);
3623
+ return { ...s, profiles: t };
3624
+ } catch (t) {
3625
+ return console.error(t), {};
3626
+ }
3627
+ }
3628
+ async getBookmarks(e) {
3629
+ if (!e) return [];
3630
+ const t = await this.http.get("/userbook/preference/apps");
3631
+ t.preference || (t.preference = null);
3632
+ const s = JSON.parse(t.preference);
3633
+ let r;
3634
+ r = s, r || (r = {
3635
+ bookmarks: [],
3636
+ applications: []
3779
3637
  });
3638
+ const i = [];
3639
+ return r.bookmarks.forEach((o, a) => {
3640
+ const c = ((e == null ? void 0 : e.apps) || []).find(
3641
+ (l) => l.name === o
3642
+ );
3643
+ if (c) {
3644
+ const l = Object.assign({}, c);
3645
+ i.push(l);
3646
+ }
3647
+ }), i;
3780
3648
  }
3781
- }
3782
- class CollaborativewallBehaviour extends AbstractBehaviourService {
3783
- constructor() {
3784
- super(...arguments);
3785
- u(this, "APP", "collaborativewall");
3786
- u(this, "RESOURCE", "collaborativewall");
3649
+ async getUserProfile(e = {}) {
3650
+ const t = await this.getPerson(e);
3651
+ return (t == null ? void 0 : t.type) || ["Guest"];
3787
3652
  }
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
- })
3653
+ async getPerson(e = {}) {
3654
+ var c;
3655
+ 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(
3656
+ i,
3657
+ t
3802
3658
  );
3659
+ 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
3660
  }
3804
- }
3805
- class CommunityBehaviour extends AbstractBehaviourService {
3806
- constructor() {
3807
- super(...arguments);
3808
- u(this, "APP", "community");
3809
- u(this, "RESOURCE", "community");
3661
+ async isAdml() {
3662
+ const e = await this.getUser();
3663
+ return (e == null ? void 0 : e.functions.ADMIN_LOCAL) !== void 0;
3810
3664
  }
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
- });
3665
+ /**
3666
+ * Get details of an application if the user can access it.
3667
+ * @return undefined if no access, or app not found
3668
+ */
3669
+ async getWebApp(e) {
3670
+ const t = await this.getUser();
3671
+ return t == null ? void 0 : t.apps.find((s) => {
3672
+ var r;
3673
+ 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
3674
  });
3828
3675
  }
3829
3676
  }
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
- });
3677
+ class StringUtils {
3678
+ static removeAccents(e) {
3679
+ for (let t = 0; t < defaultDiacriticsRemovalMap.length; t++)
3680
+ e = e.replace(
3681
+ defaultDiacriticsRemovalMap[t].letters,
3682
+ defaultDiacriticsRemovalMap[t].base
3683
+ );
3684
+ return e;
3854
3685
  }
3855
3686
  }
3856
- class FormulaireBehaviour extends AbstractBehaviourService {
3857
- constructor() {
3858
- super(...arguments);
3859
- u(this, "APP", "formulaire");
3860
- u(this, "RESOURCE", "formulaire");
3687
+ class ShareService {
3688
+ //
3689
+ // IMPLEMENTATION
3690
+ //
3691
+ constructor(e) {
3692
+ this.context = e;
3861
3693
  }
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
- })));
3694
+ get directory() {
3695
+ return this.context.directory();
3875
3696
  }
3876
- }
3877
- class ForumBehaviour extends AbstractBehaviourService {
3878
- constructor() {
3879
- super(...arguments);
3880
- u(this, "APP", "forum");
3881
- u(this, "RESOURCE", "forum");
3697
+ get http() {
3698
+ return this.context.http();
3882
3699
  }
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
3700
+ get cache() {
3701
+ return this.context.cache();
3702
+ }
3703
+ getSearchUrl(e, t, s, r) {
3704
+ if (!r)
3705
+ return `/${e}/share/json/${t}?search=${s}`;
3706
+ if (r.includes("?search=")) {
3707
+ const [i] = r.split("?search=");
3708
+ return `${i}?search=${s}`;
3709
+ } else return r.includes("?") ? `${r}&search=${s}` : `${r}?search=${s}`;
3710
+ }
3711
+ async searchShareSubjects(e, t, s, r) {
3712
+ const i = StringUtils.removeAccents(s).toLowerCase(), o = this.getSearchUrl(
3713
+ e,
3714
+ t,
3715
+ s,
3716
+ r
3717
+ ), a = await this.cache.httpGetJson(o), c = a.users.visibles.filter(({ username: p, firstName: y, lastName: d, login: g }) => {
3718
+ const A = StringUtils.removeAccents(
3719
+ d || ""
3720
+ ).toLowerCase(), f = StringUtils.removeAccents(
3721
+ y || ""
3722
+ ).toLowerCase(), w = StringUtils.removeAccents(
3723
+ p || ""
3724
+ ).toLowerCase(), F = StringUtils.removeAccents(g || "").toLowerCase();
3725
+ return w.includes(i) || f.includes(i) || A.includes(i) || F.includes(i);
3726
+ }).map((p) => ({
3727
+ avatarUrl: this.directory.getAvatarUrl(p.id, "user"),
3728
+ directoryUrl: this.directory.getDirectoryUrl(p.id, "user"),
3729
+ displayName: p.username,
3730
+ id: p.id,
3731
+ profile: p.profile,
3732
+ type: "user"
3733
+ })), l = a.groups.visibles.filter(({ name: p }) => StringUtils.removeAccents(p || "").toLowerCase().includes(i)).map((p) => ({
3734
+ avatarUrl: this.directory.getAvatarUrl(p.id, "group"),
3735
+ directoryUrl: this.directory.getDirectoryUrl(p.id, "group"),
3736
+ displayName: p.name,
3737
+ id: p.id,
3738
+ type: "group",
3739
+ structureName: p.structureName
3740
+ }));
3741
+ return [...(await this.directory.getBookMarks()).filter(({ displayName: p }) => StringUtils.removeAccents(
3742
+ p || ""
3743
+ ).toLowerCase().includes(i)).map((p) => ({
3744
+ avatarUrl: "",
3745
+ directoryUrl: "",
3746
+ profile: "",
3747
+ displayName: p.displayName,
3748
+ id: p.id,
3749
+ type: "sharebookmark"
3750
+ })), ...c, ...l];
3751
+ }
3752
+ async getShareMapping(e, t) {
3753
+ const s = await this.cache.httpGetJson(
3754
+ t || `/${e}/rights/sharing`
3755
+ );
3756
+ for (const r of Object.keys(s))
3757
+ if (r.includes(".")) {
3758
+ const i = r.split(".")[1], o = s[r];
3759
+ delete s[r], s[i] = o;
3760
+ }
3761
+ return s;
3762
+ }
3763
+ getActionsAvailableFor({ id: e, type: t }, s, r) {
3764
+ const o = (t === "user" ? s.users.checked[e] : s.groups.checked[e]) || [], a = Object.keys(r), c = [];
3765
+ for (const l of a)
3766
+ r[l].filter(
3767
+ (p) => o.includes(p)
3768
+ ).length > 0 && c.push(l);
3769
+ return c;
3770
+ }
3771
+ async getRightsForResource(e, t, s) {
3772
+ const r = await this.directory.getBookMarks(), i = this.getSearchUrl(
3773
+ e,
3774
+ t,
3775
+ "",
3776
+ s == null ? void 0 : s.getResourceRights
3777
+ ), o = await this.cache.httpGetJson(
3778
+ i
3779
+ ), a = await this.getShareMapping(
3780
+ e,
3781
+ s == null ? void 0 : s.getShareMapping
3782
+ ), c = await this.cache.httpGetJson(
3783
+ "/infra/public/json/sharing-rights.json"
3784
+ ), l = Object.keys(o.users.checked).map((d) => o.users.visibles.find(
3785
+ (A) => A.id === d
3786
+ )).filter((d) => d !== void 0).map((d) => {
3787
+ const g = this.getActionsAvailableFor(
3788
+ { id: d.id, type: "user" },
3789
+ o,
3790
+ a
3791
+ );
3792
+ return {
3793
+ id: d.id,
3794
+ type: "user",
3795
+ displayName: d.username,
3796
+ profile: d.profile,
3797
+ avatarUrl: this.directory.getAvatarUrl(d.id, "user"),
3798
+ directoryUrl: this.directory.getDirectoryUrl(d.id, "user"),
3799
+ actions: g.map((f) => {
3800
+ const w = c[f];
3801
+ return {
3802
+ displayName: f,
3803
+ id: f,
3804
+ priority: w.priority
3805
+ };
3806
+ })
3807
+ };
3808
+ }).sort((d, g) => (d.displayName || "").localeCompare(g.displayName)), h = Object.keys(o.groups.checked).map((d) => o.groups.visibles.find(
3809
+ (A) => A.id === d
3810
+ )).filter((d) => d !== void 0).map((d) => {
3811
+ const g = this.getActionsAvailableFor(
3812
+ { id: d.id, type: "group" },
3813
+ o,
3814
+ a
3815
+ );
3816
+ return {
3817
+ id: d.id,
3818
+ type: "group",
3819
+ displayName: d.name,
3820
+ profile: void 0,
3821
+ avatarUrl: this.directory.getAvatarUrl(d.id, "group"),
3822
+ directoryUrl: this.directory.getDirectoryUrl(d.id, "group"),
3823
+ actions: g.map((f) => {
3824
+ const w = c[f];
3825
+ return {
3826
+ displayName: f,
3827
+ id: f,
3828
+ priority: w.priority
3829
+ };
3830
+ })
3831
+ };
3832
+ }).sort((d, g) => (d.displayName || "").localeCompare(g.displayName)), E = [...l, ...h], p = o.groups.visibles.map(
3833
+ ({ groupDisplayName: d, id: g, name: A, labels: f }) => ({
3834
+ labels: f,
3835
+ displayName: d || A,
3836
+ id: g
3837
+ })
3838
+ ), y = o.users.visibles.map(
3839
+ ({ id: d, profile: g, username: A, firstName: f, lastName: w, login: F }) => ({
3840
+ displayName: A,
3841
+ firstName: f,
3842
+ lastName: w,
3843
+ login: F,
3844
+ profile: g,
3845
+ id: d
3894
3846
  })
3895
3847
  );
3848
+ return {
3849
+ rights: E,
3850
+ visibleBookmarks: r,
3851
+ visibleGroups: p,
3852
+ visibleUsers: y
3853
+ };
3896
3854
  }
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");
3855
+ async getPutSharePayload(e, t, s) {
3856
+ const r = {
3857
+ users: {},
3858
+ groups: {},
3859
+ bookmarks: {}
3860
+ }, i = await this.getShareMapping(e, s);
3861
+ for (const o of t) {
3862
+ const a = o.actions.map((l) => i[l.id]).reduce((l, h) => Array.isArray(h) ? [...l, ...h] : l, []), c = [...new Set(a)];
3863
+ c.length > 0 && (o.type === "user" ? r.users[o.id] = c : o.type === "group" ? r.groups[o.id] = c : r.bookmarks[o.id] = c);
3864
+ }
3865
+ return r;
3922
3866
  }
3923
- async loadResources() {
3924
- const { all: t } = await this.httpGet(
3925
- "/magneto/boards/editable"
3867
+ async saveRights(e, t, s, r) {
3868
+ const i = await this.getPutSharePayload(
3869
+ e,
3870
+ s,
3871
+ r == null ? void 0 : r.getShareMapping
3872
+ ), o = (r == null ? void 0 : r.saveResourceRights) || `/${e}/share/resource/${t}`, a = this.getSearchUrl(
3873
+ e,
3874
+ t,
3875
+ "",
3876
+ r == null ? void 0 : r.getResourceRights
3926
3877
  );
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");
3878
+ return this.cache.clearCache(a), await this.http.putJson(o, i);
3944
3879
  }
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
- );
3880
+ async getActionsForApp(e, t) {
3881
+ const s = await this.cache.httpGetJson(
3882
+ "/infra/public/json/sharing-rights.json"
3883
+ ), r = await this.getShareMapping(e, t);
3884
+ return Object.keys(s).map((o) => {
3885
+ const a = s[o];
3886
+ return {
3887
+ displayName: o,
3888
+ id: o,
3889
+ priority: a.priority,
3890
+ requires: a.requires
3891
+ };
3892
+ }).filter((o) => {
3893
+ var a;
3894
+ return ((a = r[o.id]) == null ? void 0 : a.length) > 0;
3895
+ }).sort((o, a) => o.priority - a.priority);
3958
3896
  }
3959
3897
  }
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;
3898
+ const loadedScripts = {};
3899
+ class HttpService {
3900
+ constructor(e, t) {
3901
+ // Axios automatically manages the XSRF-TOKEN cookie and the X-XSRF-TOKEN HTTP header.
3902
+ u(this, "axios");
3903
+ u(this, "baseUrl");
3904
+ u(this, "headers", {});
3905
+ u(this, "_latestResponse");
3906
+ this.context = e, this.axios = axios.create(t);
3997
3907
  }
3998
- }
3999
- class PollBehaviour extends AbstractBehaviourService {
4000
- constructor() {
4001
- super(...arguments);
4002
- u(this, "APP", "poll");
4003
- u(this, "RESOURCE", "poll");
3908
+ fixBaseUrl(e) {
3909
+ return e.startsWith("http://") || e.startsWith("https://") ? e : this.baseUrl ? this.baseUrl.endsWith("/") || e.startsWith("/") ? `${this.baseUrl}${e}` : `${this.baseUrl}/${e}` : e;
4004
3910
  }
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
- });
3911
+ useBaseUrl(e) {
3912
+ return this.baseUrl = e, this;
4019
3913
  }
4020
- }
4021
- class ScrapbookBehaviour extends AbstractBehaviourService {
4022
- constructor() {
4023
- super(...arguments);
4024
- u(this, "APP", "scrapbook");
4025
- u(this, "RESOURCE", "scrapbook");
3914
+ useHeaders(e) {
3915
+ return this.headers = e, this;
4026
3916
  }
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
- });
3917
+ setCdn(e) {
3918
+ e && XMLHttpRequest && !XMLHttpRequest.prototype.cdnUrl && (XMLHttpRequest.prototype.cdnUrl = e, XMLHttpRequest.prototype.baseOpen = XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.open = function() {
3919
+ const t = arguments[1];
3920
+ 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
3921
  });
4043
3922
  }
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);
3923
+ // private toAxiosConfig(params?: IHttpParams): AxiosRequestConfig {
3924
+ toAxiosConfig(e) {
3925
+ if (e) {
3926
+ const t = Object.assign({}, this.axios.defaults);
3927
+ 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));
3928
+ const s = t.headers ?? {};
3929
+ return t.headers = { ...s, ...this.headers }, t;
3930
+ } else
3931
+ return this.axios.defaults;
3932
+ }
3933
+ toCdnUrl(e) {
3934
+ e = this.fixBaseUrl(e);
3935
+ const t = this.context.conf().getCdnUrl() || "";
3936
+ if (t.length > 0 && e !== "/conf/public") {
3937
+ const s = "" + e;
3938
+ (s.startsWith("/infra/public") || s.startsWith("/assets") || /^\/([^\/]*)\/public/.test(s)) && (e = t + s);
3939
+ }
3940
+ return e;
3941
+ }
3942
+ mapAxiosError(e, t) {
3943
+ e.response ? this._latestResponse = e.response : e.request ? this._latestResponse = {
3944
+ status: 408,
3945
+ statusText: ERROR_CODE.TIME_OUT
3946
+ } : this._latestResponse = {
3947
+ status: 500,
3948
+ statusText: ERROR_CODE.UNKNOWN
3949
+ };
3950
+ const { status: s, statusText: r, headers: i, data: o } = this._latestResponse;
3951
+ return t != null && t.disableNotifications || notify.events().publish(LAYER_NAME.TRANSPORT, {
3952
+ name: EVENT_NAME.ERROR_OCCURED,
3953
+ data: {
3954
+ params: t,
3955
+ response: { status: s, statusText: r, headers: i },
3956
+ payload: o
4072
3957
  }
4073
- });
3958
+ }), o;
4074
3959
  }
4075
- }
4076
- class WikiBehaviour extends AbstractBehaviourService {
4077
- constructor() {
4078
- super(...arguments);
4079
- u(this, "APP", "wiki");
4080
- u(this, "RESOURCE", "wiki");
3960
+ mapAxiosResponse(e, t) {
3961
+ return this._latestResponse = e, e.data;
4081
3962
  }
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();
3963
+ get latestResponse() {
3964
+ return this._latestResponse;
4098
3965
  }
4099
- }
4100
- class WorkspaceBehaviour extends AbstractBehaviourService {
4101
- constructor() {
4102
- super(...arguments);
4103
- u(this, "APP", "workspace");
4104
- u(this, "RESOURCE", "workspace");
3966
+ isResponseError() {
3967
+ return this.latestResponse.status < 200 || this.latestResponse.status >= 300;
4105
3968
  }
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
- });
3969
+ async get(e, t) {
3970
+ try {
3971
+ const s = await this.axios.get(
3972
+ this.toCdnUrl(e),
3973
+ this.toAxiosConfig(t)
3974
+ );
3975
+ return this.mapAxiosResponse(s, t);
3976
+ } catch (s) {
3977
+ throw this.mapAxiosError(s, t);
3978
+ }
4129
3979
  }
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
- }
3980
+ async post(e, t, s) {
3981
+ try {
3982
+ const r = await this.axios.post(
3983
+ this.fixBaseUrl(e),
3984
+ t,
3985
+ this.toAxiosConfig(s)
3986
+ );
3987
+ return this.mapAxiosResponse(r, s);
3988
+ } catch (r) {
3989
+ throw this.mapAxiosError(r, s);
4147
3990
  }
4148
- return this.resourceProducingApps;
4149
3991
  }
4150
- static registerCustomBehaviour(e, t, s) {
4151
- this.registry.register({ application: e, resourceType: t }, s);
3992
+ async postFile(e, t, s) {
3993
+ const r = this.toAxiosConfig(s);
3994
+ r.headers && r.headers["Content-Type"] && delete r.headers["Content-Type"];
3995
+ try {
3996
+ const i = await this.axios.post(this.fixBaseUrl(e), t, {
3997
+ ...r,
3998
+ headers: {
3999
+ "Content-Type": "multipart/form-data"
4000
+ }
4001
+ });
4002
+ return this.mapAxiosResponse(i, s);
4003
+ } catch (i) {
4004
+ throw this.mapAxiosError(i, s);
4005
+ }
4152
4006
  }
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)
4007
+ async postJson(e, t, s) {
4008
+ const r = this.toAxiosConfig();
4009
+ r.headers && (r.headers["Content-Type"] = "application/json");
4010
+ try {
4011
+ const i = await this.axios.post(
4012
+ this.fixBaseUrl(e),
4013
+ t,
4014
+ this.toAxiosConfig(s)
4159
4015
  );
4160
- });
4016
+ return this.mapAxiosResponse(i, s);
4017
+ } catch (i) {
4018
+ throw this.mapAxiosError(i, s);
4019
+ }
4161
4020
  }
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;
4021
+ async put(e, t, s) {
4022
+ try {
4023
+ const r = await this.axios.put(
4024
+ this.fixBaseUrl(e),
4025
+ t,
4026
+ this.toAxiosConfig(s)
4027
+ );
4028
+ return this.mapAxiosResponse(r, s);
4029
+ } catch (r) {
4030
+ throw this.mapAxiosError(r, s);
4218
4031
  }
4219
- return r.APP = t, r;
4220
4032
  }
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;
4033
+ async putFile(e, t, s) {
4034
+ try {
4035
+ const r = this.toAxiosConfig(s);
4036
+ r.headers && r.headers["Content-Type"] && delete r.headers["Content-Type"];
4037
+ const i = await this.axios.put(this.fixBaseUrl(e), t, {
4038
+ ...r,
4039
+ headers: {
4040
+ "Content-Type": "multipart/form-data"
4041
+ }
4042
+ });
4043
+ return this.mapAxiosResponse(i, s);
4044
+ } catch (r) {
4045
+ throw this.mapAxiosError(r, s);
4046
+ }
4233
4047
  }
4234
- get http() {
4235
- return this.odeServices.http();
4048
+ async putJson(e, t, s) {
4049
+ const r = this.toAxiosConfig(s);
4050
+ r.headers && (r.headers["Content-Type"] = "application/json");
4051
+ try {
4052
+ const i = await this.axios.put(this.fixBaseUrl(e), t, r);
4053
+ return this.mapAxiosResponse(i, s);
4054
+ } catch (i) {
4055
+ throw this.mapAxiosError(i, s);
4056
+ }
4236
4057
  }
4237
- get events() {
4238
- return this.odeServices.notify().events();
4058
+ async patch(e, t, s) {
4059
+ try {
4060
+ const r = await this.axios.patch(
4061
+ this.fixBaseUrl(e),
4062
+ t,
4063
+ this.toAxiosConfig(s)
4064
+ );
4065
+ return this.mapAxiosResponse(r, s);
4066
+ } catch (r) {
4067
+ throw this.mapAxiosError(r, s);
4068
+ }
4239
4069
  }
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
- });
4070
+ async patchFile(e, t, s) {
4071
+ try {
4072
+ const r = this.toAxiosConfig(s);
4073
+ r.headers && r.headers["Content-Type"] && delete r.headers["Content-Type"];
4074
+ const i = await this.axios.patch(this.fixBaseUrl(e), t, {
4075
+ ...r,
4076
+ headers: {
4077
+ "Content-Type": "multipart/form-data"
4078
+ }
4079
+ });
4080
+ return this.mapAxiosResponse(i, s);
4081
+ } catch (r) {
4082
+ throw this.mapAxiosError(r, s);
4083
+ }
4246
4084
  }
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)
4085
+ async patchJson(e, t, s) {
4086
+ const r = this.toAxiosConfig(s);
4087
+ r.headers && (r.headers["Content-Type"] = "application/json");
4088
+ try {
4089
+ const i = await this.axios.patch(this.fixBaseUrl(e), t, r);
4090
+ return this.mapAxiosResponse(i, s);
4091
+ } catch (i) {
4092
+ throw this.mapAxiosError(i, s);
4093
+ }
4094
+ }
4095
+ async delete(e, t) {
4096
+ try {
4097
+ const s = await this.axios.delete(
4098
+ this.fixBaseUrl(e),
4099
+ this.toAxiosConfig(t)
4253
4100
  );
4101
+ return this.mapAxiosResponse(s, t);
4102
+ } catch (s) {
4103
+ throw this.mapAxiosError(s, t);
4254
4104
  }
4255
- return this;
4256
4105
  }
4257
- destroy() {
4258
- this.subscription && (this.subscription.revoke(), delete this.subscription);
4106
+ async deleteJson(e, t) {
4107
+ try {
4108
+ const s = await this.axios.delete(this.fixBaseUrl(e), {
4109
+ data: t
4110
+ });
4111
+ return this.mapAxiosResponse(s);
4112
+ } catch (s) {
4113
+ throw this.mapAxiosError(s);
4114
+ }
4115
+ }
4116
+ getScript(e, t, s) {
4117
+ const r = s ?? "exports", i = this.toAxiosConfig(t);
4118
+ return i.headers && (i.headers.Accept = "application/javascript"), this.axios.get(this.toCdnUrl(e), i).then((o) => this.mapAxiosResponse(o, t)).then((o) => {
4119
+ try {
4120
+ const a = `"use strict";var ${r.split(".")[0]}={};${o};return ${r};`;
4121
+ return Function(a)();
4122
+ } catch {
4123
+ return o;
4124
+ }
4125
+ }).catch((o) => {
4126
+ throw this.mapAxiosError(o, t), o;
4127
+ });
4128
+ }
4129
+ loadScript(e, t) {
4130
+ return loadedScripts[e] ? Promise.resolve() : this.getScript(e, t).then((s) => {
4131
+ loadedScripts[e] = !0;
4132
+ });
4259
4133
  }
4260
4134
  }
4261
- class DataService {
4135
+ const R = class R {
4136
+ // in minutes. Applies to recorded videos.
4262
4137
  constructor(e) {
4263
- u(this, "_webBroker");
4264
- u(this, "app");
4265
- u(this, "user");
4266
- u(this, "profile");
4267
- this.odeServices = e;
4138
+ this.context = e;
4139
+ }
4140
+ get http() {
4141
+ return this.context.http();
4268
4142
  }
4269
4143
  get conf() {
4270
- return this.odeServices.conf();
4144
+ return this.context.conf();
4271
4145
  }
4272
- get notify() {
4273
- return this.odeServices.notify();
4146
+ /**
4147
+ * Returns the video app public conf (maxWeight, maxDuration and accepted extensions)
4148
+ * @returns the Video app public conf
4149
+ */
4150
+ async getVideoConf() {
4151
+ var t;
4152
+ const e = await this.conf.getPublicConf(
4153
+ APP$4.VIDEO
4154
+ );
4155
+ return {
4156
+ maxWeight: (e == null ? void 0 : e["max-videosize-mbytes"]) ?? R.MAX_WEIGHT,
4157
+ maxDuration: (e == null ? void 0 : e["max-videoduration-minutes"]) ?? R.MAX_DURATION,
4158
+ acceptVideoUploadExtensions: ((t = e == null ? void 0 : e["accept-videoupload-extensions"]) == null ? void 0 : t.map(
4159
+ (s) => s.toUpperCase()
4160
+ )) ?? []
4161
+ };
4274
4162
  }
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.");
4163
+ /**
4164
+ * Starts the encoding process and check when video is fully processed.
4165
+ * @param params cf VideoUploadParams
4166
+ * @returns a VideoCheckResponse
4167
+ */
4168
+ async upload({
4169
+ data: e,
4170
+ appCode: t,
4171
+ captation: s,
4172
+ duration: r
4173
+ }) {
4174
+ if (!e.file)
4175
+ throw new Error("Invalid video file.");
4176
+ if (!e.filename)
4177
+ throw new Error("Invalid video filename");
4178
+ const i = `${e.browser.name} ${e.browser.version}`, o = new FormData();
4179
+ 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);
4180
+ let a = `/video/encode?captation=${s}`;
4181
+ r && (a += `&duration=${r}`);
4182
+ const c = await this.http.post(
4183
+ a,
4184
+ o,
4185
+ { headers: { "Content-Type": "multipart/form-data" } }
4186
+ );
4187
+ if (c.state == "running") {
4188
+ let l = 0, h = 1;
4189
+ do {
4190
+ const E = h + l;
4191
+ await new Promise(
4192
+ (y) => setTimeout(y, E * 1e3)
4193
+ ), l = h, h = Math.min(8, E);
4194
+ const p = await this.http.get(
4195
+ `/video/status/${c.processid}`
4196
+ );
4197
+ if (p.state == "succeed")
4198
+ return p.videoworkspaceid && p.videosize && this.context.data().trackVideoSave(
4199
+ p.videoworkspaceid,
4200
+ Math.round(r),
4201
+ p.videosize,
4202
+ s,
4203
+ e.url,
4204
+ i,
4205
+ e.device
4206
+ ), p;
4207
+ if (p.state == "error")
4208
+ break;
4209
+ } while (!0);
4284
4210
  }
4211
+ throw new Error("Video cannot be uploaded.");
4285
4212
  }
4286
- //FIXME When to call that ??
4287
- predestroy() {
4288
- this._webBroker && (this._webBroker.destroy(), delete this._webBroker);
4213
+ };
4214
+ u(R, "MAX_WEIGHT", 50), // in Mbytes. Applies to uploaded videos.
4215
+ u(R, "MAX_DURATION", 3);
4216
+ let VideoService = R;
4217
+ class WidgetService {
4218
+ constructor(e) {
4219
+ this.context = e;
4289
4220
  }
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
- });
4221
+ get session() {
4222
+ return this.context.session();
4296
4223
  }
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;
4224
+ async getSystemWidgets() {
4225
+ try {
4226
+ const e = await this.session.getUser();
4227
+ return e == null ? void 0 : e.widgets;
4228
+ } catch (e) {
4229
+ throw console.error("[WidgetService] getSystemWidgets failed", e), e;
4230
+ }
4299
4231
  }
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);
4232
+ async getPreferences() {
4233
+ return await this.context.conf().getPreference("widgets");
4312
4234
  }
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);
4235
+ async setPreferences(e) {
4236
+ await this.context.conf().savePreference("widgets", e);
4237
+ }
4238
+ }
4239
+ const defaultMappers = {
4240
+ csv: function({ type: n, extension: e }) {
4241
+ return MimeTypeUtils.INSTANCE.isCsvLike(n, e);
4242
+ },
4243
+ doc: function({ type: n, extension: e }) {
4244
+ return MimeTypeUtils.INSTANCE.isWordLike(n, e) ? !0 : n.indexOf("document") !== -1 && n.indexOf("wordprocessing") !== -1;
4245
+ },
4246
+ xls: function({ type: n, extension: e }) {
4247
+ return MimeTypeUtils.INSTANCE.isExcelLike(n, e) ? !0 : n.indexOf("document") !== -1 && n.indexOf("spreadsheet") !== -1 || n.indexOf("ms-excel") !== -1;
4248
+ },
4249
+ img: function({ type: n }) {
4250
+ return n.indexOf("image") !== -1;
4251
+ },
4252
+ pdf: function({ type: n }) {
4253
+ return n.indexOf("pdf") !== -1 || n === "application/x-download";
4254
+ },
4255
+ ppt: function({ type: n, extension: e }) {
4256
+ return MimeTypeUtils.INSTANCE.isPowerpointLike(n, e) ? !0 : n.indexOf("document") !== -1 && n.indexOf("presentation") !== -1 || n.indexOf("powerpoint") !== -1;
4257
+ },
4258
+ txt: function({ type: n, extension: e }) {
4259
+ return MimeTypeUtils.INSTANCE.isTxtLike(n, e);
4260
+ },
4261
+ md: function({ type: n, extension: e }) {
4262
+ return MimeTypeUtils.INSTANCE.isMdLike(n, e);
4263
+ },
4264
+ video: function({ type: n }) {
4265
+ return n.indexOf("video") !== -1;
4266
+ },
4267
+ audio: function({ type: n }) {
4268
+ return n.indexOf("audio") !== -1;
4269
+ },
4270
+ zip: function({ type: n }) {
4271
+ return n.indexOf("zip") !== -1 || n.indexOf("rar") !== -1 || n.indexOf("tar") !== -1 || n.indexOf("7z") !== -1;
4323
4272
  }
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);
4273
+ }, v = class v {
4274
+ /* Similar role notion as in infra-front > workspace > Model.ts */
4275
+ static getRole(e) {
4276
+ var t, s;
4277
+ return v.role(
4278
+ (t = e.metadata) == null ? void 0 : t["content-type"],
4279
+ !1,
4280
+ (s = e.metadata) == null ? void 0 : s.extension
4281
+ );
4330
4282
  }
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);
4283
+ /* Similar role notion as in infra-front > workspace > Model.ts */
4284
+ static role(e, t = !1, s) {
4285
+ if (s && (s = s.trim()), !e) return "unknown";
4286
+ this.roleMappers || console.warn("[DocumentHelper.role] should not have empty roles", this);
4287
+ const r = { type: e, previewRole: t, extension: s };
4288
+ for (const i of this.roleMappers) {
4289
+ const o = i(r);
4290
+ if (o)
4291
+ return o;
4292
+ }
4293
+ return "unknown";
4336
4294
  }
4337
- }
4338
- class ReactionsService {
4339
- constructor(e, t, s) {
4340
- this.context = e, this.module = t, this.resourceType = s;
4295
+ };
4296
+ // FIXME add edumedia support
4297
+ u(v, "roleMappers", [
4298
+ (e) => Object.keys(defaultMappers).find((s) => defaultMappers[s](e))
4299
+ ]);
4300
+ let DocumentHelper = v;
4301
+ class WorkspaceService {
4302
+ constructor(e) {
4303
+ this.context = e;
4341
4304
  }
4342
4305
  get http() {
4343
4306
  return this.context.http();
4344
4307
  }
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;
4308
+ extractMetadata(e) {
4309
+ const t = e.name || "", s = t.split("."), r = e.type || "application/octet-stream", i = s.length > 1 ? s[s.length - 1] : "", o = {
4310
+ "content-type": r,
4311
+ filename: t,
4312
+ size: e.size,
4313
+ extension: i,
4314
+ role: DocumentHelper.role(r, !1, i)
4315
+ }, a = t.replace("." + o.extension, ""), c = o.extension ? a + "." + o.extension : a;
4316
+ return { basename: a, fullname: c, metadata: o };
4359
4317
  }
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}`
4318
+ async saveFile(e, t) {
4319
+ const { fullname: s, metadata: r } = this.extractMetadata(e), i = new FormData();
4320
+ i.append("file", e, s);
4321
+ const o = [];
4322
+ ((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}`);
4323
+ const a = await this.http.postFile(
4324
+ `/workspace/document?${o.join("&")}`,
4325
+ i
4363
4326
  );
4364
- return this.http.isResponseError() ? void 0 : r;
4327
+ if (this.http.isResponseError())
4328
+ throw this.http.latestResponse.statusText;
4329
+ return a;
4365
4330
  }
4366
- async deleteReaction(e) {
4367
- await this.http.delete(
4368
- `/audience/reactions/${this.module}/${this.resourceType}/${e}`
4331
+ async updateFile(e, t, s) {
4332
+ const { fullname: r, metadata: i } = this.extractMetadata(t), o = new FormData();
4333
+ o.append("file", t, r);
4334
+ const a = [];
4335
+ 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}`);
4336
+ const c = await this.http.putFile(
4337
+ `/workspace/document/${e}?${a.join("&")}`,
4338
+ o
4369
4339
  );
4340
+ if (this.http.isResponseError())
4341
+ throw this.http.latestResponse.statusText;
4342
+ return c;
4370
4343
  }
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
- );
4344
+ async deleteFile(e) {
4345
+ const t = e.map((s) => s._id);
4346
+ if (t.length == 0)
4347
+ Promise.resolve(null);
4348
+ else if (await this.http.deleteJson("/workspace/documents", {
4349
+ ids: t
4350
+ }), this.http.isResponseError())
4351
+ throw this.http.latestResponse.statusText;
4379
4352
  }
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
- );
4353
+ async acceptDocuments(e) {
4354
+ const t = await this.context.session().getUser();
4355
+ return (s) => s.deleted && s.trasher ? (t == null ? void 0 : t.userId) == s.trasher : !0;
4388
4356
  }
4389
- }
4390
- class ViewsService {
4391
- constructor(e, t, s) {
4392
- this.context = e, this.module = t, this.resourceType = s;
4357
+ async searchDocuments(e) {
4358
+ const t = e.filter !== "external" || e.parentId ? await this.http.get("/workspace/documents", {
4359
+ queryParams: { ...e, _: (/* @__PURE__ */ new Date()).getTime() }
4360
+ }) : [], s = await this.acceptDocuments(e);
4361
+ return t.filter(s);
4393
4362
  }
4394
- get http() {
4395
- return this.context.http();
4363
+ async listDocuments(e, t) {
4364
+ return this.searchDocuments({ filter: e, parentId: t, includeall: !0 });
4396
4365
  }
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;
4366
+ /**
4367
+ * Duplicate and transfers documents if needed to a different folder with the specified application and visibility.
4368
+ * @param documents - The array of documents to transfer.
4369
+ * @param application - The application to associate with the transferred documents.
4370
+ * @param visibility - The visibility of the transferred documents. Defaults to "protected".
4371
+ * @returns A Promise that resolves to an array of transferred WorkspaceElements.
4372
+ */
4373
+ async transferDocuments(e, t, s = "protected") {
4374
+ const r = [];
4375
+ if (e.forEach((i) => {
4376
+ (s === "public" && !i.public || !i.public && !i.protected) && r.push(i);
4377
+ }), r.length > 0) {
4378
+ const i = await this.http.post(
4379
+ "/workspace/documents/transfer",
4380
+ {
4381
+ application: t,
4382
+ visibility: s,
4383
+ ids: r.map((o) => o._id)
4384
+ }
4385
+ );
4386
+ if (this.http.isResponseError())
4387
+ throw this.http.latestResponse.statusText;
4388
+ return r.forEach((o, a) => {
4389
+ const c = e.findIndex(
4390
+ (l) => l._id === o._id
4391
+ );
4392
+ 0 <= c && c < e.length && (e[c] = i[a]);
4393
+ }), e.filter((o) => !!o);
4394
+ }
4395
+ return e;
4402
4396
  }
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;
4397
+ /**
4398
+ * Get the URL of the thumbnail of a workspace element (or its URL),
4399
+ * or `null` if none exists or can be created.
4400
+ */
4401
+ getThumbnailUrl(e, t = 0, s = 0) {
4402
+ var i, o;
4403
+ const r = t > 0 || s > 0 ? `${t}x${s}` : "120x120";
4404
+ if (typeof e == "string")
4405
+ return e.includes("data:image") || e.includes("thumbnail") ? e : `${e}${e.includes("?") ? "&" : "?"}thumbnail=${r}`;
4406
+ {
4407
+ const a = `/workspace/${e.public ? "pub/" : ""}document/${e._id}?thumbnail=`, c = e.thumbnails;
4408
+ if ((o = (i = e.metadata) == null ? void 0 : i["content-type"]) != null && o.includes("video")) {
4409
+ const l = c && Object.keys(c).length > 0 ? Object.keys(c)[0] : null;
4410
+ return l ? a + l : null;
4411
+ } else
4412
+ return a + r;
4413
+ }
4408
4414
  }
4409
- trigger(e) {
4410
- return this.http.post(
4411
- `/audience/views/${this.module}/${this.resourceType}/${e}`
4412
- );
4415
+ /**
4416
+ * Get the URL of the file of a workspace element (or its URL),
4417
+ * or `null` if none exists or can be created.
4418
+ * @param filter - The filter to apply to the workspace element.
4419
+ * @param withChildren - If true, include all children folders.
4420
+ * @param parentId - The ID of the parent folder to list.
4421
+ * @param directShared - If true, include only elements directly shared with the user.
4422
+ *
4423
+ */
4424
+ listFolder(e, t = !1, s, r) {
4425
+ const i = {
4426
+ filter: e,
4427
+ hierarchical: t,
4428
+ parentId: s,
4429
+ directShared: r
4430
+ };
4431
+ return this.http.get("/workspace/folders/list", {
4432
+ queryParams: i
4433
+ });
4413
4434
  }
4414
- }
4415
- class AudienceService {
4416
- constructor(e, t, s) {
4417
- this.context = e, this.module = t, this.resourceType = s;
4435
+ /**
4436
+ * List all folders in the workspace.
4437
+ * @param withChildren - If true, include all children folders.
4438
+ * @param parentId - The ID of the parent folder to list.
4439
+ * @returns A promise that resolves to an array of WorkspaceElement objects.
4440
+ */
4441
+ listOwnerFolders(e, t) {
4442
+ return this.listFolder("owner", e, t);
4418
4443
  }
4419
- get views() {
4420
- return new ViewsService(this.context, this.module, this.resourceType);
4444
+ /**
4445
+ * List all shared folders in the workspace.
4446
+ * @param withChildren - If true, include all children folders.
4447
+ * @param parentId - The ID of the parent folder to list.
4448
+ * @returns A promise that resolves to an array of WorkspaceElement objects.
4449
+ */
4450
+ listSharedFolders(e, t) {
4451
+ return this.listFolder("shared", e, t, !0);
4421
4452
  }
4422
- get reactions() {
4423
- return new ReactionsService(this.context, this.module, this.resourceType);
4453
+ /**
4454
+ * Create a new folder in the workspace.
4455
+ * @param name - The name of the new folder.
4456
+ * @param parentId - The ID of the parent folder where the new folder will be created.
4457
+ * @returns void
4458
+ */
4459
+ createFolder(e, t) {
4460
+ const s = new FormData();
4461
+ return s.append("name", e), t && s.append("parentFolderId", t), this.http.postFile("/workspace/folder", s);
4424
4462
  }
4425
4463
  }
4426
4464
  class OdeServices {
@@ -4437,9 +4475,10 @@ class OdeServices {
4437
4475
  u(this, "_session");
4438
4476
  u(this, "_share");
4439
4477
  u(this, "_video");
4478
+ u(this, "_widget");
4440
4479
  u(this, "_workspace");
4441
4480
  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);
4481
+ 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._widget = new WidgetService(this), this._workspace = new WorkspaceService(this), this._embedder = new EmbedderService(this);
4443
4482
  }
4444
4483
  initialize() {
4445
4484
  return this._data.initialize(), this;
@@ -4489,6 +4528,9 @@ class OdeServices {
4489
4528
  video() {
4490
4529
  return this._video;
4491
4530
  }
4531
+ widget() {
4532
+ return this._widget;
4533
+ }
4492
4534
  workspace() {
4493
4535
  return this._workspace;
4494
4536
  }
@@ -4689,17 +4731,17 @@ class WidgetFramework {
4689
4731
  var a;
4690
4732
  const i = ((a = r.find((c) => c.child === t.skin)) == null ? void 0 : a.parent) === "panda" ? secondLevelWidgets : firstLevelWidgets;
4691
4733
  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,
4734
+ const h = c.platformConf.name;
4735
+ return i.indexOf(h) !== -1 ? !1 : (this._userPrefs[h] || (this._userPrefs[h] = {
4736
+ index: defaultWidgetOrder[h] ?? 999,
4695
4737
  show: !0,
4696
4738
  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);
4739
+ }), 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
4740
  });
4699
4741
  const o = new Idiom();
4700
4742
  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;
4743
+ const h = o.translate(`timeline.settings.${c.platformConf.name}`).toLowerCase(), E = o.translate(`timeline.settings.${l.platformConf.name}`).toLowerCase();
4744
+ return h < E ? -1 : h > E ? 1 : 0;
4703
4745
  });
4704
4746
  });
4705
4747
  }
@@ -4724,22 +4766,7 @@ class Widget {
4724
4766
  this._userPref = e, this._userPref.position = this._userPref.position ?? widgets.lookupDefaultPosition(this._platformConf.name) ?? "left";
4725
4767
  }
4726
4768
  }
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 = {
4769
+ const widgets = new WidgetFramework(), WIDGET_NAME = {
4743
4770
  LAST_INFOS: "last-infos-widget",
4744
4771
  BIRTHDAY: "birthday",
4745
4772
  CALENDAR: "calendar-widget",
@@ -4776,7 +4803,6 @@ export {
4776
4803
  FOLDER,
4777
4804
  ITimelineFactory,
4778
4805
  LAYER_NAME,
4779
- LastInfosWidget,
4780
4806
  NotifyFrameworkFactory,
4781
4807
  ReactionTypes,
4782
4808
  ResourceService,