Passed
Push — trunk ( 71cd51...9a7069 )
by Christian
11:50 queued 14s
created

index.ts ➔ locationIdPathnameQueryKey   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
import template from './sw-iframe-renderer.html.twig';
2
import type { Extension } from '../../../state/extensions.store';
3
4
/**
5
 * @package admin
6
 *
7
 * @private
8
 * @description This component renders iFrame views for extensions
9
 * @status ready
10
 * @example-type static
11
 * @component-example
12
 * <sw-iframe-renderer src="https://www.my-source.com" locationId="my-special-location" />
13
 */
14
Shopware.Component.register('sw-iframe-renderer', {
15
    template,
16
17
    inject: ['extensionSdkService'],
18
19
    props: {
20
        src: {
21
            type: String,
22
            required: true,
23
        },
24
        locationId: {
25
            type: String,
26
            required: true,
27
        },
28
    },
29
30
    data(): {
31
        heightHandler: null | (() => void),
32
        urlHandler: null | (() => void),
33
        locationHeight: null | number,
34
        signedIframeSrc: null | string,
35
        } {
36
        return {
37
            heightHandler: null,
38
            urlHandler: null,
39
            locationHeight: null,
40
            signedIframeSrc: null,
41
        };
42
    },
43
44
    created() {
45
        this.heightHandler = Shopware.ExtensionAPI.handle('locationUpdateHeight', ({ height, locationId }) => {
46
            if (locationId === this.locationId) {
47
                this.locationHeight = Number(height) ?? null;
48
            }
49
        });
50
51
        this.urlHandler = Shopware.ExtensionAPI.handle('locationUpdateUrl', async ({
52
            hash,
53
            pathname,
54
            searchParams,
55
            locationId,
56
        }) => {
57
            if (locationId !== this.locationId) {
58
                return;
59
            }
60
61
            const filteredSearchParams = JSON.stringify(searchParams.filter(([key]) => {
62
                return ![
63
                    'location-id',
64
                    'privileges',
65
                    'shop-id',
66
                    'shop-url',
67
                    'timestamp',
68
                    'sw-version',
69
                    'sw-context-language',
70
                    'sw-user-language',
71
                    'shopware-shop-signature',
72
                ].includes(key);
73
            }));
74
75
            await this.$router.replace({
76
                query: {
77
                    [this.locationIdHashQueryKey]: hash,
78
                    [this.locationIdPathnameQueryKey]: pathname,
79
                    [this.locationIdSearchParamsQueryKey]: filteredSearchParams,
80
                },
81
            });
82
        });
83
    },
84
85
    beforeDestroy() {
86
        if (this.heightHandler) {
87
            this.heightHandler();
88
        }
89
90
        if (this.urlHandler) {
91
            this.urlHandler();
92
        }
93
    },
94
95
    computed: {
96
        locationIdHashQueryKey(): string {
97
            return `locationId_${this.locationId}_hash`;
98
        },
99
100
        locationIdPathnameQueryKey(): string {
101
            return `locationId_${this.locationId}_pathname`;
102
        },
103
104
        locationIdSearchParamsQueryKey(): string {
105
            return `locationId_${this.locationId}_searchParams`;
106
        },
107
108
        componentName(): string|undefined {
109
            return Shopware.State.get('sdkLocation').locations[this.locationId];
110
        },
111
112
        extension(): Extension | undefined {
113
            const extensions = Shopware.State.get('extensions');
114
115
            return Object.values(extensions).find((ext) => {
116
                return ext.baseUrl === this.src;
117
            });
118
        },
119
120
        extensionIsApp(): boolean {
121
            return this.extension?.type === 'app';
122
        },
123
124
        iFrameSrc(): string {
125
            const urlObject = new URL(this.src, window.location.origin);
126
127
            urlObject.searchParams.append('location-id', this.locationId);
128
            if (this.extension) {
129
                urlObject.searchParams.append('privileges', JSON.stringify(this.extension.permissions));
130
            }
131
132
            return urlObject.toString();
133
        },
134
135
        iFrameHeight(): string {
136
            if (typeof this.locationHeight === 'number') {
137
                return `${this.locationHeight}px`;
138
            }
139
140
            return '100%';
141
        },
142
    },
143
144
    watch: {
145
        extension: {
146
            immediate: true,
147
            handler(extension) {
148
                if (!extension || !this.extensionIsApp) {
149
                    return;
150
                }
151
152
                // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
153
                this.extensionSdkService.signIframeSrc(extension.name, this.iFrameSrc).then((response) => {
154
                    const uri = (response as { uri?: string})?.uri;
155
156
                    if (!uri) {
157
                        return;
158
                    }
159
160
                    // add information from query with hash, pathname and queries
161
                    const urlObject = new URL(uri);
162
                    const hash = this.$route.query[this.locationIdHashQueryKey];
163
                    const pathname = this.$route.query[this.locationIdPathnameQueryKey];
164
                    const searchParams = this.$route.query[this.locationIdSearchParamsQueryKey];
165
166
                    if (hash) {
167
                        urlObject.hash = hash as string;
168
                    }
169
170
                    if (pathname) {
171
                        urlObject.pathname = pathname as string;
172
                    }
173
174
                    if (searchParams) {
175
                        const parsedSearchParams = JSON.parse(searchParams as string) as [string, string][];
176
177
                        parsedSearchParams.forEach(([key, value]) => {
178
                            urlObject.searchParams.append(key, value);
179
                        });
180
                    }
181
182
                    this.signedIframeSrc = urlObject.toString();
183
                    // eslint-disable-next-line @typescript-eslint/no-empty-function
184
                }).catch(() => {});
185
            },
186
        },
187
    },
188
});
189