@salesforcedevs/docs-components 1.3.209-alpha.10 → 1.3.209-lang2-alpha
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/lwc.config.json +1 -0
- package/package.json +1 -1
- package/src/modules/doc/amfReference/amfReference.html +2 -0
- package/src/modules/doc/amfReference/amfReference.ts +3 -0
- package/src/modules/doc/contentLayout/contentLayout.css +6 -1
- package/src/modules/doc/contentLayout/contentLayout.html +11 -0
- package/src/modules/doc/contentLayout/contentLayout.ts +18 -15
- package/src/modules/doc/header/header.css +23 -33
- package/src/modules/doc/header/header.html +2 -53
- package/src/modules/doc/header/header.ts +1 -92
- package/src/modules/doc/sidebarFooterNav/sidebarFooterNav.css +44 -0
- package/src/modules/doc/sidebarFooterNav/sidebarFooterNav.html +58 -0
- package/src/modules/doc/sidebarFooterNav/sidebarFooterNav.ts +109 -0
- package/src/modules/doc/xmlContent/types.ts +5 -2
- package/src/modules/doc/xmlContent/xmlContent.html +5 -0
- package/src/modules/doc/xmlContent/xmlContent.ts +22 -51
package/lwc.config.json
CHANGED
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import { sentenceCase } from "sentence-case";
|
|
|
4
4
|
import qs from "query-string";
|
|
5
5
|
import { AmfModelParser } from "doc/amfModelParser";
|
|
6
6
|
import { normalizeBoolean } from "dxUtils/normalizers";
|
|
7
|
+
import type { OptionWithLink } from "typings/custom";
|
|
7
8
|
import type {
|
|
8
9
|
AmfConfig,
|
|
9
10
|
AmfMetadataTopic,
|
|
@@ -48,6 +49,8 @@ export default class AmfReference extends LightningElement {
|
|
|
48
49
|
@api useOldSidebar: boolean = false;
|
|
49
50
|
@api tocTitle?: string;
|
|
50
51
|
@api tocOptions?: string;
|
|
52
|
+
@api languages!: OptionWithLink[];
|
|
53
|
+
@api language!: string;
|
|
51
54
|
@track navigation = [] as NavigationItem[];
|
|
52
55
|
@track versions: Array<ReferenceVersion> = [];
|
|
53
56
|
@track showVersionBanner = false;
|
|
@@ -61,12 +61,16 @@ dx-toc {
|
|
|
61
61
|
flex-direction: row;
|
|
62
62
|
justify-content: center;
|
|
63
63
|
max-width: var(--dx-g-doc-content-max-width);
|
|
64
|
+
|
|
65
|
+
/* Derived this manually by substracting (topHeader, doc header, banner and the content). */
|
|
66
|
+
min-height: 62vh;
|
|
64
67
|
margin: auto;
|
|
65
68
|
padding: 0 var(--dx-g-global-header-padding-horizontal);
|
|
69
|
+
margin-bottom: calc(2 * (var(--dx-g-spacing-5xl) + 4px));
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
.content-body {
|
|
69
|
-
margin: var(--dx-g-spacing-sm) 0
|
|
73
|
+
margin: var(--dx-g-spacing-sm) 0 0;
|
|
70
74
|
max-width: 900px;
|
|
71
75
|
flex: 1;
|
|
72
76
|
width: 0;
|
|
@@ -106,6 +110,7 @@ dx-toc {
|
|
|
106
110
|
.content-body-container {
|
|
107
111
|
padding-right: 0;
|
|
108
112
|
overflow-x: auto;
|
|
113
|
+
margin-bottom: calc(var(--dx-g-spacing-5xl) + 4px);
|
|
109
114
|
}
|
|
110
115
|
|
|
111
116
|
.left-nav-bar {
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
value={sidebarValue}
|
|
8
8
|
header={sidebarHeader}
|
|
9
9
|
ontogglesidebar={onToggleSidebar}
|
|
10
|
+
languages={languages}
|
|
11
|
+
language={language}
|
|
12
|
+
bail-href={bailHref}
|
|
13
|
+
bail-label={bailLabel}
|
|
10
14
|
>
|
|
11
15
|
<slot name="sidebar-header" slot="header"></slot>
|
|
12
16
|
</dx-sidebar-old>
|
|
@@ -22,6 +26,10 @@
|
|
|
22
26
|
coveo-search-hub={coveoSearchHub}
|
|
23
27
|
coveo-advanced-query-config={coveoAdvancedQueryConfig}
|
|
24
28
|
ontogglesidebar={onToggleSidebar}
|
|
29
|
+
languages={languages}
|
|
30
|
+
language={language}
|
|
31
|
+
bail-href={bailHref}
|
|
32
|
+
bail-label={bailLabel}
|
|
25
33
|
>
|
|
26
34
|
<slot name="sidebar-header" slot="header"></slot>
|
|
27
35
|
</dx-sidebar>
|
|
@@ -48,6 +56,9 @@
|
|
|
48
56
|
></dx-toc>
|
|
49
57
|
</div>
|
|
50
58
|
</div>
|
|
59
|
+
<div class="footer-container">
|
|
60
|
+
<dx-footer variant="no-signup"></dx-footer>
|
|
61
|
+
</div>
|
|
51
62
|
</div>
|
|
52
63
|
</div>
|
|
53
64
|
</template>
|
|
@@ -4,6 +4,7 @@ import { closest } from "kagekiri";
|
|
|
4
4
|
import { toJson } from "dxUtils/normalizers";
|
|
5
5
|
import { highlightTerms } from "dxUtils/highlight";
|
|
6
6
|
import { SearchSyncer } from "docUtils/searchSyncer";
|
|
7
|
+
import type { OptionWithLink } from "typings/custom";
|
|
7
8
|
|
|
8
9
|
type AnchorMap = { [key: string]: { intersect: boolean; id: string } };
|
|
9
10
|
|
|
@@ -36,6 +37,10 @@ export default class ContentLayout extends LightningElement {
|
|
|
36
37
|
@api coveoSearchHub!: string;
|
|
37
38
|
@api coveoAdvancedQueryConfig!: string;
|
|
38
39
|
@api useOldSidebar?: boolean = false;
|
|
40
|
+
@api languages!: OptionWithLink[];
|
|
41
|
+
@api language!: string;
|
|
42
|
+
@api bailHref!: string;
|
|
43
|
+
@api bailLabel!: string;
|
|
39
44
|
|
|
40
45
|
@api
|
|
41
46
|
get breadcrumbs() {
|
|
@@ -207,9 +212,9 @@ export default class ContentLayout extends LightningElement {
|
|
|
207
212
|
".sticky-doc-header"
|
|
208
213
|
) as HTMLElement;
|
|
209
214
|
|
|
210
|
-
const docPhaseEl = (
|
|
211
|
-
|
|
212
|
-
).assignedElements()[0] as HTMLSlotElement;
|
|
215
|
+
const docPhaseEl = (this.template.querySelector(
|
|
216
|
+
"[name=doc-phase]"
|
|
217
|
+
)! as any).assignedElements()[0] as HTMLSlotElement;
|
|
213
218
|
|
|
214
219
|
if (!sidebarEl || !globalNavEl || !contextNavEl || !docHeaderEl) {
|
|
215
220
|
console.warn("One or more required elements are missing.");
|
|
@@ -259,8 +264,9 @@ export default class ContentLayout extends LightningElement {
|
|
|
259
264
|
});
|
|
260
265
|
|
|
261
266
|
// Adjust right nav bar position when doc phase is present
|
|
262
|
-
const rightNavBarEl =
|
|
263
|
-
|
|
267
|
+
const rightNavBarEl = this.template.querySelector(
|
|
268
|
+
".right-nav-bar"
|
|
269
|
+
);
|
|
264
270
|
|
|
265
271
|
if (rightNavBarEl) {
|
|
266
272
|
rightNavBarEl.style.top = `${
|
|
@@ -322,17 +328,14 @@ export default class ContentLayout extends LightningElement {
|
|
|
322
328
|
};
|
|
323
329
|
|
|
324
330
|
onSlotChange(event: Event): void {
|
|
325
|
-
const slotElements = (
|
|
326
|
-
event.target as HTMLSlotElement
|
|
327
|
-
).assignedElements();
|
|
331
|
+
const slotElements = (event.target as HTMLSlotElement).assignedElements();
|
|
328
332
|
|
|
329
333
|
if (slotElements.length) {
|
|
330
334
|
this.contentLoaded = true;
|
|
331
335
|
const slotContentElement = slotElements[0];
|
|
332
|
-
const headingElements =
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
);
|
|
336
|
+
const headingElements = slotContentElement.ownerDocument?.getElementsByTagName(
|
|
337
|
+
TOC_HEADER_TAG
|
|
338
|
+
);
|
|
336
339
|
|
|
337
340
|
for (const headingElement of headingElements as any) {
|
|
338
341
|
// Sometimes elements hash is not being set when slot content is wrapped with div
|
|
@@ -392,9 +395,9 @@ export default class ContentLayout extends LightningElement {
|
|
|
392
395
|
globalNavEl?.offsetHeight +
|
|
393
396
|
contextNavEl?.offsetHeight;
|
|
394
397
|
|
|
395
|
-
const docPhaseEl = (
|
|
396
|
-
|
|
397
|
-
).assignedElements()[0] as HTMLSlotElement;
|
|
398
|
+
const docPhaseEl = (this.template.querySelector(
|
|
399
|
+
"[name=doc-phase]"
|
|
400
|
+
)! as any).assignedElements()[0] as HTMLSlotElement;
|
|
398
401
|
|
|
399
402
|
const offset = docPhaseEl
|
|
400
403
|
? headerHeight + docPhaseEl.offsetHeight
|
|
@@ -7,6 +7,8 @@ dx-logo {
|
|
|
7
7
|
.header_l2 {
|
|
8
8
|
justify-content: space-between;
|
|
9
9
|
height: var(--dx-g-doc-header-main-nav-height);
|
|
10
|
+
padding-bottom: var(--dx-g-spacing-xs);
|
|
11
|
+
background: white;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
.nav_menu-button {
|
|
@@ -16,44 +18,32 @@ dx-logo {
|
|
|
16
18
|
);
|
|
17
19
|
}
|
|
18
20
|
|
|
21
|
+
.has-brand.has-scoped-nav-items {
|
|
22
|
+
border-bottom: 1px solid var(--dx-g-gray-90);
|
|
23
|
+
border-top: 1px solid var(--dx-g-gray-90);
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
.nav_menu-ctas {
|
|
20
27
|
margin-right: var(--dx-g-spacing-sm);
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
header:not(.has-brand) > .header_l1 {
|
|
24
|
-
background:
|
|
31
|
+
background: white;
|
|
32
|
+
border-bottom: 1px solid var(--dx-g-gray-90);
|
|
25
33
|
}
|
|
26
34
|
|
|
27
35
|
header:not(.has-brand) > .header_l2 {
|
|
28
|
-
|
|
36
|
+
border-bottom: 1px solid var(--dx-g-gray-90);
|
|
37
|
+
border-top: 1px solid var(--dx-g-gray-90);
|
|
38
|
+
padding-bottom: var(--dx-g-spacing-lg);
|
|
29
39
|
}
|
|
30
40
|
|
|
31
41
|
.header_l2_group.header_l2_group-right-ctas {
|
|
32
42
|
align-items: baseline;
|
|
33
43
|
}
|
|
34
44
|
|
|
35
|
-
.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
margin-left: var(--dx-g-spacing-sm);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.header_lang-dropdown {
|
|
42
|
-
--button-primary-color: var(--dx-g-blue-vibrant-40);
|
|
43
|
-
--button-primary-color-hover: var(--dx-g-blue-vibrant-30);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.header_lang-dropdown > dx-button {
|
|
47
|
-
--dx-c-button-primary-color: var(--button-primary-color);
|
|
48
|
-
--dx-c-button-primary-color-hover: var(--button-primary-color-hover);
|
|
49
|
-
--dx-c-slot-empty-width: min-content;
|
|
50
|
-
--border-color: var(--button-primary-color);
|
|
51
|
-
|
|
52
|
-
border-bottom: 1px dashed var(--border-color);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.header_lang-dropdown > dx-button:hover {
|
|
56
|
-
--border-color: var(--button-primary-color-hover);
|
|
45
|
+
.has-brand .header_l2_group-title {
|
|
46
|
+
padding-bottom: calc(var(--dx-g-spacing-md) + 2px);
|
|
57
47
|
}
|
|
58
48
|
|
|
59
49
|
@media (max-width: 768px) {
|
|
@@ -82,6 +72,10 @@ header:not(.has-brand) > .header_l2 {
|
|
|
82
72
|
margin-right: var(--dx-g-spacing-sm);
|
|
83
73
|
}
|
|
84
74
|
|
|
75
|
+
.has-brand .header_l2_group-title {
|
|
76
|
+
padding-bottom: var(--dx-g-spacing-smd);
|
|
77
|
+
}
|
|
78
|
+
|
|
85
79
|
.header_l2_group-title {
|
|
86
80
|
margin-right: 0;
|
|
87
81
|
padding: var(--dx-g-spacing-smd)
|
|
@@ -89,19 +83,15 @@ header:not(.has-brand) > .header_l2 {
|
|
|
89
83
|
min-height: var(--dx-g-doc-header-main-nav-height);
|
|
90
84
|
}
|
|
91
85
|
|
|
92
|
-
.header_l2_group-title .header_lang-dropdown {
|
|
93
|
-
margin-left: auto;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.header_lang-dropdown > dx-button {
|
|
97
|
-
padding: var(--dx-g-spacing-2xs) 0;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
86
|
.has-scoped-nav-items > .header_l2 {
|
|
101
87
|
height: unset;
|
|
102
88
|
}
|
|
103
89
|
|
|
104
90
|
.has-scoped-nav-items .header_l2_group-title {
|
|
105
|
-
border-bottom: 1px solid var(--dx-g-
|
|
91
|
+
border-bottom: 1px solid var(--dx-g-gray-90);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
header:not(.has-brand) > .header_l2 {
|
|
95
|
+
padding-bottom: 0;
|
|
106
96
|
}
|
|
107
97
|
}
|
|
@@ -14,28 +14,12 @@
|
|
|
14
14
|
if:true={isValidBrand}
|
|
15
15
|
sprite="salesforcebrand"
|
|
16
16
|
symbol={brand}
|
|
17
|
-
size="
|
|
17
|
+
size="large"
|
|
18
18
|
></dx-icon>
|
|
19
|
-
<span class="subtitle dx-text-display-
|
|
19
|
+
<span class="subtitle dx-text-display-7">
|
|
20
20
|
{subtitle}
|
|
21
21
|
</span>
|
|
22
22
|
</a>
|
|
23
|
-
<dx-dropdown
|
|
24
|
-
if:true={showMobileLanguages}
|
|
25
|
-
class="header_lang-dropdown"
|
|
26
|
-
options={languages}
|
|
27
|
-
small
|
|
28
|
-
value={language}
|
|
29
|
-
value-path={langValuePath}
|
|
30
|
-
onchange={onLangChange}
|
|
31
|
-
>
|
|
32
|
-
<dx-button
|
|
33
|
-
aria-label="Select Language"
|
|
34
|
-
variant="inline"
|
|
35
|
-
icon-size="large"
|
|
36
|
-
icon-symbol="world"
|
|
37
|
-
></dx-button>
|
|
38
|
-
</dx-dropdown>
|
|
39
23
|
</div>
|
|
40
24
|
<div
|
|
41
25
|
if:true={hasScopedNavItems}
|
|
@@ -52,41 +36,6 @@
|
|
|
52
36
|
></dx-header-nav>
|
|
53
37
|
</div>
|
|
54
38
|
</div>
|
|
55
|
-
<div
|
|
56
|
-
if:false={smallMobile}
|
|
57
|
-
class="header_l2_group header_l2_group-right-ctas"
|
|
58
|
-
>
|
|
59
|
-
<dx-dropdown
|
|
60
|
-
if:true={hasLanguages}
|
|
61
|
-
class="header_lang-dropdown"
|
|
62
|
-
options={languages}
|
|
63
|
-
small
|
|
64
|
-
value-path={langValuePath}
|
|
65
|
-
value={language}
|
|
66
|
-
onchange={onLangChange}
|
|
67
|
-
>
|
|
68
|
-
<dx-button
|
|
69
|
-
aria-label="Select Language"
|
|
70
|
-
variant="inline"
|
|
71
|
-
icon-size="small"
|
|
72
|
-
icon-symbol="world"
|
|
73
|
-
>
|
|
74
|
-
{languageLabel}
|
|
75
|
-
</dx-button>
|
|
76
|
-
</dx-dropdown>
|
|
77
|
-
<dx-button
|
|
78
|
-
if:true={hasBailLink}
|
|
79
|
-
aria-label={bailLabel}
|
|
80
|
-
class="header_bail-link"
|
|
81
|
-
href={bailHref}
|
|
82
|
-
onclick={handleBailClick}
|
|
83
|
-
variant="tertiary"
|
|
84
|
-
icon-symbol="new_window"
|
|
85
|
-
target="_blank"
|
|
86
|
-
>
|
|
87
|
-
{bailLabel}
|
|
88
|
-
</dx-button>
|
|
89
|
-
</div>
|
|
90
39
|
</div>
|
|
91
40
|
</header>
|
|
92
41
|
</dx-brand-theme-provider>
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { api } from "lwc";
|
|
2
2
|
import cx from "classnames";
|
|
3
|
-
import type { OptionWithNested
|
|
3
|
+
import type { OptionWithNested } from "typings/custom";
|
|
4
4
|
import { HeaderBase } from "dxBaseElements/headerBase";
|
|
5
5
|
import { toJson } from "dxUtils/normalizers";
|
|
6
|
-
import get from "lodash.get";
|
|
7
|
-
import { track } from "dxUtils/analytics";
|
|
8
6
|
|
|
9
7
|
const TABLET_MATCH = "980px";
|
|
10
8
|
const MOBILE_MATCH = "880px";
|
|
11
|
-
const SMALL_MOBILE_MATCH = "768px";
|
|
12
9
|
|
|
13
10
|
export default class Header extends HeaderBase {
|
|
14
11
|
@api langValuePath: string = "id"; // allows to override how language property is interpreted, follows valuePath dropdown api.
|
|
@@ -23,31 +20,7 @@ export default class Header extends HeaderBase {
|
|
|
23
20
|
this._scopedNavItems = toJson(value);
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
@api
|
|
27
|
-
get languages() {
|
|
28
|
-
return this._languages;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
set languages(value) {
|
|
32
|
-
this._languages = toJson(value);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
@api
|
|
36
|
-
get language() {
|
|
37
|
-
return this._language;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
set language(value) {
|
|
41
|
-
if (this._language !== value) {
|
|
42
|
-
this._language = value;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
private _language: string | null = null;
|
|
47
|
-
private _languages!: OptionWithLink[];
|
|
48
23
|
private _scopedNavItems!: OptionWithNested[];
|
|
49
|
-
private smallMobile = false;
|
|
50
|
-
private smallMobileMatchMedia!: MediaQueryList;
|
|
51
24
|
private tablet = false;
|
|
52
25
|
private tabletMatchMedia!: MediaQueryList;
|
|
53
26
|
private shouldRender = false;
|
|
@@ -60,24 +33,6 @@ export default class Header extends HeaderBase {
|
|
|
60
33
|
return this.scopedNavItems && this.scopedNavItems.length > 0;
|
|
61
34
|
}
|
|
62
35
|
|
|
63
|
-
private get hasLanguages(): boolean {
|
|
64
|
-
return !!(this.languages && this.languages.length);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private get showMobileLanguages(): boolean {
|
|
68
|
-
return this.smallMobile && this.hasLanguages;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private get languageLabel(): string {
|
|
72
|
-
return (
|
|
73
|
-
(this.language &&
|
|
74
|
-
this.languages.find(
|
|
75
|
-
(lang) => get(lang, this.langValuePath) === this.language
|
|
76
|
-
)?.label) ||
|
|
77
|
-
this.languages[0].label
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
36
|
connectedCallback(): void {
|
|
82
37
|
super.connectedCallback();
|
|
83
38
|
this.tabletMatchMedia = window.matchMedia(
|
|
@@ -86,14 +41,6 @@ export default class Header extends HeaderBase {
|
|
|
86
41
|
this.onTabletChange(this.tabletMatchMedia);
|
|
87
42
|
this.tabletMatchMedia.addEventListener("change", this.onTabletChange);
|
|
88
43
|
|
|
89
|
-
this.smallMobileMatchMedia = window.matchMedia(
|
|
90
|
-
`(max-width: ${SMALL_MOBILE_MATCH})`
|
|
91
|
-
);
|
|
92
|
-
this.onSmallMobileChange(this.smallMobileMatchMedia);
|
|
93
|
-
this.smallMobileMatchMedia.addEventListener(
|
|
94
|
-
"change",
|
|
95
|
-
this.onSmallMobileChange
|
|
96
|
-
);
|
|
97
44
|
if (
|
|
98
45
|
(window.location.pathname.includes("/docs/") &&
|
|
99
46
|
window.location.pathname !== "/docs/apis") ||
|
|
@@ -110,53 +57,15 @@ export default class Header extends HeaderBase {
|
|
|
110
57
|
"change",
|
|
111
58
|
this.onTabletChange
|
|
112
59
|
);
|
|
113
|
-
|
|
114
|
-
this.smallMobileMatchMedia.removeEventListener(
|
|
115
|
-
"change",
|
|
116
|
-
this.onSmallMobileChange
|
|
117
|
-
);
|
|
118
60
|
}
|
|
119
61
|
|
|
120
62
|
private onTabletChange = (e: MediaQueryListEvent | MediaQueryList) =>
|
|
121
63
|
(this.tablet = e.matches);
|
|
122
64
|
|
|
123
|
-
private onSmallMobileChange = (e: MediaQueryListEvent | MediaQueryList) =>
|
|
124
|
-
(this.smallMobile = e.matches);
|
|
125
|
-
|
|
126
65
|
protected additionalClasses(): string {
|
|
127
66
|
return cx(
|
|
128
67
|
this.brand && "has-brand",
|
|
129
68
|
this.hasScopedNavItems && "has-scoped-nav-items"
|
|
130
69
|
);
|
|
131
70
|
}
|
|
132
|
-
|
|
133
|
-
private onLangChange(event: CustomEvent<string>): void {
|
|
134
|
-
const { detail } = event;
|
|
135
|
-
this._language = detail;
|
|
136
|
-
|
|
137
|
-
this.dispatchEvent(new CustomEvent("langchange", { detail }));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
private handleBailClick(event: Event) {
|
|
141
|
-
const payload = {
|
|
142
|
-
click_text: "pdf",
|
|
143
|
-
click_url: this.bailHref,
|
|
144
|
-
element_title: "pdf",
|
|
145
|
-
element_type: "link",
|
|
146
|
-
content_category: "download"
|
|
147
|
-
};
|
|
148
|
-
track(event.target!, "custEv_pdfDownload", {
|
|
149
|
-
...payload,
|
|
150
|
-
file_name: this.getFilename(this.bailHref!),
|
|
151
|
-
file_extension: "pdf"
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
track(event.target!, "custEv_linkClick", {
|
|
155
|
-
...payload
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
private getFilename = function (path: string) {
|
|
160
|
-
return path.substring(path.lastIndexOf("/") + 1);
|
|
161
|
-
};
|
|
162
71
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
@import "dxHelpers/reset";
|
|
2
|
+
|
|
3
|
+
:host {
|
|
4
|
+
--button-primary-color: var(--dx-g-blue-vibrant-50);
|
|
5
|
+
--button-primary-color-hover: var(--dx-g-cloud-blue-vibrant-95);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.footer-display {
|
|
9
|
+
display: flex;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.footer_lang-dropdown {
|
|
13
|
+
display: flex;
|
|
14
|
+
padding: 0 var(--dx-g-spacing-md);
|
|
15
|
+
margin-left: var(--dx-g-spacing-sm);
|
|
16
|
+
height: var(--dx-g-spacing-xl);
|
|
17
|
+
border-radius: var(--dx-g-spacing-xs);
|
|
18
|
+
align-items: center;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.footer_lang-dropdown > dx-button {
|
|
22
|
+
--dx-c-button-primary-color: var(--button-primary-color);
|
|
23
|
+
--dx-c-slot-empty-width: min-content;
|
|
24
|
+
--border-color: var(--button-primary-color);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.footer_lang-dropdown:hover,
|
|
28
|
+
.footer_lang-dropdown:active,
|
|
29
|
+
.footer_lang-dropdown:focus,
|
|
30
|
+
.pdf_bail-link:hover {
|
|
31
|
+
background-color: var(--button-primary-color-hover);
|
|
32
|
+
|
|
33
|
+
--border-color: var(--button-primary-color-hover);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.pdf_bail-link {
|
|
37
|
+
--dx-c-button-horizontal-spacing: var(--dx-g-spacing-sm);
|
|
38
|
+
|
|
39
|
+
padding: 0 var(--dx-g-spacing-md);
|
|
40
|
+
border-radius: var(--dx-g-spacing-xs);
|
|
41
|
+
display: flex;
|
|
42
|
+
height: var(--dx-g-spacing-xl);
|
|
43
|
+
align-items: center;
|
|
44
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div if:false={mobile} class="footer-display">
|
|
3
|
+
<dx-button
|
|
4
|
+
if:true={hasBailLink}
|
|
5
|
+
aria-label={bailLabel}
|
|
6
|
+
class="pdf_bail-link"
|
|
7
|
+
href={bailHref}
|
|
8
|
+
onclick={handleBailClick}
|
|
9
|
+
variant="inline"
|
|
10
|
+
icon-symbol="new_window"
|
|
11
|
+
target="_blank"
|
|
12
|
+
>
|
|
13
|
+
{bailLabel}
|
|
14
|
+
</dx-button>
|
|
15
|
+
<dx-dropdown
|
|
16
|
+
if:true={hasLanguages}
|
|
17
|
+
class="footer_lang-dropdown"
|
|
18
|
+
options={languages}
|
|
19
|
+
small
|
|
20
|
+
value-path={langValuePath}
|
|
21
|
+
value={language}
|
|
22
|
+
onchange={onLangChange}
|
|
23
|
+
variant="docoption"
|
|
24
|
+
lang-picker="true"
|
|
25
|
+
>
|
|
26
|
+
<dx-button
|
|
27
|
+
aria-label="Select Language"
|
|
28
|
+
variant="inline"
|
|
29
|
+
icon-size="medium"
|
|
30
|
+
icon-symbol="world"
|
|
31
|
+
>
|
|
32
|
+
{languageLabel}
|
|
33
|
+
</dx-button>
|
|
34
|
+
</dx-dropdown>
|
|
35
|
+
</div>
|
|
36
|
+
<div if:true={mobile} class="footer-display">
|
|
37
|
+
<dx-dropdown
|
|
38
|
+
if:true={hasLanguages}
|
|
39
|
+
class="footer_lang-dropdown"
|
|
40
|
+
options={languages}
|
|
41
|
+
small
|
|
42
|
+
value-path={langValuePath}
|
|
43
|
+
value={language}
|
|
44
|
+
onchange={onLangChange}
|
|
45
|
+
variant="docoption"
|
|
46
|
+
lang-picker="true"
|
|
47
|
+
>
|
|
48
|
+
<dx-button
|
|
49
|
+
aria-label="Select Language"
|
|
50
|
+
variant="inline"
|
|
51
|
+
icon-size="small"
|
|
52
|
+
icon-symbol="world"
|
|
53
|
+
>
|
|
54
|
+
{languageLabel}
|
|
55
|
+
</dx-button>
|
|
56
|
+
</dx-dropdown>
|
|
57
|
+
</div>
|
|
58
|
+
</template>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* eslint-disable @lwc/lwc/no-document-query */
|
|
2
|
+
import { LightningElement, api } from "lwc";
|
|
3
|
+
import type { OptionWithLink } from "typings/custom";
|
|
4
|
+
import { toJson } from "dxUtils/normalizers";
|
|
5
|
+
import get from "lodash.get";
|
|
6
|
+
import { track } from "dxUtils/analytics";
|
|
7
|
+
|
|
8
|
+
const MOBILE_SIZE_MATCH = "768px";
|
|
9
|
+
|
|
10
|
+
export default class SidebarFooterNav extends LightningElement {
|
|
11
|
+
@api langValuePath: string = "id";
|
|
12
|
+
@api bailHref?: string | null = null;
|
|
13
|
+
@api bailLabel?: string | null = null;
|
|
14
|
+
|
|
15
|
+
@api
|
|
16
|
+
get languages() {
|
|
17
|
+
return this._languages;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
set languages(value) {
|
|
21
|
+
this._languages = toJson(value);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@api
|
|
25
|
+
get language() {
|
|
26
|
+
return this._language;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
set language(value) {
|
|
30
|
+
if (this._language !== value) {
|
|
31
|
+
this._language = value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private _languages!: OptionWithLink[];
|
|
36
|
+
private _language: string | null = null;
|
|
37
|
+
private mobile: boolean = false;
|
|
38
|
+
private matchMedia!: MediaQueryList;
|
|
39
|
+
|
|
40
|
+
private get hasLanguages(): boolean {
|
|
41
|
+
return !!(this.languages && this.languages.length > 1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private get languageLabel(): string {
|
|
45
|
+
return (
|
|
46
|
+
(this.language &&
|
|
47
|
+
this.languages.find(
|
|
48
|
+
(lang) => get(lang, this.langValuePath) === this.language
|
|
49
|
+
)?.label) ||
|
|
50
|
+
this.languages[0].label
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get hasBailLink(): boolean {
|
|
55
|
+
return !!(this.bailHref && this.bailLabel);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private onLangChange(event: CustomEvent<string>): void {
|
|
59
|
+
const { detail } = event;
|
|
60
|
+
this._language = detail;
|
|
61
|
+
|
|
62
|
+
this.dispatchEvent(
|
|
63
|
+
new CustomEvent("langchange", {
|
|
64
|
+
detail,
|
|
65
|
+
bubbles: true,
|
|
66
|
+
composed: true
|
|
67
|
+
})
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private getFilename = function (path: string) {
|
|
72
|
+
return path.substring(path.lastIndexOf("/") + 1);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
private handleBailClick(event: Event) {
|
|
76
|
+
const payload = {
|
|
77
|
+
click_text: "pdf",
|
|
78
|
+
click_url: this.bailHref,
|
|
79
|
+
element_title: "pdf",
|
|
80
|
+
element_type: "link",
|
|
81
|
+
content_category: "download"
|
|
82
|
+
};
|
|
83
|
+
track(event.target!, "custEv_pdfDownload", {
|
|
84
|
+
...payload,
|
|
85
|
+
file_name: this.getFilename(this.bailHref!),
|
|
86
|
+
file_extension: "pdf"
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
track(event.target!, "custEv_linkClick", {
|
|
90
|
+
...payload
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
connectedCallback() {
|
|
95
|
+
this.matchMedia = window.matchMedia(
|
|
96
|
+
`(max-width: ${MOBILE_SIZE_MATCH})`
|
|
97
|
+
);
|
|
98
|
+
this.onMediaChange(this.matchMedia);
|
|
99
|
+
this.matchMedia.addEventListener("change", this.onMediaChange);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
disconnectedCallback() {
|
|
103
|
+
this.matchMedia.removeEventListener("change", this.onMediaChange);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private onMediaChange = (event: MediaQueryListEvent | MediaQueryList) => {
|
|
107
|
+
this.mobile = event.matches;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
@@ -61,12 +61,15 @@ export type ApiDocLanguage = {
|
|
|
61
61
|
|
|
62
62
|
export interface Header extends Element {
|
|
63
63
|
subtitle: string;
|
|
64
|
+
headerHref: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type SiderbarFooter = {
|
|
64
68
|
bailHref: string;
|
|
65
69
|
bailLabel: string;
|
|
66
70
|
languages: Array<DocLanguage>;
|
|
67
71
|
language?: string;
|
|
68
|
-
|
|
69
|
-
}
|
|
72
|
+
};
|
|
70
73
|
|
|
71
74
|
export type ApiNavItem = {
|
|
72
75
|
children: Array<ApiNavItem>;
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
sidebar-value={sidebarValue}
|
|
12
12
|
onselect={handleSelect}
|
|
13
13
|
use-old-sidebar={useOldSidebar}
|
|
14
|
+
onlangchange={handleLanguageChange}
|
|
15
|
+
languages={sidebarFooterContent.languages}
|
|
16
|
+
language={sidebarFooterContent.language}
|
|
17
|
+
bail-href={sidebarFooterContent.bailHref}
|
|
18
|
+
bail-label={sidebarFooterContent.bailLabel}
|
|
14
19
|
>
|
|
15
20
|
<doc-phase
|
|
16
21
|
slot="version-banner"
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
DocVersion,
|
|
9
9
|
TreeNode,
|
|
10
10
|
Header,
|
|
11
|
+
SiderbarFooter,
|
|
11
12
|
HistoryState,
|
|
12
13
|
PageReference,
|
|
13
14
|
TocMap
|
|
@@ -16,7 +17,6 @@ import { SearchSyncer } from "docUtils/searchSyncer";
|
|
|
16
17
|
import { LightningElementWithState } from "dxBaseElements/lightningElementWithState";
|
|
17
18
|
import { logCoveoPageView, oldVersionDocInfo } from "docUtils/utils";
|
|
18
19
|
import { Breadcrumb, DocPhaseInfo, Language } from "typings/custom";
|
|
19
|
-
import { track as trackGTM } from "dxUtils/analytics";
|
|
20
20
|
|
|
21
21
|
// TODO: Imitating from actual implementation as doc-content use it like this. We should refactor it later.
|
|
22
22
|
const handleContentError = (error: any): void => console.log(error);
|
|
@@ -26,6 +26,12 @@ const PIXEL_PER_CHARACTER_MAP: { [key: string]: number } = {
|
|
|
26
26
|
"ja-jp": 12.5
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
const defaultSidebarFooter: SiderbarFooter = {
|
|
30
|
+
bailHref: "",
|
|
31
|
+
bailLabel: "",
|
|
32
|
+
languages: [],
|
|
33
|
+
language: ""
|
|
34
|
+
};
|
|
29
35
|
export default class DocXmlContent extends LightningElementWithState<{
|
|
30
36
|
isFetchingDocument: boolean;
|
|
31
37
|
isFetchingContent: boolean;
|
|
@@ -64,15 +70,16 @@ export default class DocXmlContent extends LightningElementWithState<{
|
|
|
64
70
|
private docContent = "";
|
|
65
71
|
private language?: DocLanguage | null = null;
|
|
66
72
|
private loaded = false;
|
|
73
|
+
private _pageHeader?: Header;
|
|
67
74
|
private pdfUrl = "";
|
|
68
75
|
private tocMap: TocMap = {};
|
|
69
76
|
private sidebarContent: Array<TreeNode> | null = null;
|
|
70
77
|
private version: DocVersion | null = null;
|
|
71
78
|
private docTitle = "";
|
|
72
79
|
private _pathName = "";
|
|
73
|
-
private _pageHeader?: Header;
|
|
74
80
|
private listenerAttached = false;
|
|
75
81
|
private _enableCoveo?: boolean = false;
|
|
82
|
+
private sidebarFooterContent: SiderbarFooter = { ...defaultSidebarFooter };
|
|
76
83
|
|
|
77
84
|
private searchSyncer = new SearchSyncer({
|
|
78
85
|
callbacks: {
|
|
@@ -214,13 +221,6 @@ export default class DocXmlContent extends LightningElementWithState<{
|
|
|
214
221
|
disconnectedCallback(): void {
|
|
215
222
|
window.removeEventListener("popstate", this.handlePopState);
|
|
216
223
|
this.searchSyncer.dispose();
|
|
217
|
-
if (this.listenerAttached) {
|
|
218
|
-
this.pageHeader.removeEventListener(
|
|
219
|
-
"langchange",
|
|
220
|
-
this.handleLanguageChange
|
|
221
|
-
);
|
|
222
|
-
this.listenerAttached = false;
|
|
223
|
-
}
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
private get languageId(): string | undefined {
|
|
@@ -371,17 +371,6 @@ export default class DocXmlContent extends LightningElementWithState<{
|
|
|
371
371
|
({ id }) => id === event.detail
|
|
372
372
|
);
|
|
373
373
|
this.pageReference.docId = this.language!.url;
|
|
374
|
-
|
|
375
|
-
trackGTM(event.target!, "custEv_ctaLinkClick", {
|
|
376
|
-
click_text: event.detail,
|
|
377
|
-
element_title: "language selector",
|
|
378
|
-
click_url: `${window.location.origin}${this.pageReferenceToString(
|
|
379
|
-
this.pageReference
|
|
380
|
-
)}`,
|
|
381
|
-
element_type: "link",
|
|
382
|
-
content_category: "cta"
|
|
383
|
-
});
|
|
384
|
-
|
|
385
374
|
this.updateUrl();
|
|
386
375
|
this.fetchDocument();
|
|
387
376
|
};
|
|
@@ -414,12 +403,8 @@ export default class DocXmlContent extends LightningElementWithState<{
|
|
|
414
403
|
}
|
|
415
404
|
|
|
416
405
|
getReferenceFromUrl(): PageReference {
|
|
417
|
-
const [
|
|
418
|
-
|
|
419
|
-
docId,
|
|
420
|
-
deliverable,
|
|
421
|
-
contentDocumentId
|
|
422
|
-
] = window.location.pathname.substr(1).split("/");
|
|
406
|
+
const [page, docId, deliverable, contentDocumentId] =
|
|
407
|
+
window.location.pathname.substr(1).split("/");
|
|
423
408
|
|
|
424
409
|
const { origin: domain, hash, search } = window.location;
|
|
425
410
|
|
|
@@ -469,7 +454,7 @@ export default class DocXmlContent extends LightningElementWithState<{
|
|
|
469
454
|
this.availableVersions = data.availableVersions;
|
|
470
455
|
this.pdfUrl = data.pdfUrl;
|
|
471
456
|
|
|
472
|
-
this.
|
|
457
|
+
this.updateHeaderAndSidebarFooter();
|
|
473
458
|
|
|
474
459
|
this.buildBreadcrumbs();
|
|
475
460
|
|
|
@@ -533,7 +518,7 @@ export default class DocXmlContent extends LightningElementWithState<{
|
|
|
533
518
|
});
|
|
534
519
|
}
|
|
535
520
|
|
|
536
|
-
|
|
521
|
+
updateHeaderAndSidebarFooter(): void {
|
|
537
522
|
if (!this.pageHeader) {
|
|
538
523
|
return;
|
|
539
524
|
}
|
|
@@ -543,20 +528,12 @@ export default class DocXmlContent extends LightningElementWithState<{
|
|
|
543
528
|
}
|
|
544
529
|
|
|
545
530
|
if (this.pdfUrl) {
|
|
546
|
-
this.
|
|
547
|
-
this.
|
|
531
|
+
this.sidebarFooterContent.bailHref = this.pdfUrl;
|
|
532
|
+
this.sidebarFooterContent.bailLabel = "PDF";
|
|
548
533
|
}
|
|
549
534
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
"langchange",
|
|
553
|
-
this.handleLanguageChange
|
|
554
|
-
);
|
|
555
|
-
this.listenerAttached = true;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
this.pageHeader.languages = this.availableLanguages;
|
|
559
|
-
this.pageHeader.language = this.language?.id;
|
|
535
|
+
this.sidebarFooterContent.languages = this.availableLanguages;
|
|
536
|
+
this.sidebarFooterContent.language = this.language?.id;
|
|
560
537
|
|
|
561
538
|
if (this.pageReference) {
|
|
562
539
|
const { docId, deliverable, page } = this.pageReference;
|
|
@@ -581,20 +558,14 @@ export default class DocXmlContent extends LightningElementWithState<{
|
|
|
581
558
|
}
|
|
582
559
|
|
|
583
560
|
private updateSearchInput(searchParam: string): void {
|
|
584
|
-
(
|
|
585
|
-
"doc-content-layout"
|
|
586
|
-
)
|
|
561
|
+
(
|
|
562
|
+
this.template.querySelector("doc-content-layout") as any
|
|
563
|
+
)?.setSidebarInputValue(searchParam);
|
|
587
564
|
}
|
|
588
565
|
|
|
589
566
|
private pageReferenceToString(reference: PageReference): string {
|
|
590
|
-
const {
|
|
591
|
-
|
|
592
|
-
docId,
|
|
593
|
-
deliverable,
|
|
594
|
-
contentDocumentId,
|
|
595
|
-
hash,
|
|
596
|
-
search
|
|
597
|
-
} = reference;
|
|
567
|
+
const { page, docId, deliverable, contentDocumentId, hash, search } =
|
|
568
|
+
reference;
|
|
598
569
|
return `/${page}/${docId}/${deliverable}/${contentDocumentId}${this.normalizeSearch(
|
|
599
570
|
search!
|
|
600
571
|
)}${this.normalizeHash(hash)}`;
|