foreman_theme_satellite 16.4.1 → 16.4.3

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -5
  3. data/app/assets/javascripts/foreman_theme_satellite/locale/en_GB/foreman_theme_satellite.js +1 -1
  4. data/app/assets/javascripts/foreman_theme_satellite/locale/es/foreman_theme_satellite.js +1 -1
  5. data/app/assets/javascripts/foreman_theme_satellite/locale/fr/foreman_theme_satellite.js +4 -4
  6. data/app/assets/javascripts/foreman_theme_satellite/locale/ja/foreman_theme_satellite.js +6 -6
  7. data/app/assets/javascripts/foreman_theme_satellite/locale/ka/foreman_theme_satellite.js +1 -1
  8. data/app/assets/javascripts/foreman_theme_satellite/locale/ko/foreman_theme_satellite.js +4 -4
  9. data/app/assets/javascripts/foreman_theme_satellite/locale/pt_BR/foreman_theme_satellite.js +1 -1
  10. data/app/assets/javascripts/foreman_theme_satellite/locale/zh_CN/foreman_theme_satellite.js +4 -4
  11. data/app/assets/stylesheets/foreman_theme_satellite/documentation.scss +12 -0
  12. data/app/assets/stylesheets/foreman_theme_satellite/foreman_theme_satellite.css +1 -0
  13. data/app/controllers/concerns/documentation_controller_branding.rb +15 -4
  14. data/app/helpers/documentation_visibility_helper.rb +30 -0
  15. data/app/overrides/hide_documentation.rb +23 -0
  16. data/lib/foreman_theme_satellite/engine.rb +1 -0
  17. data/lib/foreman_theme_satellite/version.rb +1 -1
  18. data/locale/en_GB/LC_MESSAGES/foreman_theme_satellite.mo +0 -0
  19. data/locale/en_GB/foreman_theme_satellite.po +1 -1
  20. data/locale/es/LC_MESSAGES/foreman_theme_satellite.mo +0 -0
  21. data/locale/es/foreman_theme_satellite.po +1 -1
  22. data/locale/foreman_theme_satellite.pot +6 -6
  23. data/locale/fr/LC_MESSAGES/foreman_theme_satellite.mo +0 -0
  24. data/locale/fr/foreman_theme_satellite.po +5 -5
  25. data/locale/ja/LC_MESSAGES/foreman_theme_satellite.mo +0 -0
  26. data/locale/ja/foreman_theme_satellite.po +7 -7
  27. data/locale/ka/LC_MESSAGES/foreman_theme_satellite.mo +0 -0
  28. data/locale/ka/foreman_theme_satellite.po +1 -1
  29. data/locale/ko/LC_MESSAGES/foreman_theme_satellite.mo +0 -0
  30. data/locale/ko/foreman_theme_satellite.po +5 -5
  31. data/locale/pt_BR/LC_MESSAGES/foreman_theme_satellite.mo +0 -0
  32. data/locale/pt_BR/foreman_theme_satellite.po +1 -1
  33. data/locale/zh_CN/LC_MESSAGES/foreman_theme_satellite.mo +0 -0
  34. data/locale/zh_CN/foreman_theme_satellite.po +5 -5
  35. data/webpack/components/SatelliteWelcomeEnv.js +54 -0
  36. data/webpack/components/fills/UpgradePage/SatelliteUpgradeHelperCard.js +11 -3
  37. data/webpack/documentation/documentationMenuKeyboard.js +89 -0
  38. data/webpack/documentation/documentationMenuKeyboard.test.js +229 -0
  39. data/webpack/documentation/hideDocumentation.js +173 -0
  40. data/webpack/documentation/hideDocumentation.test.js +294 -0
  41. data/webpack/index.js +34 -3
  42. data/webpack/test_setup.js +3 -0
  43. metadata +10 -1
