@rancher/shell 0.3.4 → 0.3.5

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.
Files changed (246) hide show
  1. package/assets/styles/app.scss +1 -1
  2. package/assets/styles/fonts/_fontstack.scss +11 -11
  3. package/assets/styles/vendor/vue-js-modal.scss +3 -3
  4. package/assets/translations/en-us.yaml +92 -22
  5. package/assets/translations/zh-hans.yaml +84 -15
  6. package/babel.config.js +13 -0
  7. package/chart/gatekeeper.vue +77 -0
  8. package/chart/istio.vue +108 -111
  9. package/chart/logging/index.vue +13 -4
  10. package/chart/monitoring/index.vue +15 -5
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/chart/rancher-backup/index.vue +10 -3
  13. package/cloud-credential/aws.vue +1 -1
  14. package/cloud-credential/digitalocean.vue +1 -1
  15. package/cloud-credential/gcp.vue +1 -1
  16. package/cloud-credential/generic.vue +2 -2
  17. package/cloud-credential/linode.vue +1 -1
  18. package/cloud-credential/pnap.vue +1 -1
  19. package/components/ActionMenu.vue +3 -4
  20. package/components/AssignTo.vue +1 -1
  21. package/components/AsyncButton.vue +1 -1
  22. package/components/BannerGraphic.vue +1 -1
  23. package/components/ButtonDropdown.vue +2 -3
  24. package/components/ChartPsp.vue +76 -0
  25. package/components/CruResource.vue +6 -2
  26. package/components/DashboardMetrics.vue +12 -10
  27. package/components/DetailText.vue +1 -1
  28. package/components/DisableAuthProviderModal.vue +1 -1
  29. package/components/EmberPage.vue +1 -1
  30. package/components/EtcdInfoBanner.vue +5 -4
  31. package/components/ExplorerMembers.vue +1 -1
  32. package/components/ExplorerProjectsNamespaces.vue +14 -1
  33. package/components/FileDiff.vue +6 -7
  34. package/components/GrafanaDashboard.vue +18 -21
  35. package/components/LazyImage.vue +10 -12
  36. package/components/LogItem.vue +1 -1
  37. package/components/Markdown.vue +1 -1
  38. package/components/PromptRemove.vue +2 -2
  39. package/components/PromptRestore.vue +1 -1
  40. package/components/ResourceDetail/Masthead.vue +16 -0
  41. package/components/ResourceDetail/index.vue +21 -4
  42. package/components/ResourceList/index.vue +1 -1
  43. package/components/ResourceTable.vue +4 -1
  44. package/components/SingleClusterInfo.vue +2 -2
  45. package/components/SortableTable/THead.vue +1 -1
  46. package/components/SortableTable/index.vue +5 -2
  47. package/components/__tests__/AsyncButton.test.ts +3 -1
  48. package/components/__tests__/ChartPsp.test.ts +75 -0
  49. package/components/__tests__/CruResource.test.ts +3 -1
  50. package/components/auth/Principal.vue +1 -1
  51. package/components/fleet/FleetBundles.vue +3 -1
  52. package/components/fleet/FleetClusters.vue +1 -2
  53. package/components/fleet/FleetIntro.vue +9 -1
  54. package/components/fleet/FleetNoWorkspaces.vue +62 -0
  55. package/components/fleet/FleetSummary.vue +7 -1
  56. package/components/form/LabeledSelect.vue +14 -11
  57. package/components/form/MatchExpressions.vue +17 -2
  58. package/components/form/NameNsDescription.vue +31 -45
  59. package/components/form/ResourceSelector.vue +1 -1
  60. package/components/form/SecretSelector.vue +5 -1
  61. package/components/form/ServiceNameSelect.vue +1 -1
  62. package/components/form/SimpleSecretSelector.vue +9 -9
  63. package/components/form/__tests__/LabeledSelect.test.ts +138 -0
  64. package/components/form/__tests__/NameNsDescription.ts +32 -0
  65. package/components/formatter/InternalExternalIP.vue +6 -0
  66. package/components/formatter/InvolvedObjectLink.vue +54 -0
  67. package/components/formatter/Link.vue +20 -4
  68. package/components/formatter/LinkName.vue +6 -1
  69. package/components/formatter/ServiceTargets.vue +1 -1
  70. package/components/nav/Group.vue +2 -2
  71. package/components/nav/NamespaceFilter.vue +15 -11
  72. package/components/nav/TopLevelMenu.vue +2 -4
  73. package/components/nav/Type.vue +1 -1
  74. package/components/nav/WorkspaceSwitcher.vue +46 -5
  75. package/config/labels-annotations.js +17 -0
  76. package/config/product/auth.js +3 -2
  77. package/config/product/explorer.js +11 -4
  78. package/config/product/fleet.js +2 -0
  79. package/config/router.js +414 -0
  80. package/config/table-headers.js +10 -2
  81. package/config/types.js +11 -8
  82. package/config/uiplugins.js +30 -0
  83. package/content/docs/en-us/whats-new.md +10 -0
  84. package/content/docs/zh-hans/whats-new.md +11 -1
  85. package/core/plugin-routes.ts +23 -0
  86. package/creators/app/app.package.json +2 -1
  87. package/creators/app/files/.eslintrc.js +1 -1
  88. package/creators/app/files/babel.config.js +1 -18
  89. package/creators/app/files/vue.config.js +7 -0
  90. package/creators/app/init +5 -5
  91. package/creators/pkg/files/.github/workflows/build-extension.yml +111 -0
  92. package/creators/pkg/init +35 -4
  93. package/creators/update/init +1 -1
  94. package/detail/constraints.gatekeeper.sh.constraint.vue +20 -10
  95. package/detail/fleet.cattle.io.gitrepo.vue +19 -11
  96. package/detail/harvesterhci.io.management.cluster.vue +3 -3
  97. package/detail/provisioning.cattle.io.cluster.vue +54 -12
  98. package/detail/workload/index.vue +3 -3
  99. package/dialog/AddClusterMemberDialog.vue +1 -1
  100. package/dialog/AddProjectMemberDialog.vue +2 -2
  101. package/dialog/AddonConfigConfirmationDialog.vue +27 -15
  102. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  103. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  104. package/dialog/GenericPrompt.vue +18 -6
  105. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  106. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  107. package/dialog/ScaleMachineDownDialog.vue +1 -1
  108. package/edit/auth/github.vue +8 -8
  109. package/edit/auth/googleoauth.vue +5 -5
  110. package/edit/auth/ldap/index.vue +1 -1
  111. package/edit/auth/oidc.vue +1 -1
  112. package/edit/auth/saml.vue +1 -1
  113. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  114. package/edit/fleet.cattle.io.clustergroup.vue +6 -4
  115. package/edit/fleet.cattle.io.gitrepo.vue +16 -3
  116. package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
  117. package/edit/management.cattle.io.fleetworkspace.vue +141 -6
  118. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
  119. package/edit/management.cattle.io.setting.vue +1 -1
  120. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
  121. package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
  122. package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
  123. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  124. package/edit/namespace.vue +2 -2
  125. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
  126. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  127. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +10 -0
  128. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
  129. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
  130. package/edit/provisioning.cattle.io.cluster/rke2.vue +248 -84
  131. package/edit/resources.cattle.io.backup.vue +1 -1
  132. package/edit/service.vue +1 -1
  133. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
  134. package/edit/workload/__tests__/Job.test.ts +3 -1
  135. package/edit/workload/index.vue +8 -3
  136. package/edit/workload/mixins/workload.js +16 -0
  137. package/layouts/default.vue +7 -3
  138. package/list/fleet.cattle.io.bundle.vue +6 -3
  139. package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
  140. package/list/fleet.cattle.io.gitrepo.vue +44 -5
  141. package/list/management.cattle.io.fleetworkspace.vue +45 -0
  142. package/list/node.vue +69 -16
  143. package/list/provisioning.cattle.io.cluster.vue +30 -1
  144. package/machine-config/azure.vue +97 -38
  145. package/middleware/authenticated.js +34 -0
  146. package/mixins/chart.js +73 -2
  147. package/mixins/resource-fetch.js +2 -2
  148. package/models/apps.statefulset.js +28 -0
  149. package/models/cluster/node.js +23 -2
  150. package/models/cluster.x-k8s.io.machine.js +4 -2
  151. package/models/clusterroletemplatebinding.js +7 -0
  152. package/models/constraints.gatekeeper.sh.constraint.js +9 -0
  153. package/models/fleet.cattle.io.cluster.js +19 -10
  154. package/models/fleet.cattle.io.gitrepo.js +7 -2
  155. package/models/management.cattle.io.cluster.js +1 -1
  156. package/models/management.cattle.io.fleetworkspace.js +12 -0
  157. package/models/management.cattle.io.gitreporestriction.js +5 -0
  158. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
  159. package/models/provisioning.cattle.io.cluster.js +7 -5
  160. package/nuxt/App.js +210 -0
  161. package/nuxt/axios.js +186 -0
  162. package/nuxt/client.js +817 -0
  163. package/nuxt/components/nuxt-build-indicator.vue +143 -0
  164. package/nuxt/components/nuxt-child.js +122 -0
  165. package/nuxt/components/nuxt-error.vue +98 -0
  166. package/nuxt/components/nuxt-link.client.js +98 -0
  167. package/nuxt/components/nuxt-link.server.js +16 -0
  168. package/nuxt/components/nuxt-loading.vue +154 -0
  169. package/nuxt/components/nuxt.js +101 -0
  170. package/nuxt/cookie-universal-nuxt.js +9 -0
  171. package/nuxt/empty.js +1 -0
  172. package/nuxt/index.js +365 -0
  173. package/nuxt/jsonp.js +82 -0
  174. package/nuxt/loading.html +39 -0
  175. package/nuxt/middleware.js +12 -0
  176. package/nuxt/mixins/fetch.client.js +90 -0
  177. package/nuxt/mixins/fetch.server.js +69 -0
  178. package/nuxt/portal-vue.js +4 -0
  179. package/nuxt/server.js +312 -0
  180. package/nuxt/store.js +178 -0
  181. package/nuxt/utils.js +630 -0
  182. package/nuxt/views/app.template.html +9 -0
  183. package/nuxt/views/error.html +23 -0
  184. package/package.json +5 -9
  185. package/pages/auth/setup.vue +2 -2
  186. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
  187. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  188. package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
  189. package/pages/c/_cluster/apps/charts/install.vue +40 -66
  190. package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
  191. package/pages/c/_cluster/explorer/index.vue +29 -25
  192. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  193. package/pages/c/_cluster/fleet/index.vue +95 -34
  194. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  195. package/pages/c/_cluster/istio/index.vue +5 -5
  196. package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
  197. package/pages/c/_cluster/monitoring/index.vue +7 -0
  198. package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
  199. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
  200. package/pages/c/_cluster/uiplugins/index.vue +49 -17
  201. package/pages/home.vue +9 -4
  202. package/pages/index.vue +10 -1
  203. package/plugins/clean-html-directive.js +31 -0
  204. package/plugins/dashboard-store/actions.js +32 -9
  205. package/plugins/dashboard-store/mutations.js +5 -2
  206. package/plugins/dashboard-store/resource-class.js +8 -1
  207. package/plugins/steve/mutations.js +3 -2
  208. package/plugins/steve/steve-description-class.js +5 -1
  209. package/plugins/steve/subscribe.js +63 -54
  210. package/plugins/steve-create-worker.js +14 -0
  211. package/promptRemove/management.cattle.io.globalrole.vue +2 -2
  212. package/promptRemove/management.cattle.io.project.vue +2 -2
  213. package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
  214. package/promptRemove/pod.vue +1 -1
  215. package/public/index.html +65 -0
  216. package/rancher-components/components/Banner/Banner.test.ts +9 -1
  217. package/rancher-components/components/Banner/Banner.vue +1 -1
  218. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
  219. package/rancher-components/components/Form/Radio/RadioButton.vue +1 -1
  220. package/scripts/build-pkg.sh +1 -0
  221. package/scripts/clean +6 -0
  222. package/scripts/extension/bundle +58 -0
  223. package/scripts/extension/helmpatch +89 -0
  224. package/scripts/extension/publish +314 -0
  225. package/scripts/test-plugins-build.sh +4 -0
  226. package/store/__tests__/index.test.ts +110 -0
  227. package/store/index.js +145 -58
  228. package/store/type-map.js +5 -1
  229. package/tsconfig.default.json +36 -0
  230. package/tsconfig.json +24 -0
  231. package/types/shell/index.d.ts +420 -343
  232. package/utils/__tests__/string.test.ts +12 -0
  233. package/utils/auth.js +65 -0
  234. package/utils/monitoring.js +2 -1
  235. package/utils/position.js +5 -8
  236. package/utils/router.scrollBehavior.js +80 -0
  237. package/utils/select.js +1 -3
  238. package/utils/socket.js +1 -0
  239. package/utils/string.js +13 -0
  240. package/utils/time.js +9 -0
  241. package/vue.config.js +679 -0
  242. package/chart/rancher-alerting-drivers.vue +0 -53
  243. package/chart/rancher-gatekeeper.vue +0 -37
  244. package/creators/app/files/nuxt.config.js +0 -6
  245. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
  246. package/nuxt.config.js +0 -798
