Passed
Push — 6.4.10.0 ( 7787f7...516736 )
by Christian
17:15
created

index.ts ➔ onSelectFieldChange   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
1
import type CriteriaType from 'src/core/data/criteria.data';
2
import type RepositoryType from 'src/core/data/repository.data';
3
import type EntityCollectionType from 'src/core/data/entity-collection.data';
4
import template from './sw-text-editor-link-menu.html.twig';
5
6
const { Component } = Shopware;
7
const { Criteria, EntityCollection } = Shopware.Data;
8
9
type LinkCategories = 'link' | 'detail' | 'category' | 'email' | 'phone';
10
interface TextEditorLinkMenuConfig {
11
    title: string,
12
    icon: string,
13
    expanded: boolean,
14
    newTab: boolean,
15
    displayAsButton: boolean,
16
    value: string,
17
    type: string,
18
    tag: 'a',
19
    active: false,
20
}
21
22
/**
23
 * @private
24
 */
25
Component.register('sw-text-editor-link-menu', {
26
    template,
27
28
    inject: [
29
        'repositoryFactory',
30
    ],
31
32
    props: {
33
        buttonConfig: {
34
            type: Object as () => TextEditorLinkMenuConfig,
35
            required: true,
36
        },
37
    },
38
39
    data(): {
40
        linkTitle: string,
41
        linkTarget: string,
42
        isHTTPs: boolean,
43
        opensNewTab: boolean,
44
        displayAsButton: boolean,
45
        linkCategory: LinkCategories,
46
        categoryCollection?: EntityCollectionType,
47
        } {
48
        return {
49
            linkTitle: '',
50
            linkTarget: '',
51
            isHTTPs: false,
52
            opensNewTab: false,
53
            displayAsButton: false,
54
            linkCategory: 'link',
55
            categoryCollection: undefined,
56
        };
57
    },
58
59
    computed: {
60
        seoUrlReplacePrefix(): string {
61
            return '124c71d524604ccbad6042edce3ac799';
62
        },
63
64
        entityFilter(): CriteriaType {
65
            const criteria = new Criteria();
66
            criteria.addSorting(Criteria.sort('name', 'ASC'));
67
68
            return criteria;
69
        },
70
71
        categoryRepository(): RepositoryType {
72
            return this.repositoryFactory.create('category');
73
        },
74
    },
75
76
    watch: {
77
        buttonConfig: {
78
            async handler(buttonConfig): Promise<void> {
79
                const { title, newTab, displayAsButton, value, type } = buttonConfig as TextEditorLinkMenuConfig;
80
                this.linkTitle = title;
81
                this.opensNewTab = newTab;
82
                this.displayAsButton = displayAsButton;
83
84
                const parsedResult = await this.parseLink(value, type);
85
                this.linkCategory = parsedResult.type;
86
                this.linkTarget = parsedResult.target;
87
            },
88
            immediate: true,
89
        },
90
    },
91
92
    created(): void {
93
        this.createdComponent();
94
    },
95
96
    methods: {
97
        createdComponent(): void {
98
            this.categoryCollection = this.getEmptyCategoryCollection();
99
        },
100
101
        getCategoryCollection(categoryId: string): Promise<EntityCollectionType> {
102
            const categoryCriteria = (new Criteria()).addFilter(Criteria.equals('id', categoryId));
103
            return this.categoryRepository.search(categoryCriteria);
104
        },
105
106
        getEmptyCategoryCollection(): EntityCollectionType {
107
            return new EntityCollection(
108
                this.categoryRepository.route,
109
                this.categoryRepository.entityName,
110
                Shopware.Context.api,
111
            );
112
        },
113
114
        async parseLink(link: string, detectedLinkType: string): Promise<{ type: LinkCategories, target: string }> {
115
            const slicedLink = link.slice(0, -1).split('/');
116
117
            if (link.startsWith(this.seoUrlReplacePrefix)) {
118
                const [productId] = slicedLink.splice(-1);
119
                return { type: 'detail', target: productId };
120
            }
121
122
            if (link.startsWith('category')) {
123
                this.categoryCollection = await this.getCategoryCollection(slicedLink[2]);
124
                return {
125
                    type: 'category',
126
                    target: slicedLink[2],
127
                };
128
            }
129
130
            if (link.startsWith('mailto:')) {
131
                return {
132
                    type: 'email',
133
                    target: link.replace('mailto:', ''),
134
                };
135
            }
136
137
            if (link.startsWith('tel:')) {
138
                return {
139
                    type: 'phone',
140
                    target: link.replace('tel:', ''),
141
                };
142
            }
143
144
            return {
145
                target: link,
146
                type: detectedLinkType as LinkCategories,
147
            };
148
        },
149
150
        replaceCategorySelection(category: {id: string}): void {
151
            this.linkTarget = category.id;
152
        },
153
154
        removeCategorySelection(): void {
155
            this.linkTarget = '';
156
        },
157
158
        prepareLink(): string {
159
            switch (this.linkCategory) {
160
                case 'detail':
161
                    return `${this.seoUrlReplacePrefix}/detail/${this.linkTarget}#`;
162
                case 'category':
163
                    return `${this.seoUrlReplacePrefix}/navigation/${this.linkTarget}#`;
164
                case 'email':
165
                    return `mailto:${this.linkTarget}`;
166
                case 'phone':
167
                    return `tel:${this.linkTarget.replace(/\//, '')}`;
168
                default:
169
                    return this.addProtocolToLink(this.linkTarget);
170
            }
171
        },
172
173
        addProtocolToLink(link: string): string {
174
            if (/(^(\w+):\/\/)|(mailto:)|(fax:)|(tel:)/.test(link)) {
175
                return link;
176
            }
177
178
            const isInternal = /^\/[^\/\s]/.test(link);
179
            const isAnchor = link.substring(0, 1) === '#';
180
            const isProtocolRelative = /^\/\/[^\/\s]/.test(link);
181
182
            if (!isInternal && !isAnchor && !isProtocolRelative) {
183
                link = `http://${link}`;
184
            }
185
186
            return link;
187
        },
188
189
        setLink(): void {
190
            this.$emit('button-click', {
191
                type: 'link',
192
                value: this.prepareLink(),
193
                displayAsButton: this.displayAsButton ? 'primary' : false,
194
                newTab: this.opensNewTab,
195
            });
196
        },
197
198
        removeLink(): void {
199
            this.$emit('button-click', {
200
                type: 'linkRemove',
201
            });
202
        },
203
204
        onSelectFieldChange(): void {
205
            this.linkTarget = '';
206
        },
207
    },
208
});
209