@@ -0,0 +1,294 @@
1
+ import assert from 'assert';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import {
5
+ hideDocumentation,
6
+ hiddenClass,
7
+ normalizeSatelliteDocumentation,
8
+ installDocumentationHiding,
9
+ } from './hideDocumentation';
10
+
11
+ const styles = fs
12
+ .readFileSync(
13
+ path.join(
14
+ __dirname,
15
+ '../../app/assets/stylesheets/foreman_theme_satellite/documentation.scss'
16
+ ),
17
+ 'utf8'
18
+ )
19
+ .replace(/^\/\/.*$/gm, '');
20
+ const createDOM = (html) => {
21
+ document.head.innerHTML = `<style>${styles}</style>`;
22
+ document.body.innerHTML = html;
23
+ };
24
+ afterEach(() => {
25
+ document.head.innerHTML = '';
26
+ document.body.innerHTML = '';
27
+ jest.restoreAllMocks();
28
+ });
29
+
30
+ test('hides documentation controls but preserves inline links, sentences and actions', async () => {
31
+ createDOM(
32
+ `<div class="foreman-empty-state"><div><div class="empty-state-description">Description</div><span id="sentence">See <a href="/links/manual">documentation</a></span></div><ul id="permissions"><li>view_hosts</li></ul><a id="create" href="/hosts/new">Create</a></div><ul><li id="docs"><button data-ouia-component-id="doc-url-dropdown">Docs</button></li><li id="support"><a href="/links/support">Support</a></li></ul>`
33
+ );
34
+ const doc = document;
35
+ hideDocumentation(doc);
36
+ assert(doc.querySelector('#docs button').classList.contains(hiddenClass));
37
+ assert(!doc.getElementById('docs').classList.contains(hiddenClass));
38
+ ['sentence', 'permissions', 'create', 'support'].forEach((id) => {
39
+ assert(!doc.getElementById(id).classList.contains(hiddenClass));
40
+ });
41
+ assert.equal(
42
+ doc.querySelector('#sentence a').getAttribute('href'),
43
+ '/links/manual'
44
+ );
45
+ });
46
+
47
+ test('handles React node reuse without leaving functional links hidden', async () => {
48
+ createDOM(
49
+ '<a data-ouia-component-id="audits-documentation-button" href="/links/manual">Documentation</a>'
50
+ );
51
+ const doc = document;
52
+ hideDocumentation(doc);
53
+ const link = doc.querySelector('a');
54
+ assert(link.classList.contains(hiddenClass));
55
+ link.setAttribute('data-ouia-component-id', 'create-host');
56
+ link.href = '/hosts/new';
57
+ hideDocumentation(doc);
58
+ assert(!link.classList.contains(hiddenClass));
59
+ });
60
+
61
+ test('observes late documentation buttons and reused control identifiers', async () => {
62
+ createDOM('<main></main>');
63
+ const doc = document;
64
+ const observer = installDocumentationHiding(doc);
65
+ const link = doc.createElement('a');
66
+ link.href = '/links/docs/Managing_Hosts';
67
+ link.setAttribute(
68
+ 'data-ouia-component-id',
69
+ 'register-host-documentation-button'
70
+ );
71
+ doc.body.appendChild(link);
72
+ await new Promise((resolve) => setTimeout(resolve, 60));
73
+ assert(link.classList.contains(hiddenClass));
74
+ link.setAttribute('data-ouia-component-id', 'create-host');
75
+ link.href = '/hosts/new';
76
+ await new Promise((resolve) => setTimeout(resolve, 60));
77
+ assert(!link.classList.contains(hiddenClass));
78
+ observer.disconnect();
79
+ });
80
+
81
+ test('hides localized table documentation without hiding other dropdown actions', async () => {
82
+ createDOM(
83
+ '<div data-ouia-component-id="action-buttons-dropdown"><ul><li id="docs"><a data-ouia-component-id="Dokumentace-dropdown-item" href="/hosts/help">Dokumentace</a></li><li id="export"><a data-ouia-component-id="Export-dropdown-item" href="/hosts.csv">Export</a></li></ul></div>'
84
+ );
85
+ hideDocumentation(document, 'Dokumentace');
86
+ assert(document.querySelector('#docs a').classList.contains(hiddenClass));
87
+ assert(!document.getElementById('export').classList.contains(hiddenClass));
88
+ });
89
+
90
+ test('welcome sentences keep their documentation links', async () => {
91
+ assert.doesNotMatch(styles, /a\[href/);
92
+ createDOM(`
93
+ <div class="pf-v5-c-empty-state__body">
94
+ <div class="empty-state-description">No discovered hosts found in this context.</div>
95
+ <span id="discovered">For more information please see <a href="/links/plugin_manual?name=foreman_discovery">documentation</a></span>
96
+ </div>
97
+ <div class="empty-state-description" id="reports">If you wish to configure Puppet to forward its reports to Foreman, please follow <a href="/links/manual/3.5.4PuppetReports">setting up reporting</a> and <a href="/links/wiki/Mail_Notifications">e-mail reporting</a></div>
98
+ `);
99
+ const doc = document;
100
+ hideDocumentation(doc, 'Documentation');
101
+ normalizeSatelliteDocumentation(doc, '/links/manual');
102
+ assert.equal(
103
+ doc.querySelector('#discovered').textContent,
104
+ 'For more information please see documentation'
105
+ );
106
+ assert.equal(
107
+ doc.querySelector('#reports').textContent,
108
+ 'If you wish to configure Puppet to forward its reports to Foreman, please follow setting up reporting and e-mail reporting'
109
+ );
110
+ doc.querySelectorAll('#discovered a, #reports a').forEach((link) => {
111
+ assert.notEqual(window.getComputedStyle(link).display, 'none');
112
+ });
113
+ });
114
+
115
+ test('CSS and JavaScript leave inline documentation links visible', async () => {
116
+ const urls = [
117
+ '/links/manual',
118
+ '/links/docs/Managing_Hosts',
119
+ '/links/plugin_manual',
120
+ '/links/wiki',
121
+ 'https://docs.redhat.com/en/documentation',
122
+ 'https://docs.theforeman.org/',
123
+ ];
124
+ createDOM(
125
+ urls.map((url) => `<p>See <a href="${url}">documentation</a>.</p>`).join('')
126
+ );
127
+ hideDocumentation(document);
128
+ document.querySelectorAll('a').forEach((link) => {
129
+ assert.notEqual(window.getComputedStyle(link).display, 'none');
130
+ assert.notEqual(
131
+ window.getComputedStyle(link.parentElement).display,
132
+ 'none'
133
+ );
134
+ });
135
+ });
136
+
137
+ test('hides only the upgrade documentation button and preserves card content and helper', async () => {
138
+ createDOM(
139
+ '<section id="card"><p id="description">Upgrade instructions</p><a data-ouia-component-id="upgrade-docs-button" href="/links/upgrade?section=documentation">Documentation</a><a id="helper" data-ouia-component-id="upgrade-helper-button" href="/links/upgrade?section=helper">Upgrade helper</a></section>'
140
+ );
141
+ hideDocumentation(document);
142
+ const style = (selector) =>
143
+ window.getComputedStyle(document.querySelector(selector)).display;
144
+ assert.equal(style('[data-ouia-component-id="upgrade-docs-button"]'), 'none');
145
+ ['#card', '#description', '#helper'].forEach((selector) => {
146
+ assert.notEqual(style(selector), 'none');
147
+ });
148
+ });
149
+
150
+ test('direct Satellite links use the landing redirect while other products and support remain unchanged', async () => {
151
+ const satelliteUrls = [
152
+ 'https://docs.redhat.com/en/documentation/red_hat_satellite/6.19/managing_hosts/index#chapter',
153
+ 'https://access.redhat.com/documentation/en-us/red_hat_satellite/6.10/html/guide/chapter',
154
+ 'https://offline.example/docs/en/documentation/red_hat_satellite/6.19/guide',
155
+ ];
156
+ const preserved = [
157
+ 'https://docs.redhat.com/en/documentation/subscription_central/1/guide',
158
+ 'https://docs.ansible.com/ansible/latest/guide',
159
+ 'https://access.redhat.com/products/red-hat-satellite#get-support',
160
+ 'https://access.redhat.com/labs/satelliteupgradehelper',
161
+ 'https://access.redhat.com/solutions/satellite6-tasks#task',
162
+ 'https://access.redhat.com/articles/1586183',
163
+ ];
164
+ createDOM(
165
+ [...satelliteUrls, ...preserved]
166
+ .map((url) => `<a href="${url}">Documentation</a>`)
167
+ .join('')
168
+ );
169
+ normalizeSatelliteDocumentation(document, '/prefix/links/manual');
170
+ const links = [...document.querySelectorAll('a')];
171
+ links.slice(0, satelliteUrls.length).forEach((link) => {
172
+ assert.equal(link.getAttribute('href'), '/prefix/links/manual');
173
+ assert.notEqual(window.getComputedStyle(link).display, 'none');
174
+ });
175
+ links
176
+ .slice(satelliteUrls.length)
177
+ .forEach((link, i) => assert.equal(link.href, preserved[i]));
178
+ });
179
+
180
+ test('normalizes late Satellite links and React href updates', async () => {
181
+ createDOM('<main></main>');
182
+ const observer = installDocumentationHiding(
183
+ document,
184
+ 'Documentation',
185
+ '/prefix/links/manual'
186
+ );
187
+ const link = document.createElement('a');
188
+ link.href =
189
+ 'https://docs.redhat.com/en/documentation/red_hat_satellite/6.19/guide';
190
+ document.body.appendChild(link);
191
+ await new Promise((resolve) => setTimeout(resolve, 60));
192
+ assert.equal(link.getAttribute('href'), '/prefix/links/manual');
193
+ link.href =
194
+ 'https://docs.redhat.com/en/documentation/red_hat_satellite/6.19/another-guide';
195
+ await new Promise((resolve) => setTimeout(resolve, 60));
196
+ assert.equal(link.getAttribute('href'), '/prefix/links/manual');
197
+ observer.disconnect();
198
+ });
199
+
200
+ test('observer passes visit added subtrees and changed attributes only', async () => {
201
+ createDOM(
202
+ '<a id="outside" href="https://docs.ansible.com/ansible/latest/guide">Ansible</a><button id="kept" data-ouia-component-id="doc-url-dropdown">Docs</button><main></main>'
203
+ );
204
+ const doc = document;
205
+ const observer = installDocumentationHiding(
206
+ doc,
207
+ 'Dokumentace',
208
+ '/prefix/links/manual'
209
+ );
210
+ const documentQueries = [];
211
+ const querySelectorAll = doc.querySelectorAll.bind(doc);
212
+ jest.spyOn(doc, 'querySelectorAll').mockImplementation((selector) => {
213
+ documentQueries.push(selector);
214
+ return querySelectorAll(selector);
215
+ });
216
+ const wrapper = doc.createElement('div');
217
+ wrapper.innerHTML =
218
+ '<div data-ouia-component-id="action-buttons-dropdown"><a id="localized" data-ouia-component-id="Dokumentace-dropdown-item" href="/hosts/help">Dokumentace</a></div><a id="inside" href="https://docs.redhat.com/en/documentation/red_hat_satellite/6.19/guide">Docs</a><button id="audits" data-ouia-component-id="audits-documentation-button">Documentation</button>';
219
+ doc.querySelector('main').appendChild(wrapper);
220
+ await new Promise((resolve) => setTimeout(resolve, 60));
221
+ assert.equal(documentQueries.length, 0);
222
+ assert.equal(
223
+ doc.getElementById('inside').getAttribute('href'),
224
+ '/prefix/links/manual'
225
+ );
226
+ assert.equal(
227
+ doc.getElementById('outside').getAttribute('href'),
228
+ 'https://docs.ansible.com/ansible/latest/guide'
229
+ );
230
+ assert(doc.getElementById('localized').classList.contains(hiddenClass));
231
+ assert(doc.getElementById('audits').classList.contains(hiddenClass));
232
+ assert(doc.getElementById('kept').classList.contains(hiddenClass));
233
+ doc
234
+ .getElementById('localized')
235
+ .setAttribute('data-ouia-component-id', 'Export-dropdown-item');
236
+ await new Promise((resolve) => setTimeout(resolve, 60));
237
+ assert.equal(documentQueries.length, 0);
238
+ assert(!doc.getElementById('localized').classList.contains(hiddenClass));
239
+ assert(doc.getElementById('kept').classList.contains(hiddenClass));
240
+ assert(doc.getElementById('audits').classList.contains(hiddenClass));
241
+ observer.disconnect();
242
+ });
243
+
244
+ test('observer applies a mutation that arrives while a frame is scheduled', async () => {
245
+ createDOM('<main></main>');
246
+ const doc = document;
247
+ const observer = installDocumentationHiding(
248
+ doc,
249
+ 'Documentation',
250
+ '/prefix/links/manual'
251
+ );
252
+ let frame = null;
253
+ jest.spyOn(window, 'requestAnimationFrame').mockImplementation((callback) => {
254
+ frame = callback;
255
+ return 1;
256
+ });
257
+ const link = doc.createElement('a');
258
+ link.href =
259
+ 'https://docs.redhat.com/en/documentation/red_hat_satellite/6.19/guide';
260
+ doc.body.appendChild(link);
261
+ await Promise.resolve();
262
+ assert.equal(typeof frame, 'function');
263
+ const scheduledFrame = frame;
264
+ const button = doc.createElement('button');
265
+ button.setAttribute('data-ouia-component-id', 'audits-documentation-button');
266
+ doc.body.appendChild(button);
267
+ await Promise.resolve();
268
+ scheduledFrame();
269
+ assert.equal(link.getAttribute('href'), '/prefix/links/manual');
270
+ assert(button.classList.contains(hiddenClass));
271
+ observer.disconnect();
272
+ });
273
+
274
+ test('Reports inline sentence stays complete even beside a hidden documentation button', async () => {
275
+ createDOM(
276
+ '<ul><li id="report"><div class="empty-state-description">If you wish to configure Puppet to forward its reports to Foreman, please follow <a href="/links/manual/3.5.4PuppetReports">setting up reporting</a> and <a href="/links/wiki/Mail_Notifications">e-mail reporting</a></div><button data-ouia-component-id="audits-documentation-button">Documentation</button></li></ul>'
277
+ );
278
+ const doc = document;
279
+ hideDocumentation(doc);
280
+ normalizeSatelliteDocumentation(doc, '/links/manual');
281
+ assert.equal(
282
+ doc.querySelector('.empty-state-description').textContent,
283
+ 'If you wish to configure Puppet to forward its reports to Foreman, please follow setting up reporting and e-mail reporting'
284
+ );
285
+ doc.querySelectorAll('.empty-state-description a').forEach((link) => {
286
+ for (let node = link; node; node = node.parentElement) {
287
+ assert.notEqual(window.getComputedStyle(node).display, 'none');
288
+ }
289
+ });
290
+ assert.equal(
291
+ window.getComputedStyle(doc.querySelector('button')).display,
292
+ 'none'
293
+ );
294
+ });
data/webpack/index.js CHANGED
@@ -3,25 +3,56 @@ import React from 'react';
3
3
  import componentRegistry from 'foremanReact/components/componentRegistry';
4
4
  import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
5
5
  import { translate as __ } from 'foremanReact/common/I18n';
6
+ import { foremanUrl } from 'foremanReact/common/helpers';
6
7
  import { Helmet } from 'react-helmet';
7
8
 
9
+ import { installDocumentationHiding } from './documentation/hideDocumentation';
10
+
8
11
  import SatelliteUpgradeHelperCard from './components/fills/UpgradePage/SatelliteUpgradeHelperCard';
12
+ import { SatelliteWelcomeEnv } from './components/SatelliteWelcomeEnv';
13
+
14
+ const SATELLITE_FILL_WEIGHT = 1000;
9
15
 
10
16
  // register components for erb mounting
11
17
  componentRegistry.register({ name: 'Helmet', type: Helmet });
18
+ componentRegistry.register({
19
+ name: 'SatelliteWelcomeEnv',
20
+ type: SatelliteWelcomeEnv,
21
+ });
12
22
 
13
23
  addGlobalFill(
14
24
  'upgrade-page-upgrade-docs',
15
25
  'Satellite upgrade helper card',
16
26
  <SatelliteUpgradeHelperCard key="satellite-upgrade-helper-card" />,
17
- 1000,
27
+ SATELLITE_FILL_WEIGHT
18
28
  );
19
29
  addGlobalFill(
20
30
  'upgrade-page-footer',
21
31
  'Satellite upgrade page footer',
22
32
  {
23
- helpDesc: __('If you require assistance or encounter issues, reach out to Red Hat Support or explore the resources available in the Customer Portal for troubleshooting.'),
33
+ helpDesc: __(
34
+ 'If you require assistance or encounter issues, reach out to Red Hat Support or explore the resources available in the Customer Portal for troubleshooting.'
35
+ ),
24
36
  helpLinkText: __('Contact support'),
25
37
  },
26
- 1000,
38
+ SATELLITE_FILL_WEIGHT
27
39
  );
40
+
41
+ if (document.readyState === 'loading') {
42
+ document.addEventListener(
43
+ 'DOMContentLoaded',
44
+ () =>
45
+ installDocumentationHiding(
46
+ document,
47
+ __('Documentation'),
48
+ foremanUrl('/links/manual')
49
+ ),
50
+ { once: true }
51
+ );
52
+ } else {
53
+ installDocumentationHiding(
54
+ document,
55
+ __('Documentation'),
56
+ foremanUrl('/links/manual')
57
+ );
58
+ }
@@ -0,0 +1,3 @@
1
+ // Foreman's Jest configuration resolves this alias to its shared test setup.
2
+ // eslint-disable-next-line import/no-unresolved
3
+ import 'foremanJSTestSetup';
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_theme_satellite
3
3
  version: !ruby/object:Gem::Version
4
- version: 16.4.1
4
+ version: 16.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shimon Stein
@@ -66,6 +66,7 @@ files:
66
66
  - app/assets/javascripts/foreman_theme_satellite/theme_ng_page_title.js
67
67
  - app/assets/stylesheets/foreman_theme_satellite/application_colors.css
68
68
  - app/assets/stylesheets/foreman_theme_satellite/bastion.scss
69
+ - app/assets/stylesheets/foreman_theme_satellite/documentation.scss
69
70
  - app/assets/stylesheets/foreman_theme_satellite/external_logout.scss
70
71
  - app/assets/stylesheets/foreman_theme_satellite/foreman_theme_satellite.css
71
72
  - app/assets/stylesheets/foreman_theme_satellite/login.scss
@@ -76,6 +77,7 @@ files:
76
77
  - app/assets/stylesheets/foreman_theme_satellite/wizard.scss
77
78
  - app/controllers/concerns/documentation_controller_branding.rb
78
79
  - app/controllers/concerns/provisioning_templates_controller_branding.rb
80
+ - app/helpers/documentation_visibility_helper.rb
79
81
  - app/helpers/provisioning_templates_helper_branding.rb
80
82
  - app/helpers/theme_application_helper.rb
81
83
  - app/helpers/theme_css_class_helper.rb
@@ -94,6 +96,7 @@ files:
94
96
  - app/models/concerns/setting_branding.rb
95
97
  - app/models/concerns/upstream_only_settings.rb
96
98
  - app/overrides/bootdisk_help_page.rb
99
+ - app/overrides/hide_documentation.rb
97
100
  - app/overrides/layouts/base/eol_banner.html.erb.deface
98
101
  - app/overrides/layouts/base/theme_react_root.html.erb.deface
99
102
  - app/overrides/layouts/base/theme_resources.html.erb.deface
@@ -148,8 +151,14 @@ files:
148
151
  - locale/zh_CN/LC_MESSAGES/foreman_theme_satellite.mo
149
152
  - locale/zh_CN/foreman_theme_satellite.po
150
153
  - package.json
154
+ - webpack/components/SatelliteWelcomeEnv.js
151
155
  - webpack/components/fills/UpgradePage/SatelliteUpgradeHelperCard.js
156
+ - webpack/documentation/documentationMenuKeyboard.js
157
+ - webpack/documentation/documentationMenuKeyboard.test.js
158
+ - webpack/documentation/hideDocumentation.js
159
+ - webpack/documentation/hideDocumentation.test.js
152
160
  - webpack/index.js
161
+ - webpack/test_setup.js
153
162
  homepage: https://github.com/RedHatSatellite/foreman_theme_satellite
154
163
  licenses:
155
164
  - GPL-3.0