@@ -0,0 +1,12 @@
1
+ import { decodeHtml } from '@shell/utils/string';
2
+
3
+ describe('fx: decodeHtml', () => {
4
+ it('should decode HTML values from escaped string into valid markup', () => {
5
+ const text = '<i>whatever</i>';
6
+ const expectation = `<i>whatever</i>`;
7
+
8
+ const result = decodeHtml(text);
9
+
10
+ expect(result).toStrictEqual(expectation);
11
+ });
12
+ });
package/utils/auth.js CHANGED
@@ -2,6 +2,7 @@ import { Popup, popupWindowOptions } from '@shell/utils/window';
2
2
  import { parse as parseUrl, addParam } from '@shell/utils/url';
3
3
  import { BACK_TO, SPA, _EDIT, _FLAGGED } from '@shell/config/query-params';
4
4
  import { MANAGEMENT } from '@shell/config/types';
5
+ import { allHash } from '@shell/utils/promise';
5
6
 
6
7
  export function openAuthPopup(url, provider) {
7
8
  const popup = new Popup(() => {
@@ -79,3 +80,67 @@ export const authProvidersInfo = async(store) => {
79
80
  enabled
80
81
  };
81
82
  };
83
+
84
+ export const checkSchemasForFindAllHash = (types, store) => {
85
+ const hash = {};
86
+
87
+ for (const [key, value] of Object.entries(types)) {
88
+ const schema = store.getters[`${ value.inStoreType }/schemaFor`](value.type);
89
+
90
+ // It could be that user has permissions for GET but not list
91
+ // e.g. Standard user with GitRepo permissions try to fetch list of fleetworkspaces
92
+ // user has ability to GET but not fleet workspaces
93
+ // so optionally define a function that require it to pass before /findAll
94
+ const validSchema = value.schemaValidator ? value.schemaValidator(schema) : !!schema;
95
+
96
+ if (validSchema) {
97
+ hash[key] = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type } );
98
+ }
99
+ }
100
+
101
+ return allHash(hash);
102
+ };
103
+
104
+ export const checkPermissions = (types, getters) => {
105
+ const hash = {};
106
+
107
+ for (const [key, value] of Object.entries(types)) {
108
+ const schema = getters['management/schemaFor'](value.type);
109
+
110
+ if (!schema) {
111
+ hash[key] = false;
112
+
113
+ continue;
114
+ }
115
+
116
+ // It could be that user has permissions for GET but not list
117
+ // e.g. Standard user with GitRepo permissions try to fetch list of fleetworkspaces
118
+ // user has ability to GET but not fleet workspaces
119
+ // so optionally define a function that require it to pass before /findAll
120
+ if (value.schemaValidator) {
121
+ hash[key] = value.schemaValidator(schema);
122
+
123
+ continue;
124
+ }
125
+
126
+ if (value.resourceMethods && schema) {
127
+ hash[key] = value.resourceMethods.every((method) => {
128
+ return (schema.resourceMethods || []).includes(method);
129
+ });
130
+
131
+ continue;
132
+ }
133
+
134
+ if (value.collectionMethods && schema) {
135
+ hash[key] = value.collectionMethods.every((method) => {
136
+ return (schema.collectionMethods || []).includes(method);
137
+ });
138
+
139
+ continue;
140
+ }
141
+
142
+ hash[key] = !!schema;
143
+ }
144
+
145
+ return allHash(hash);
146
+ };
@@ -26,9 +26,10 @@ export function haveV2Monitoring(getters) {
26
26
  if (haveV1Monitoring(getters)) {
27
27
  return false;
28
28
  }
29
+ const inStore = getters['getStoreNameByProductId'];
29
30
 
30
31
  // Just check for the pod monitors CRD
31
- const schemas = getters[`cluster/all`](SCHEMA);
32
+ const schemas = getters[`${ inStore }/all`](SCHEMA);
32
33
  const exists = findBy(schemas, 'id', normalizeType(MONITORING.PODMONITOR));
33
34
 
34
35
  return !!exists;
package/utils/position.js CHANGED
@@ -1,5 +1,4 @@
1
1
  // @TODO replace this with popper.js...
2
- import $ from 'jquery';
3
2
 
4
3
  export const LEFT = 'left';
5
4
  export const RIGHT = 'right';
@@ -10,10 +9,9 @@ export const BOTTOM = 'bottom';
10
9
  export const AUTO = 'auto';
11
10
 
12
11
  export function boundingRect(elem) {
13
- const $elem = $(elem);
14
- const pos = $elem.offset();
15
- const width = $elem.outerWidth(false);
16
- const height = $elem.outerHeight(false);
12
+ const pos = elem.getBoundingClientRect();
13
+ const width = elem.offsetWidth;
14
+ const height = elem.offsetHeight;
17
15
 
18
16
  return {
19
17
  top: pos.top,
@@ -37,9 +35,8 @@ export function fakeRectFor(event) {
37
35
  }
38
36
 
39
37
  export function screenRect() {
40
- const $window = $(window);
41
- const width = $window.width();
42
- const height = $window.height();
38
+ const width = window.innerWidth;
39
+ const height = window.innerHeight;
43
40
  const top = window.pageYOffset;
44
41
  const left = window.pageXOffset;
45
42
 
@@ -0,0 +1,80 @@
1
+ import { getMatchedComponents, setScrollRestoration } from '../nuxt/utils';
2
+
3
+ if (process.client) {
4
+ if ('scrollRestoration' in window.history) {
5
+ setScrollRestoration('manual');
6
+
7
+ // reset scrollRestoration to auto when leaving page, allowing page reload
8
+ // and back-navigation from other pages to use the browser to restore the
9
+ // scrolling position.
10
+ window.addEventListener('beforeunload', () => {
11
+ setScrollRestoration('auto');
12
+ });
13
+
14
+ // Setting scrollRestoration to manual again when returning to this page.
15
+ window.addEventListener('load', () => {
16
+ setScrollRestoration('manual');
17
+ });
18
+ }
19
+ }
20
+
21
+ function shouldScrollToTop(route) {
22
+ const Pages = getMatchedComponents(route);
23
+
24
+ if (Pages.length === 1) {
25
+ const { options = {} } = Pages[0];
26
+
27
+ return options.scrollToTop !== false;
28
+ }
29
+
30
+ return Pages.some(({ options }) => options && options.scrollToTop);
31
+ }
32
+
33
+ export default function(to, from, savedPosition) {
34
+ // If the returned position is falsy or an empty object, will retain current scroll position
35
+ let position = false;
36
+ const isRouteChanged = to !== from;
37
+
38
+ // savedPosition is only available for popstate navigations (back button)
39
+ if (savedPosition) {
40
+ position = savedPosition;
41
+ } else if (isRouteChanged && shouldScrollToTop(to)) {
42
+ position = { x: 0, y: 0 };
43
+ }
44
+
45
+ const nuxt = window.$nuxt;
46
+
47
+ if (
48
+ // Initial load (vuejs/vue-router#3199)
49
+ !isRouteChanged ||
50
+ // Route hash changes
51
+ (to.path === from.path && to.hash !== from.hash)
52
+ ) {
53
+ nuxt.$nextTick(() => nuxt.$emit('triggerScroll'));
54
+ }
55
+
56
+ return new Promise((resolve) => {
57
+ // wait for the out transition to complete (if necessary)
58
+ nuxt.$once('triggerScroll', () => {
59
+ // coords will be used if no selector is provided,
60
+ // or if the selector didn't match any element.
61
+ if (to.hash) {
62
+ let hash = to.hash;
63
+
64
+ // CSS.escape() is not supported with IE and Edge.
65
+ if (typeof window.CSS !== 'undefined' && typeof window.CSS.escape !== 'undefined') {
66
+ hash = `#${ window.CSS.escape(hash.substr(1)) }`;
67
+ }
68
+ try {
69
+ if (document.querySelector(hash)) {
70
+ // scroll to anchor by returning the selector
71
+ position = { selector: hash };
72
+ }
73
+ } catch (e) {
74
+ console.warn('Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).'); // eslint-disable-line no-console
75
+ }
76
+ }
77
+ resolve(position);
78
+ });
79
+ });
80
+ }
package/utils/select.js CHANGED
@@ -1,5 +1,3 @@
1
- import $ from 'jquery';
2
-
3
1
  export function onClickOption(option, e) {
4
2
  if (!this.$attrs.multiple) {
5
3
  return;
@@ -29,7 +27,7 @@ export function onClickOption(option, e) {
29
27
  // We used to use popper for these, but it does not suppotr fractional pixel placements which
30
28
  // means the dropdown does not appear aligned to the control when placed in a column-based layout
31
29
  export function calculatePosition(dropdownList, component, width, placement) {
32
- const selectEl = $(component.$parent.$el)[0];
30
+ const selectEl = component.$parent.$el;
33
31
  const r = selectEl.getBoundingClientRect();
34
32
  const p = placement || 'bottom-start';
35
33
  const docHeight = document.body.offsetHeight;
package/utils/socket.js CHANGED
@@ -26,6 +26,7 @@ export const EVENT_DISCONNECT_ERROR = 'disconnect_error';
26
26
 
27
27
  export const NO_WATCH = 'NO_WATCH';
28
28
  export const NO_SCHEMA = 'NO_SCHEMA';
29
+ export const REVISION_TOO_OLD = 'TOO_OLD';
29
30
 
30
31
  export default class Socket extends EventTarget {
31
32
  url;
package/utils/string.js CHANGED
@@ -60,6 +60,19 @@ export function escapeHtml(html) {
60
60
  });
61
61
  }
62
62
 
63
+ /**
64
+ * Return HTML markup from escaped HTML string, allowing specific tags
65
+ * @param text string
66
+ * @returns string
67
+ */
68
+ export function decodeHtml(text) {
69
+ const div = document.createElement('div');
70
+
71
+ div.innerHTML = text;
72
+
73
+ return div.textContent || div.innerText || '';
74
+ }
75
+
63
76
  export function escapeRegex(string) {
64
77
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
65
78
  }
package/utils/time.js CHANGED
@@ -97,6 +97,15 @@ export function elapsedTime(seconds) {
97
97
  };
98
98
  }
99
99
 
100
+ const days = Math.floor(seconds / (3600 * 24));
101
+
102
+ if (days > 1) {
103
+ return {
104
+ diff: 60,
105
+ label: `${ days }d${ hours - (days * 24) }h`,
106
+ };
107
+ }
108
+
100
109
  if (hours > 7) {
101
110
  return {
102
111
  diff: 60,