comand-component-library 3.1.43 → 3.1.46
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/dist/comand-component-library.css +1 -1
- package/dist/comand-component-library.umd.min.js +1 -1
- package/package.json +47 -40
- package/src/App.vue +379 -136
- package/src/ComponentDocumentation.vue +156 -0
- package/src/ComponentLibraryHelp.vue +20 -0
- package/src/assets/data/accordion.json +21 -24
- package/src/assets/data/address-data.json +34 -0
- package/src/assets/data/bank-account-data.json +22 -0
- package/src/assets/data/box-product.json +14 -4
- package/src/assets/data/box-user.json +48 -22
- package/src/assets/data/breadcrumbs.json +11 -3
- package/src/assets/data/cookie-disclaimer.json +4 -4
- package/src/assets/data/fake-select-colors.json +4 -0
- package/src/assets/data/fake-select-countries.json +12 -12
- package/src/assets/data/fake-select-filter-options.json +14 -0
- package/src/assets/data/fake-select-options-with-icons.json +6 -12
- package/src/assets/data/fake-select-options.json +3 -3
- package/src/assets/data/list-of-links-section-anchors.json +23 -0
- package/src/assets/data/list-of-links-top-header-navigation.json +20 -0
- package/src/assets/data/list-of-links.json +42 -0
- package/src/assets/data/main-navigation.json +48 -0
- package/src/assets/data/multistep-form-progress-bar.json +33 -0
- package/src/assets/data/select-options.json +4 -0
- package/src/assets/data/{share-buttons.json → share-buttons-page-by-json.json} +8 -8
- package/src/assets/data/share-buttons-page-by-property.json +30 -0
- package/src/assets/data/switch-language.json +20 -0
- package/src/assets/data/table-large.json +1 -1
- package/src/assets/data/table-small.json +1 -1
- package/src/assets/styles/global-styles.scss +43 -14
- package/src/assets/styles/transitions.scss +21 -1
- package/src/components/CmdAccordion.vue +43 -42
- package/src/components/CmdAddressData.vue +124 -56
- package/src/components/CmdBackToTopButton.vue +3 -3
- package/src/components/CmdBankAccountData.vue +104 -0
- package/src/components/CmdBox.vue +253 -56
- package/src/components/CmdBoxSiteSearch.vue +138 -39
- package/src/components/CmdBoxWrapper.vue +206 -0
- package/src/components/CmdBreadcrumbs.vue +29 -13
- package/src/components/CmdCompanyLogo.vue +6 -4
- package/src/components/CmdCookieDisclaimer.vue +99 -75
- package/src/components/CmdCopyrightInformation.vue +1 -1
- package/src/components/CmdCustomHeadline.vue +93 -0
- package/src/components/CmdFakeSelect.vue +330 -66
- package/src/components/CmdFancyBox.vue +47 -33
- package/src/components/CmdForm.vue +107 -0
- package/src/components/CmdFormElement.vue +528 -83
- package/src/components/CmdFormFilters.vue +25 -11
- package/src/components/CmdGoogleMaps.vue +9 -3
- package/src/components/CmdImageGallery.vue +28 -5
- package/src/components/CmdImageZoom.vue +9 -1
- package/src/components/CmdListOfLinks.vue +169 -0
- package/src/components/CmdLoginForm.vue +146 -66
- package/src/components/CmdMainNavigation.vue +140 -42
- package/src/components/CmdMultipleSwitch.vue +33 -2
- package/src/components/CmdMultistepFormProgressBar.vue +60 -10
- package/src/components/CmdOpeningHours.vue +36 -10
- package/src/components/CmdPager.vue +7 -5
- package/src/components/CmdProgressBar.vue +21 -4
- package/src/components/CmdShareButtons.vue +64 -9
- package/src/components/CmdSiteHeader.vue +25 -12
- package/src/components/CmdSlideButton.vue +5 -2
- package/src/components/CmdSlideshow.vue +23 -7
- package/src/components/CmdSwitchButton.vue +15 -6
- package/src/components/CmdSwitchLanguage.vue +18 -10
- package/src/components/CmdSystemMessage.vue +30 -17
- package/src/components/CmdTable.vue +15 -7
- package/src/components/CmdTabs.vue +43 -3
- package/src/components/CmdThumbnailScroller.vue +22 -6
- package/src/components/CmdTooltip.vue +184 -11
- package/src/components/CmdUploadForm.vue +830 -176
- package/src/components/CmdWidthLimitationWrapper.vue +9 -6
- package/src/composables/event.js +8 -0
- package/src/composables/scrollspy.js +52 -0
- package/src/directives/focus.js +19 -0
- package/src/directives/telephone.js +1 -1
- package/src/documentation/commonProps.js +6 -0
- package/src/documentation/components/ComponentCode.vue +50 -0
- package/src/documentation/components/ComponentProperties.vue +237 -0
- package/src/documentation/components/ExampleSectionWrapper.vue +46 -0
- package/src/documentation/components/ViewCodeData.vue +113 -0
- package/src/documentation/data/CmdAccordionHelp.js +22 -0
- package/src/documentation/data/CmdAddressDataHelp.js +17 -0
- package/src/documentation/data/CmdBackToTopButtonHelp.js +3 -0
- package/src/documentation/data/CmdBankAccountDataHelp.js +8 -0
- package/src/documentation/data/CmdBoxHelp.js +45 -0
- package/src/documentation/data/CmdBoxSiteSearchHelp.js +11 -0
- package/src/documentation/data/CmdBreadcrumbsHelp.js +6 -0
- package/src/documentation/data/CmdCompanyLogoHelp.js +8 -0
- package/src/documentation/data/CmdCookieDisclaimerHelp.js +9 -0
- package/src/documentation/data/CmdCopyrightInformation.js +2 -0
- package/src/documentation/data/CmdCustomHeadlineHelp.js +8 -0
- package/src/documentation/data/CmdFakeSelectHelp.js +60 -0
- package/src/documentation/data/CmdFancyBoxHelp.js +7 -0
- package/src/documentation/data/CmdFooterNavigationHelp.js +5 -0
- package/src/documentation/data/CmdFormElementHelp.js +189 -0
- package/src/documentation/data/CmdFormFiltersHelp.js +6 -0
- package/src/documentation/data/CmdFormHelp.js +10 -0
- package/src/documentation/data/CmdGoogleMapsHelp.js +5 -0
- package/src/documentation/data/CmdImageGalleryHelp.js +5 -0
- package/src/documentation/data/CmdImageZoomHelp.js +6 -0
- package/src/documentation/data/CmdListOfLinksHelp.js +24 -0
- package/src/documentation/data/CmdLoginFormHelp.js +6 -0
- package/src/documentation/data/CmdMainNavigationHelp.js +7 -0
- package/src/documentation/data/CmdMultistepFormProgressBarHelp.js +6 -0
- package/src/documentation/data/CmdOpeningHoursHelp.js +10 -0
- package/src/documentation/data/CmdPagerHelp.js +7 -0
- package/src/documentation/data/CmdProgressBarHelp.js +13 -0
- package/src/documentation/data/CmdShareButtonsHelp.js +13 -0
- package/src/documentation/data/CmdSiteHeaderHelp.js +21 -0
- package/src/documentation/data/CmdSlideButtonHelp.js +10 -0
- package/src/documentation/data/CmdSlideshowHelp.js +7 -0
- package/src/documentation/data/CmdSwitchLanguageHelp.js +6 -0
- package/src/documentation/data/CmdSystemMessageHelp.js +32 -0
- package/src/documentation/data/CmdTableHelp.js +14 -0
- package/src/documentation/data/CmdTabsHelp.js +10 -0
- package/src/documentation/data/CmdThumbnailScrollerHelp.js +5 -0
- package/src/documentation/data/CmdTooltipHelp.js +13 -0
- package/src/documentation/data/CmdUploadFormHelp.js +17 -0
- package/src/documentation/data/CmdWidthLimitationWrapperHelp.js +7 -0
- package/src/documentation/data/componentsDescription.json +158 -0
- package/src/documentation/generated/CmdAccordionPropertyDescriptions.json +57 -0
- package/src/documentation/generated/CmdAddressDataPropertyDescriptions.json +32 -0
- package/src/documentation/generated/CmdBackToTopButtonPropertyDescriptions.json +12 -0
- package/src/documentation/generated/CmdBankAccountDataPropertyDescriptions.json +34 -0
- package/src/documentation/generated/CmdBoxPropertyDescriptions.json +91 -0
- package/src/documentation/generated/CmdBoxSiteSearchPropertyDescriptions.json +41 -0
- package/src/documentation/generated/CmdBoxWrapperPropertyDescriptions.json +47 -0
- package/src/documentation/generated/CmdBreadcrumbsPropertyDescriptions.json +17 -0
- package/src/documentation/generated/CmdCompanyLogoPropertyDescriptions.json +27 -0
- package/src/documentation/generated/CmdCookieDisclaimerPropertyDescriptions.json +22 -0
- package/src/documentation/generated/CmdCustomHeadlinePropertyDescriptions.json +22 -0
- package/src/documentation/generated/CmdFakeSelectPropertyDescriptions.json +79 -0
- package/src/documentation/generated/CmdFancyBoxPropertyDescriptions.json +62 -0
- package/src/documentation/generated/CmdFooterNavigationPropertyDescriptions.json +17 -0
- package/src/documentation/generated/CmdFormElementPropertyDescriptions.json +178 -0
- package/src/documentation/generated/CmdFormFiltersPropertyDescriptions.json +32 -0
- package/src/documentation/generated/CmdFormPropertyDescriptions.json +40 -0
- package/src/documentation/generated/CmdGoogleMapsPropertyDescriptions.json +7 -0
- package/src/documentation/generated/CmdImageGalleryPropertyDescriptions.json +22 -0
- package/src/documentation/generated/CmdImageZoomPropertyDescriptions.json +12 -0
- package/src/documentation/generated/CmdListOfLinksPropertyDescriptions.json +60 -0
- package/src/documentation/generated/CmdLoginFormPropertyDescriptions.json +90 -0
- package/src/documentation/generated/CmdMainNavigationPropertyDescriptions.json +62 -0
- package/src/documentation/generated/CmdMultipleSwitchPropertyDescriptions.json +52 -0
- package/src/documentation/generated/CmdMultistepFormProgressBarPropertyDescriptions.json +17 -0
- package/src/documentation/generated/CmdOpeningHoursPropertyDescriptions.json +42 -0
- package/src/documentation/generated/CmdPagerPropertyDescriptions.json +37 -0
- package/src/documentation/generated/CmdProgressBarPropertyDescriptions.json +32 -0
- package/src/documentation/generated/CmdShareButtonsPropertyDescriptions.json +34 -0
- package/src/documentation/generated/CmdSiteHeaderPropertyDescriptions.json +27 -0
- package/src/documentation/generated/CmdSlideButtonPropertyDescriptions.json +25 -0
- package/src/documentation/generated/CmdSlideshowPropertyDescriptions.json +42 -0
- package/src/documentation/generated/CmdSwitchButtonPropertyDescriptions.json +79 -0
- package/src/documentation/generated/CmdSwitchLanguagePropertyDescriptions.json +7 -0
- package/src/documentation/generated/CmdSystemMessagePropertyDescriptions.json +40 -0
- package/src/documentation/generated/CmdTablePropertyDescriptions.json +62 -0
- package/src/documentation/generated/CmdTabsPropertyDescriptions.json +27 -0
- package/src/documentation/generated/CmdThumbnailScrollerPropertyDescriptions.json +32 -0
- package/src/documentation/generated/CmdTooltipPropertyDescriptions.json +17 -0
- package/src/documentation/generated/CmdUploadFormPropertyDescriptions.json +90 -0
- package/src/documentation/generated/CmdWidthLimitationWrapperPropertyDescriptions.json +41 -0
- package/src/documentation/generated/frameworkIcons.json +730 -0
- package/src/documentation/generated/logosIcons.json +110 -0
- package/src/documentation/tabs.js +46 -0
- package/src/documentation/views/ContainerPage.vue +237 -0
- package/src/documentation/views/HelpHome.vue +13 -0
- package/src/documentation/views/IconFont.vue +80 -0
- package/src/documentation/views/components/CmdAccordionHelp.vue +78 -0
- package/src/documentation/views/components/CmdAddressDataHelp.vue +65 -0
- package/src/documentation/views/components/CmdBackToTopButtonHelp.vue +62 -0
- package/src/documentation/views/components/CmdBankAccountDataHelp.vue +88 -0
- package/src/documentation/views/components/CmdBoxHelp.vue +137 -0
- package/src/documentation/views/components/CmdBoxSiteSearchHelp.vue +60 -0
- package/src/documentation/views/components/CmdBoxWrapperHelp.vue +111 -0
- package/src/documentation/views/components/CmdBreadcrumbsHelp.vue +51 -0
- package/src/documentation/views/components/CmdCompanyLogoHelp.vue +48 -0
- package/src/documentation/views/components/CmdCookieDisclaimerHelp.vue +105 -0
- package/src/documentation/views/components/CmdCustomHeadlineHelp.vue +53 -0
- package/src/documentation/views/components/CmdFakeSelectHelp.vue +175 -0
- package/src/documentation/views/components/CmdFancyBoxHelp.vue +79 -0
- package/src/documentation/views/components/CmdFormElementHelp.vue +412 -0
- package/src/documentation/views/components/CmdFormFiltersHelp.vue +69 -0
- package/src/documentation/views/components/CmdFormHelp.vue +41 -0
- package/src/documentation/views/components/CmdGoogleMapsHelp.vue +55 -0
- package/src/documentation/views/components/CmdImageGalleryHelp.vue +46 -0
- package/src/documentation/views/components/CmdImageZoomHelp.vue +34 -0
- package/src/documentation/views/components/CmdListOfLinksHelp.vue +64 -0
- package/src/documentation/views/components/CmdLoginFormHelp.vue +117 -0
- package/src/documentation/views/components/CmdMainNavigationHelp.vue +94 -0
- package/src/documentation/views/components/CmdMultistepFormProgressBarHelp.vue +49 -0
- package/src/documentation/views/components/CmdOpeningHoursHelp.vue +49 -0
- package/src/documentation/views/components/CmdPagerHelp.vue +57 -0
- package/src/documentation/views/components/CmdProgressBarHelp.vue +47 -0
- package/src/documentation/views/components/CmdShareButtonsHelp.vue +65 -0
- package/src/documentation/views/components/CmdSiteHeaderHelp.vue +72 -0
- package/src/documentation/views/components/CmdSlideButtonHelp.vue +90 -0
- package/src/documentation/views/components/CmdSlideshowHelp.vue +60 -0
- package/src/documentation/views/components/CmdSwitchLanguageHelp.vue +64 -0
- package/src/documentation/views/components/CmdSystemMessageHelp.vue +86 -0
- package/src/documentation/views/components/CmdTableHelp.vue +84 -0
- package/src/documentation/views/components/CmdTabsHelp.vue +52 -0
- package/src/documentation/views/components/CmdThumbnailScrollerHelp.vue +50 -0
- package/src/documentation/views/components/CmdTooltipHelp.vue +59 -0
- package/src/documentation/views/components/CmdUploadFormHelp.vue +59 -0
- package/src/documentation/views/components/CmdWidthLimitationWrapperHelp.vue +46 -0
- package/src/index.js +6 -3
- package/src/main.js +25 -15
- package/src/mixins/CmdAddressData/DefaultMessageProperties.js +17 -0
- package/src/mixins/CmdBox/DefaultMessageProperties.js +10 -0
- package/src/mixins/CmdFakeSelect/DefaultMessageProperties.js +9 -0
- package/src/mixins/CmdFormElement/DefaultMessageProperties.js +9 -0
- package/src/mixins/CmdImageGallery/DefaultMessageProperties.js +9 -0
- package/src/mixins/CmdSiteSearch/DefaultMessageProperties.js +14 -0
- package/src/mixins/CmdUploadForm/DefaultMessageProperties.js +53 -0
- package/src/mixins/FieldValidation.js +220 -0
- package/src/mixins/GlobalDefaultMessageProperties.js +15 -0
- package/src/mixins/I18n.js +56 -0
- package/src/mixins/Tooltip.js +26 -0
- package/src/router/index.js +67 -0
- package/src/utilities.js +3 -6
- package/src/utils/GetFileExtension.js +15 -0
- package/src/utils/common.js +6 -0
- package/src/utils/dom.js +8 -0
- package/src/utils/globalSequence.js +13 -0
- package/src/utils/string.js +8 -0
- package/src/assets/data/address.json +0 -13
- package/src/assets/data/footer-navigation.json +0 -38
- package/src/assets/data/languages.json +0 -31
- package/src/assets/data/multisteps.json +0 -27
- package/src/assets/data/navigation.json +0 -47
- package/src/assets/data/pager.json +0 -11
- package/src/assets/data/top-header-navigation.json +0 -27
- package/src/components/CmdFooterNavigation.vue +0 -71
- package/src/components/CmdMainHeadline.vue +0 -75
- package/src/components/CmdTopHeaderNavigation.vue +0 -88
@@ -1,166 +1,533 @@
|
|
1
1
|
<template>
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
<
|
6
|
-
|
7
|
-
type="file"
|
8
|
-
multiple="multiple"
|
9
|
-
labelText="Choose file(s) with file-explorer:"
|
10
|
-
@change="filesSelected"
|
11
|
-
v-show="enableFileSelect"
|
2
|
+
<!-- begin advanced mode -->
|
3
|
+
<fieldset v-if="advancedMode" :class="['cmd-upload-form flex-container', { 'upload-initiated': uploadInitiated }]">
|
4
|
+
<!-- begin CmdCustomHeadline -->
|
5
|
+
<CmdCustomHeadline v-if="cmdCustomHeadline"
|
6
|
+
v-bind="cmdCustomHeadline"
|
12
7
|
/>
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
formatSize(uploadFile.file.size)
|
28
|
-
}}<template v-if="uploadFile.width && uploadFile.height">, {{
|
29
|
-
uploadFile.width
|
30
|
-
}} px x {{ uploadFile.height }} px</template>)
|
31
|
-
<span v-if="uploadFile.allowedType" class="icon-check allowed" title="File ready to upload!"></span>
|
32
|
-
<span v-else class="icon-cancel not-allowed"
|
33
|
-
title="File type not allowed (file will not be uploaded)!"></span>
|
34
|
-
</span>
|
35
|
-
</li>
|
36
|
-
</ul>
|
37
|
-
<CmdSystemMessage v-if="!listOfFiles.length" status="warning" :fullWidth="true"
|
38
|
-
message="No files selected for upload!">
|
39
|
-
</CmdSystemMessage>
|
40
|
-
<CmdSystemMessage v-else :status="messageStatusUploadSize()" :fullWidth="true">
|
41
|
-
<p>Current upload size is {{ formatSize(uploadSize) }} (of max. {{ formatSize(maxUploadSize) }}).</p>
|
42
|
-
</CmdSystemMessage>
|
43
|
-
<CmdSystemMessage v-if="uploadSize > maxUploadSize" status="error" :fullWidth="true"
|
44
|
-
message="Total file size to large!">
|
8
|
+
<!-- end CmdCustomHeadline -->
|
9
|
+
|
10
|
+
<!-- begin CmdSystemMessage -->
|
11
|
+
<CmdSystemMessage
|
12
|
+
v-if="systemMessageStatus && allSystemMessages.length"
|
13
|
+
:iconClose="{ show: false }"
|
14
|
+
:validationStatus="systemMessageStatus"
|
15
|
+
:systemMessage="allSystemMessages.length === 1 ? allSystemMessages[0] : getMessage('cmduploadform.system_message.the_following_errors_occurred')"
|
16
|
+
>
|
17
|
+
<ul v-if="allSystemMessages.length > 1">
|
18
|
+
<li v-for="(systemMessage, index) in allSystemMessages" :key="index">
|
19
|
+
{{ systemMessage }}
|
20
|
+
</li>
|
21
|
+
</ul>
|
45
22
|
</CmdSystemMessage>
|
23
|
+
<!-- end CmdSystemMessage -->
|
24
|
+
|
25
|
+
<div :class="['box drop-area', { 'allow-drop': allowDrop }]" v-on="dragAndDropHandler">
|
26
|
+
<template v-if="!listOfFiles.length">
|
27
|
+
<h4 v-if="allowMultipleFileUploads">
|
28
|
+
{{ getMessage("cmduploadform.no_files_to_upload") }}
|
29
|
+
</h4>
|
30
|
+
<h4 v-else>
|
31
|
+
{{ getMessage("cmduploadform.no_file_to_upload") }}
|
32
|
+
</h4>
|
33
|
+
</template>
|
34
|
+
|
35
|
+
<!-- begin total-upload information -->
|
36
|
+
<template v-else>
|
37
|
+
<template v-if="showTotalUpload && listOfFiles.length !== 1">
|
38
|
+
<h4>{{ getMessage("cmduploadform.headline.summary_of_all_files") }}</h4>
|
39
|
+
<ul v-if="showTotalUpload && listOfFiles.length !== 1" class="list-of-files">
|
40
|
+
<li class="flex-container no-flex">
|
41
|
+
<a
|
42
|
+
href="#"
|
43
|
+
:title="getMessage('cmduploadform.labeltext.remove_all_files_from_list')"
|
44
|
+
@click.prevent="cancelUpload"
|
45
|
+
>
|
46
|
+
<span :class="deleteIconClass"></span>
|
47
|
+
</a>
|
48
|
+
<span>
|
49
|
+
<strong>{{ listOfFiles.length }}
|
50
|
+
<template v-if="!allowMultipleFileUploads">
|
51
|
+
{{ getMessage("cmduploadform.labeltext.file_uploading") }}
|
52
|
+
</template>
|
53
|
+
<template v-else>
|
54
|
+
{{ getMessage("cmduploadform.labeltext.files_uploading") }}
|
55
|
+
</template>
|
56
|
+
<span
|
57
|
+
:class="[
|
58
|
+
'text-align-right',
|
59
|
+
{ error: maxTotalUploadSize > 0 && totalSize > maxTotalUploadSize }
|
60
|
+
]">({{ formatSize(totalSize) }})</span>
|
61
|
+
</strong>
|
62
|
+
</span>
|
63
|
+
<span class="progressbar" v-if="uploadInitiated">
|
64
|
+
<span>{{ getPercentage(totalUploadProgress) }}</span>
|
65
|
+
<progress
|
66
|
+
max="100"
|
67
|
+
:value="totalUploadProgress"
|
68
|
+
:title="totalBytesUploaded"
|
69
|
+
></progress>
|
70
|
+
</span>
|
71
|
+
</li>
|
72
|
+
</ul>
|
73
|
+
<hr/>
|
74
|
+
</template>
|
75
|
+
<!-- end total-upload information -->
|
76
|
+
|
77
|
+
<!-- begin list of selected files -->
|
78
|
+
<h4>{{ getMessage("cmduploadform.headline.list_of_selected_files") }}</h4>
|
79
|
+
<ul class="list-of-files">
|
80
|
+
<li
|
81
|
+
v-for="(uploadFile, index) in listOfFiles"
|
82
|
+
:key="index"
|
83
|
+
class="flex-container no-flex"
|
84
|
+
>
|
85
|
+
<a
|
86
|
+
href="#"
|
87
|
+
:title="getMessage('cmduploadform.labeltext.remove_file_from_list')"
|
88
|
+
@click.prevent="removeFile(index)"
|
89
|
+
><span :class="deleteIconClass"></span>
|
90
|
+
</a>
|
91
|
+
<span
|
92
|
+
:class="[
|
93
|
+
'text-align-right',
|
94
|
+
uploadFile.allowedType ? 'allowed' : 'not-allowed',
|
95
|
+
{ error: uploadFile.error }
|
96
|
+
]"
|
97
|
+
>
|
98
|
+
{{ uploadFile.file.name }} ({{ formatSize(uploadFile.file.size) }})
|
99
|
+
</span>
|
100
|
+
<template v-if="uploadInitiated && !uploadFile.error">
|
101
|
+
<span class="progressbar">
|
102
|
+
<span>{{ getPercentage(uploadFile.progress) }}</span>
|
103
|
+
<!-- do not place inside progress-tag (will not be displayed then) -->
|
104
|
+
<progress
|
105
|
+
max="100"
|
106
|
+
:value="uploadFile.progress"
|
107
|
+
:title="
|
108
|
+
formatSize(uploadFile.uploadedBytes) + '/' + formatSize(uploadFile.file.size)
|
109
|
+
"
|
110
|
+
></progress>
|
111
|
+
</span>
|
112
|
+
</template>
|
113
|
+
</li>
|
114
|
+
</ul>
|
115
|
+
<a
|
116
|
+
v-if="failedUpload"
|
117
|
+
href="#"
|
118
|
+
@click.prevent="cancel"
|
119
|
+
:title="getMessage('cmduploadform.all_files_will_be_removed')">
|
120
|
+
{{ getMessage("cmduploadform.reset_upload") }}
|
121
|
+
</a>
|
122
|
+
<hr/>
|
123
|
+
</template>
|
124
|
+
<!-- end list of selected files -->
|
125
|
+
|
126
|
+
<!-- begin upload conditions -->
|
127
|
+
<h4 v-if="allowMultipleFileUploads && listOfFiles.length">
|
128
|
+
{{ getMessage("cmduploadform.headline.select_additional_files") }}
|
129
|
+
</h4>
|
130
|
+
<h4 v-if="!allowMultipleFileUploads && listOfFiles.length">
|
131
|
+
{{ getMessage("cmduploadform.headline.select_new_file") }}
|
132
|
+
</h4>
|
133
|
+
<dl class="small">
|
134
|
+
<template v-if="maxTotalUploadSize > 0">
|
135
|
+
<dt :class="{ error: totalSize > maxTotalUploadSize }">
|
136
|
+
{{ getMessage("cmduploadform.max_total_upload_size") }}
|
137
|
+
</dt>
|
138
|
+
<dd :class="['text-align-right', { error: totalSize > maxTotalUploadSize }]">
|
139
|
+
{{ formatSize(maxTotalUploadSize) }}
|
140
|
+
</dd>
|
141
|
+
</template>
|
142
|
+
<dt :class="{ error: errors.fileSize }">
|
143
|
+
{{ getMessage("cmduploadform.max_file_upload_size") }}
|
144
|
+
</dt>
|
145
|
+
<dd :class="['text-align-right', { error: errors.fileSize }]">
|
146
|
+
{{ formatSize(maxFileUploadSize) }}
|
147
|
+
</dd>
|
148
|
+
<dt :class="{ error: errors.fileType }">
|
149
|
+
{{ getMessage("cmduploadform.allowed_file_types") }}
|
150
|
+
</dt>
|
151
|
+
<dd>
|
152
|
+
<a
|
153
|
+
:class="showListOfFileExtensions ? 'icon-not-visible' : 'icon-visible'"
|
154
|
+
href="#"
|
155
|
+
@click.prevent="showListOfFileExtensions = !showListOfFileExtensions"
|
156
|
+
:title="getMessage('cmduploadform.tooltip.toggle_list_of_allowed_file_types')"
|
157
|
+
></a>
|
158
|
+
<transition name="fade">
|
159
|
+
<ul v-if="showListOfFileExtensions" class="list-of-file-extensions">
|
160
|
+
<li
|
161
|
+
v-for="(fileExtension, index) in allowedFileExtensions"
|
162
|
+
:key="index"
|
163
|
+
:class="{ error: errors.fileType }"
|
164
|
+
>
|
165
|
+
{{ fileExtension }}
|
166
|
+
</li>
|
167
|
+
</ul>
|
168
|
+
</transition>
|
169
|
+
</dd>
|
170
|
+
</dl>
|
171
|
+
<!-- end upload conditions -->
|
172
|
+
<button
|
173
|
+
type="button"
|
174
|
+
:class="['button upload primary', { disabled: uploadInitiated }]"
|
175
|
+
:disabled="uploadInitiated"
|
176
|
+
@click="selectFiles()"
|
177
|
+
>
|
178
|
+
<span class="icon-file-upload"></span>
|
179
|
+
<span v-if="allowMultipleFileUploads">{{
|
180
|
+
getMessage("cmduploadform.labeltext.select_files")
|
181
|
+
}}</span>
|
182
|
+
<span v-else>{{ getMessage("cmduploadform.labeltext.select_file") }}</span>
|
183
|
+
</button>
|
184
|
+
<p v-if="enableDragAndDrop" :class="['text-drag-and-drop', { disabled: uploadInitiated }]">
|
185
|
+
<span>{{ getMessage("cmduploadform.or") }}</span>
|
186
|
+
<strong>
|
187
|
+
{{ getMessage("cmduploadform.drag_and_drop") }}
|
188
|
+
<template v-if="allowMultipleFileUploads && listOfFiles.length">
|
189
|
+
{{ getMessage("cmduploadform.additional") }}
|
190
|
+
</template>
|
191
|
+
<template v-if="!allowMultipleFileUploads && listOfFiles.length">
|
192
|
+
{{ getMessage("cmduploadform.new") }}
|
193
|
+
</template>
|
194
|
+
{{ getMessage("cmduploadform.files_to_this_area") }}
|
195
|
+
</strong>
|
196
|
+
</p>
|
197
|
+
</div>
|
198
|
+
<!-- begin CmdFormElement -->
|
46
199
|
<CmdFormElement
|
47
200
|
v-if="enableComment"
|
48
201
|
element="textarea"
|
49
|
-
labelText="
|
50
|
-
|
51
|
-
|
202
|
+
:labelText="getMessage('cmduploadform.labeltext.comment')"
|
203
|
+
v-model="comment"
|
204
|
+
:required="commentRequired"
|
205
|
+
:statusMessage="commentStatusMessage"
|
206
|
+
:placeholder="getMessage('cmduploadform.placeholder.comment')"
|
207
|
+
:status="commentStatusMessage ? 'error' : ''"
|
52
208
|
/>
|
209
|
+
<!-- end CmdFormElement -->
|
210
|
+
|
53
211
|
<div class="button-wrapper no-flex">
|
54
|
-
<button
|
212
|
+
<button
|
213
|
+
:class="[
|
214
|
+
'button primary',
|
215
|
+
{
|
216
|
+
disabled:
|
217
|
+
listOfFiles.length === 0 ||
|
218
|
+
(maxTotalUploadSize > 0 && totalSize > maxTotalUploadSize) ||
|
219
|
+
uploadInitiated
|
220
|
+
}
|
221
|
+
]"
|
222
|
+
:disabled="
|
223
|
+
listOfFiles.length === 0 ||
|
224
|
+
(maxTotalUploadSize > 0 && totalSize > maxTotalUploadSize) ||
|
225
|
+
uploadInitiated
|
226
|
+
"
|
227
|
+
@click="uploadFiles"
|
228
|
+
>
|
55
229
|
<span class="icon-upload"></span>
|
56
|
-
<span v-if="
|
57
|
-
|
230
|
+
<span v-if="listOfFiles.length === 1 || !allowMultipleFileUploads">
|
231
|
+
{{ getMessage("cmduploadform.buttontext.upload_file") }}
|
232
|
+
</span>
|
233
|
+
<span v-else>{{ getMessage("cmduploadform.buttontext.upload_files") }}</span>
|
58
234
|
</button>
|
59
|
-
<button class="button" @click="
|
60
|
-
<span class="icon-cancel"></span
|
235
|
+
<button :class="['button', { disabled: listOfFiles.length === 0 }]" @click="cancel">
|
236
|
+
<span class="icon-cancel"></span>
|
237
|
+
<span>{{ getMessage("cmduploadform.buttontext.cancel") }}</span>
|
61
238
|
</button>
|
62
239
|
</div>
|
63
240
|
</fieldset>
|
241
|
+
<!-- end advanced mode -->
|
242
|
+
|
243
|
+
<!-- begin simple mode -->
|
244
|
+
<a v-else href="#" @click.prevent="selectFiles" :class="['cmd-upload-form drop-area', {'allow-drop': allowDrop }]" v-on="dragAndDropHandler">
|
245
|
+
<span class="progressbar" v-if="uploadInitiated">
|
246
|
+
<span>{{ getPercentage(totalUploadProgress) }}</span>
|
247
|
+
<progress
|
248
|
+
max="100"
|
249
|
+
:value="totalUploadProgress"
|
250
|
+
:title="totalBytesUploaded">
|
251
|
+
</progress>
|
252
|
+
</span>
|
253
|
+
|
254
|
+
<!-- begin slot-content -->
|
255
|
+
<slot>
|
256
|
+
<template v-if="enableDragAndDrop">
|
257
|
+
<template v-if="fileTypeImage">
|
258
|
+
<span>{{ getMessage("cmduploadform.select_image") }}</span>
|
259
|
+
<span class="icon-image"></span>
|
260
|
+
</template>
|
261
|
+
<template v-else>
|
262
|
+
<span>{{ getMessage("cmduploadform.select_file") }}</span>
|
263
|
+
<span class="icon-file"></span>
|
264
|
+
</template>
|
265
|
+
</template>
|
266
|
+
<template v-else>
|
267
|
+
<span>{{ getMessage("cmduploadform.drag_and_drop_file_here") }}</span>
|
268
|
+
<span class="icon-drag-and-drop"></span>
|
269
|
+
</template>
|
270
|
+
<small>{{ getMessage("cmduploadform.max_upload_size") }} {{ formatSize(maxFileUploadSize) }}</small>
|
271
|
+
<small>{{ getMessage("cmduploadform.allowed_file_types") }} {{ allowedFileExtensions }}</small>
|
272
|
+
</slot>
|
273
|
+
<!-- end slot-content -->
|
274
|
+
</a>
|
275
|
+
<!-- end simple mode -->
|
276
|
+
|
277
|
+
<!-- begin CmdFormElement -->
|
278
|
+
<CmdFormElement
|
279
|
+
element="input"
|
280
|
+
type="file"
|
281
|
+
:labelText="getMessage('cmduploadform.labeltext.select_files')"
|
282
|
+
:disabled="uploadInitiated"
|
283
|
+
:multiple="allowMultipleFileUploads"
|
284
|
+
@change="filesSelected"
|
285
|
+
ref="formElement"
|
286
|
+
/>
|
287
|
+
<!-- end CmdFormElement -->
|
64
288
|
</template>
|
65
289
|
|
66
290
|
<script>
|
291
|
+
// import mixins
|
292
|
+
import I18n from "../mixins/I18n"
|
293
|
+
import DefaultMessageProperties from "../mixins/CmdUploadForm/DefaultMessageProperties"
|
294
|
+
|
295
|
+
import {getFileExtension} from "../utils/GetFileExtension.js"
|
296
|
+
import axios from "axios"
|
297
|
+
|
67
298
|
// import components
|
299
|
+
import CmdCustomHeadline from "./CmdCustomHeadline"
|
68
300
|
import CmdFormElement from "./CmdFormElement"
|
69
301
|
import CmdSystemMessage from "./CmdSystemMessage"
|
70
302
|
|
71
303
|
export default {
|
72
304
|
name: "CmdUploadForm",
|
73
|
-
emits: ["click"],
|
305
|
+
emits: ["click", "error", "upload-complete", "upload-file-success"],
|
306
|
+
mixins: [I18n, DefaultMessageProperties],
|
307
|
+
components: {
|
308
|
+
CmdCustomHeadline,
|
309
|
+
CmdFormElement,
|
310
|
+
CmdSystemMessage,
|
311
|
+
},
|
74
312
|
data() {
|
75
313
|
return {
|
76
314
|
comment: "",
|
77
315
|
allowDrop: false,
|
78
|
-
listOfFiles: []
|
316
|
+
listOfFiles: [],
|
317
|
+
systemMessages: [],
|
318
|
+
defaultSystemMessageStatus: "",
|
319
|
+
showListOfFileExtensions: false,
|
320
|
+
resetForm: {},
|
321
|
+
uploadInitiated: false,
|
322
|
+
errors: {}
|
79
323
|
}
|
80
324
|
},
|
81
|
-
|
82
|
-
|
83
|
-
|
325
|
+
created() {
|
326
|
+
// Set initial data for resetForm.
|
327
|
+
this.resetForm.comment = this.presetComment
|
328
|
+
this.resetForm.allowDrop = this.allowDrop
|
329
|
+
this.resetForm.listOfFiles = JSON.parse(JSON.stringify(this.listOfFiles))
|
330
|
+
this.resetForm.systemMessages = this.systemMessages
|
331
|
+
this.resetForm.systemMessageStatus = this.systemMessageStatus
|
84
332
|
},
|
85
333
|
props: {
|
86
334
|
/**
|
87
|
-
*
|
335
|
+
* set icon class for delete-icons
|
88
336
|
*/
|
89
|
-
|
337
|
+
deleteIconClass: {
|
90
338
|
type: String,
|
91
|
-
|
339
|
+
default: "icon-delete"
|
92
340
|
},
|
93
341
|
/**
|
94
|
-
*
|
342
|
+
* toggle visibility of total upload (number of files, total size, total progress
|
95
343
|
*/
|
96
|
-
|
97
|
-
type:
|
98
|
-
|
344
|
+
showTotalUpload: {
|
345
|
+
type: Boolean,
|
346
|
+
default: true
|
99
347
|
},
|
100
348
|
/**
|
101
|
-
*
|
349
|
+
* toggle if upload is handled by component itself or by outer component
|
102
350
|
*/
|
103
|
-
|
351
|
+
componentHandlesUpload: {
|
104
352
|
type: Boolean,
|
105
353
|
default: true
|
106
354
|
},
|
107
355
|
/**
|
108
|
-
*
|
356
|
+
* list of allowed file extensions to upload (all can be selected)
|
109
357
|
*/
|
110
|
-
|
358
|
+
allowedFileExtensions: {
|
359
|
+
type: Array,
|
360
|
+
required: true
|
361
|
+
},
|
362
|
+
/**
|
363
|
+
* activate if the comment given by the user should be mandatory
|
364
|
+
*
|
365
|
+
* enableComment-property must be set to true
|
366
|
+
*/
|
367
|
+
commentRequired: {
|
111
368
|
type: Boolean,
|
112
369
|
default: true
|
113
370
|
},
|
114
371
|
/**
|
115
|
-
*
|
372
|
+
* show a message if mandatory comment-textarea is not filled
|
373
|
+
*
|
374
|
+
* enableComment-property and commentRequired-property must be set to true
|
375
|
+
*/
|
376
|
+
commentStatusMessage: {
|
377
|
+
type: String,
|
378
|
+
default: ""
|
379
|
+
},
|
380
|
+
/**
|
381
|
+
* properties for CmdCustomHeadline-component
|
382
|
+
*/
|
383
|
+
cmdCustomHeadline: {
|
384
|
+
type: Object,
|
385
|
+
required: false
|
386
|
+
},
|
387
|
+
/**
|
388
|
+
* enable if files can also be dragged (and dropped) into upload-area
|
389
|
+
*/
|
390
|
+
enableDragAndDrop: {
|
391
|
+
type: Boolean,
|
392
|
+
default: false
|
393
|
+
},
|
394
|
+
/**
|
395
|
+
* enable if a comment should be possible to left by the user
|
116
396
|
*/
|
117
397
|
enableComment: {
|
118
398
|
type: Boolean,
|
119
399
|
default: true
|
120
400
|
},
|
121
401
|
/**
|
122
|
-
*
|
402
|
+
* preset the comment-textarea
|
403
|
+
*
|
404
|
+
* enableComment-property must be set to true
|
123
405
|
*/
|
124
|
-
|
125
|
-
type:
|
126
|
-
|
406
|
+
presetComment: {
|
407
|
+
type: String,
|
408
|
+
default: ""
|
127
409
|
},
|
128
410
|
/**
|
129
|
-
*
|
411
|
+
* set to 0 if no maximum for total upload size should be set
|
130
412
|
*/
|
131
|
-
|
132
|
-
type:
|
133
|
-
|
413
|
+
maxTotalUploadSize: {
|
414
|
+
type: Number,
|
415
|
+
default: 5242880
|
134
416
|
},
|
135
417
|
/**
|
136
|
-
*
|
418
|
+
* max file size (in bytes) for each single file
|
137
419
|
*/
|
138
|
-
|
420
|
+
maxFileUploadSize: {
|
139
421
|
type: Number,
|
140
422
|
default: 10485760
|
423
|
+
},
|
424
|
+
/**
|
425
|
+
* enable if more than file should be enabled to be selected for upload
|
426
|
+
*/
|
427
|
+
allowMultipleFileUploads: {
|
428
|
+
type: Boolean,
|
429
|
+
default: false
|
430
|
+
},
|
431
|
+
/**
|
432
|
+
* defines upload options if component handles upload itself
|
433
|
+
*
|
434
|
+
* componentHandlesUpload-property must be true
|
435
|
+
*/
|
436
|
+
uploadOptions: {
|
437
|
+
type: Object,
|
438
|
+
required: false
|
439
|
+
},
|
440
|
+
/**
|
441
|
+
* activate to use full upload-form-style and -functionality
|
442
|
+
*
|
443
|
+
* @affectsStyling: true
|
444
|
+
*/
|
445
|
+
advancedMode: {
|
446
|
+
type: Boolean,
|
447
|
+
default: true
|
141
448
|
}
|
142
449
|
},
|
143
450
|
computed: {
|
144
|
-
|
145
|
-
|
451
|
+
fileTypeImage() {
|
452
|
+
return this.allowedFileExtensions.some(extension => extension.includes('jpg'));
|
453
|
+
|
454
|
+
},
|
455
|
+
failedUpload() {
|
456
|
+
return this.listOfFiles.some(file => file.error)
|
457
|
+
},
|
458
|
+
totalBytesUploaded() {
|
459
|
+
const bytes = this.listOfFiles
|
460
|
+
.map(uploadFile => [
|
461
|
+
uploadFile.file.size,
|
462
|
+
((uploadFile.progress || 0) * uploadFile.file.size) / 100
|
463
|
+
])
|
464
|
+
.reduce((a, b) => [a[0] + b[0], a[1] + b[1]])
|
465
|
+
return this.formatSize(bytes[1]) + "/" + this.formatSize(bytes[0])
|
466
|
+
},
|
467
|
+
totalSize() {
|
468
|
+
let totalSize = 0
|
146
469
|
for (let i = 0; i < this.listOfFiles.length; i++) {
|
147
|
-
|
148
|
-
uploadSize = uploadSize + this.listOfFiles[i].file.size
|
149
|
-
}
|
470
|
+
totalSize = totalSize + this.listOfFiles[i].file.size
|
150
471
|
}
|
151
|
-
return
|
472
|
+
return totalSize
|
152
473
|
},
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
474
|
+
allSystemMessages() {
|
475
|
+
if (this.maxTotalUploadSize > 0 && this.totalSize > this.maxTotalUploadSize) {
|
476
|
+
return [
|
477
|
+
this.getMessage("cmduploadform.system_message_total_size_of_files_too_large"),
|
478
|
+
...this.systemMessages
|
479
|
+
]
|
480
|
+
}
|
481
|
+
return this.systemMessages
|
482
|
+
},
|
483
|
+
systemMessageStatus() {
|
484
|
+
return this.defaultSystemMessageStatus || (this.allSystemMessages.length ? "error" : "")
|
485
|
+
},
|
486
|
+
dragAndDropHandler() {
|
487
|
+
// register handlers only if drag-and-drop is enabled
|
488
|
+
if (this.enableDragAndDrop) {
|
489
|
+
return {
|
490
|
+
dragenter: this.dragEnter,
|
491
|
+
dragover: this.dragOver,
|
492
|
+
dragleave: this.dragLeave,
|
493
|
+
drop: this.drop
|
158
494
|
}
|
159
495
|
}
|
160
|
-
return
|
496
|
+
return {}
|
497
|
+
},
|
498
|
+
totalUploadProgress() {
|
499
|
+
const progress = this.listOfFiles
|
500
|
+
.map(uploadFile => [
|
501
|
+
uploadFile.file.size,
|
502
|
+
((uploadFile.progress || 0) * uploadFile.file.size) / 100
|
503
|
+
])
|
504
|
+
.reduce((a, b) => [a[0] + b[0], a[1] + b[1]])
|
505
|
+
return (progress[1] / progress[0]) * 100
|
506
|
+
}
|
507
|
+
},
|
508
|
+
watch: {
|
509
|
+
presetComment: {
|
510
|
+
handler(newValue) {
|
511
|
+
this.comment = newValue
|
512
|
+
},
|
513
|
+
immediate: true
|
161
514
|
}
|
162
515
|
},
|
163
516
|
methods: {
|
517
|
+
getPercentage(percentage) {
|
518
|
+
if (percentage) {
|
519
|
+
return percentage.toFixed(2) + "%"
|
520
|
+
}
|
521
|
+
return "0.00%"
|
522
|
+
},
|
523
|
+
// use imported function as method (to use in template)
|
524
|
+
getFileExtension(filename) {
|
525
|
+
return getFileExtension(filename)
|
526
|
+
},
|
527
|
+
selectFiles() {
|
528
|
+
let inputFile = this.$refs.formElement.getDomElement().querySelector("input[type='file']")
|
529
|
+
inputFile.click()
|
530
|
+
},
|
164
531
|
dragEnter(event) {
|
165
532
|
this.dragOver(event)
|
166
533
|
},
|
@@ -187,11 +554,11 @@ export default {
|
|
187
554
|
this.allowDrop = false
|
188
555
|
},
|
189
556
|
/*
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
557
|
+
drag(event) {
|
558
|
+
alert("dropped")
|
559
|
+
event.dataTransfer.setData("text", event.target.id)
|
560
|
+
},
|
561
|
+
*/
|
195
562
|
drop(event) {
|
196
563
|
this.allowDrop = false
|
197
564
|
if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length > 0) {
|
@@ -200,144 +567,431 @@ export default {
|
|
200
567
|
}
|
201
568
|
},
|
202
569
|
cancelUpload() {
|
570
|
+
// cancel upload for each file
|
571
|
+
this.listOfFiles.forEach(file => {
|
572
|
+
if (file.abortController) {
|
573
|
+
file.abortController.abort()
|
574
|
+
}
|
575
|
+
})
|
576
|
+
|
577
|
+
// clear list of files, remove error-highlighting and hide all system-messages afterwards
|
578
|
+
this.errors = {}
|
203
579
|
this.listOfFiles = []
|
204
|
-
this.
|
205
|
-
|
580
|
+
this.hideAllSystemMessages()
|
581
|
+
|
582
|
+
// set uploadInitiated to false to enable all disabled buttons
|
583
|
+
this.uploadInitiated = false
|
584
|
+
},
|
585
|
+
cancel() {
|
586
|
+
this.cancelUpload()
|
587
|
+
|
588
|
+
// emit click event with argument "cancel" to react in outer component
|
589
|
+
this.$emit("click", "cancel")
|
206
590
|
},
|
207
591
|
filesSelected(event) {
|
208
592
|
this.checkFiles(event.target.files)
|
209
593
|
},
|
210
594
|
checkFiles(files) {
|
595
|
+
if (!files.length) {
|
596
|
+
return
|
597
|
+
}
|
598
|
+
|
599
|
+
this.defaultSystemMessageStatus = ""; // hide systemMessage if already is shown
|
600
|
+
this.systemMessages = [] // hide systemMessage if already is shown
|
601
|
+
this.errors = {}
|
602
|
+
|
211
603
|
for (let i = 0; i < files.length; i++) {
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
604
|
+
// define file-object which will be pushed in listOfFiles
|
605
|
+
const uploadFile = {
|
606
|
+
file: files[i],
|
607
|
+
progress: null,
|
608
|
+
uploadedBytes: 0
|
217
609
|
}
|
218
610
|
|
219
|
-
|
220
|
-
|
611
|
+
// check size for current file
|
612
|
+
if (files[i].size > this.maxFileUploadSize) {
|
613
|
+
this.errors.fileSize = true
|
614
|
+
this.systemMessages.push(
|
615
|
+
this.getMessage(
|
616
|
+
"cmduploadform.system_message.file_size_too_large",
|
617
|
+
files[i].name,
|
618
|
+
files[i].size
|
619
|
+
)
|
620
|
+
)
|
621
|
+
continue
|
221
622
|
}
|
222
623
|
|
223
|
-
if
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
624
|
+
// check if current file has allowed file-type (else continue with next file)
|
625
|
+
if (!this.allowedFileExtensions.includes(getFileExtension(files[i].name))) {
|
626
|
+
this.showListOfFileExtensions = true
|
627
|
+
this.errors.fileType = true
|
628
|
+
this.systemMessages.push(
|
629
|
+
this.getMessage(
|
630
|
+
"cmduploadform.system_message.not_allowed_file_type",
|
631
|
+
files[i].name,
|
632
|
+
getFileExtension(files[i].name)
|
633
|
+
)
|
634
|
+
)
|
635
|
+
continue
|
636
|
+
}
|
637
|
+
|
638
|
+
// check (if multiple files can be selected) if current file already exists in listOfFiles
|
639
|
+
if (
|
640
|
+
this.allowMultipleFileUploads &&
|
641
|
+
this.listOfFiles.some(listOfFilesEntry =>
|
642
|
+
this.compareFiles(listOfFilesEntry.file, files[i])
|
643
|
+
)
|
644
|
+
) {
|
645
|
+
this.systemMessages.push(
|
646
|
+
this.getMessage(
|
647
|
+
"cmduploadform.system_message.duplicate_file",
|
648
|
+
files[i].name,
|
649
|
+
getFileExtension(files[i].name)
|
650
|
+
)
|
651
|
+
)
|
652
|
+
continue
|
653
|
+
}
|
654
|
+
|
655
|
+
if (this.allowMultipleFileUploads) {
|
656
|
+
// push file-object (for each valid file) to listOfFiles-array
|
657
|
+
this.listOfFiles.push(uploadFile)
|
658
|
+
} else {
|
659
|
+
if (files.length > 1) {
|
660
|
+
this.systemMessages.push(
|
661
|
+
this.getMessage("cmduploadform.system_message.only_one_file_allowed")
|
662
|
+
)
|
663
|
+
}
|
664
|
+
// assign uploadFile-object (which contains current (and valid) file to listOfFiles-array
|
665
|
+
this.listOfFiles = [uploadFile]
|
666
|
+
break
|
236
667
|
}
|
237
|
-
this.listOfFiles.push(uploadFile)
|
238
668
|
}
|
669
|
+
|
670
|
+
if (!this.advancedMode) {
|
671
|
+
if (this.systemMessages.length) {
|
672
|
+
this.$emit("error", {messages: this.systemMessages})
|
673
|
+
return
|
674
|
+
}
|
675
|
+
if (this.listOfFiles.length) {
|
676
|
+
this.uploadFiles()
|
677
|
+
}
|
678
|
+
}
|
679
|
+
},
|
680
|
+
compareFiles(file1, file2) {
|
681
|
+
return (
|
682
|
+
file1.name === file2.name &&
|
683
|
+
file1.lastModified === file2.lastModified &&
|
684
|
+
file1.size === file2.size
|
685
|
+
)
|
239
686
|
},
|
240
687
|
removeFile(index) {
|
241
|
-
/* remove file from list */
|
688
|
+
/* remove specific file from list */
|
242
689
|
this.listOfFiles.splice(index, 1)
|
690
|
+
if (!this.listOfFiles.length) {
|
691
|
+
this.uploadInitiated = false
|
692
|
+
}
|
693
|
+
this.hideAllSystemMessages()
|
694
|
+
},
|
695
|
+
hideAllSystemMessages() {
|
696
|
+
// hide all system-messages if all files are removed from list
|
697
|
+
if (!this.listOfFiles.length) {
|
698
|
+
this.systemMessages = []
|
699
|
+
}
|
243
700
|
},
|
244
701
|
formatSize(size) {
|
245
702
|
if (size < 1024) {
|
246
703
|
return size
|
247
704
|
} else if (size < 1048576) {
|
248
|
-
return size =
|
705
|
+
return (size = Math.round((size / 1024) * 100) / 100 + " KB")
|
249
706
|
} else {
|
250
|
-
return size =
|
707
|
+
return (size = Math.round((size / 1048576) * 100) / 100 + " MB")
|
251
708
|
}
|
252
709
|
},
|
253
710
|
uploadFiles() {
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
711
|
+
this.systemMessages = []
|
712
|
+
this.errors = {}
|
713
|
+
this.defaultSystemMessageStatus = ""
|
714
|
+
|
715
|
+
if (
|
716
|
+
this.enableComment &&
|
717
|
+
!this.comment &&
|
718
|
+
this.commentRequired &&
|
719
|
+
this.commentStatusMessage
|
720
|
+
) {
|
721
|
+
this.defaultSystemMessageStatus = "error"
|
722
|
+
this.systemMessages.push(this.getMessage("cmduploadform.system_message.fill_required"))
|
723
|
+
} else {
|
724
|
+
this.uploadInitiated = true
|
725
|
+
|
726
|
+
if (this.componentHandlesUpload && this.uploadOptions && this.uploadOptions.url) {
|
727
|
+
const url = new URL(this.uploadOptions.url, location.href)
|
728
|
+
const formData = new FormData()
|
729
|
+
|
730
|
+
// // append information about files to formData-object
|
731
|
+
// formData.append(
|
732
|
+
// this.uploadOptions.filesParam ? this.uploadOptions.filesParam : "files",
|
733
|
+
// this.listOfFiles.map(uploadFile => uploadFile.file)
|
734
|
+
// )
|
735
|
+
|
736
|
+
// iterate over additionalParams-object and append to formData-object
|
737
|
+
Object.entries(this.uploadOptions.additionalParams || {}).forEach(([key, value]) =>
|
738
|
+
formData.append(key, value)
|
739
|
+
)
|
740
|
+
|
741
|
+
// append comment to formData-object
|
742
|
+
if (this.enableComment) {
|
743
|
+
formData.append("comment", this.comment)
|
259
744
|
}
|
260
|
-
}
|
261
745
|
|
262
|
-
|
263
|
-
|
746
|
+
const requests = []
|
747
|
+
|
748
|
+
// iterate over list-of-files to send upload request for each file individually
|
749
|
+
this.listOfFiles.forEach(file => {
|
750
|
+
requests.push(this.uploadSingleFile(url, file, formData))
|
751
|
+
})
|
752
|
+
|
753
|
+
// check upload-status for each file individually
|
754
|
+
Promise.allSettled(requests).then(results => {
|
755
|
+
// if status equals "rejected" the upload was not successful and the file will not be deleted from list
|
756
|
+
const rejectedFiles = results.filter(result => result.status === "rejected")
|
757
|
+
this.uploadInitiated = false
|
758
|
+
|
759
|
+
if (rejectedFiles.length) {
|
760
|
+
this.defaultSystemMessageStatus = "error"
|
761
|
+
this.systemMessages.push(
|
762
|
+
this.getMessage(
|
763
|
+
"cmduploadform.system_message.some_files_are_not_uploaded_successfully"
|
764
|
+
)
|
765
|
+
)
|
766
|
+
} else {
|
767
|
+
this.defaultSystemMessageStatus = "success"
|
768
|
+
this.systemMessages.push(
|
769
|
+
this.getMessage("cmduploadform.system_message.all_files_are_uploaded_successfully")
|
770
|
+
)
|
771
|
+
}
|
772
|
+
|
773
|
+
this.$emit("upload-complete", {success: !rejectedFiles.length})
|
774
|
+
})
|
775
|
+
} else {
|
776
|
+
let uploadObj = {}
|
777
|
+
uploadObj.listOfFiles = this.listOfFiles
|
778
|
+
uploadObj.type = "upload"
|
779
|
+
uploadObj.comment = this.comment
|
780
|
+
|
781
|
+
// emit uploadObj to handle upload by outer component
|
782
|
+
this.$emit("click", uploadObj, this.showMessage)
|
264
783
|
}
|
784
|
+
}
|
785
|
+
},
|
786
|
+
onUploadProgress(event, uploadFile) {
|
787
|
+
if (event.lengthComputable) {
|
788
|
+
uploadFile.progress = (event.loaded / event.total) * 100
|
789
|
+
uploadFile.uploadedBytes = event.loaded
|
265
790
|
} else {
|
266
|
-
|
791
|
+
uploadFile.progress = null
|
792
|
+
uploadFile.uploadedBytes = 0
|
267
793
|
}
|
794
|
+
this.$forceUpdate()
|
268
795
|
},
|
269
|
-
|
270
|
-
|
271
|
-
|
796
|
+
uploadSingleFile(url, file, formData) {
|
797
|
+
file.abortController = new AbortController()
|
798
|
+
|
799
|
+
// append information about given file to formData-object
|
800
|
+
formData.set(
|
801
|
+
this.uploadOptions.filesParam ? this.uploadOptions.filesParam : "files",
|
802
|
+
file.file
|
803
|
+
)
|
804
|
+
|
805
|
+
return (
|
806
|
+
axios
|
807
|
+
.post(url, formData, {
|
808
|
+
signal: file.abortController.signal,
|
809
|
+
onUploadProgress: event => this.onUploadProgress(event, file)
|
810
|
+
})
|
811
|
+
// emit information about successful-upload + file
|
812
|
+
.then(response => {
|
813
|
+
this.$emit("upload-file-success", file)
|
814
|
+
return response
|
815
|
+
})
|
816
|
+
// delete uploaded file from list-of-files-array
|
817
|
+
.then(response => {
|
818
|
+
const positionOfFile = this.listOfFiles.indexOf(file)
|
819
|
+
if (positionOfFile !== -1) {
|
820
|
+
this.listOfFiles.splice(positionOfFile, 1)
|
821
|
+
}
|
822
|
+
return response
|
823
|
+
})
|
824
|
+
.catch(error => {
|
825
|
+
this.defaultSystemMessageStatus = "error"
|
826
|
+
this.systemMessages.push(error)
|
827
|
+
file.error = true
|
828
|
+
throw new Error()
|
829
|
+
})
|
830
|
+
)
|
831
|
+
},
|
832
|
+
showMessage(result) {
|
833
|
+
if (result === true) {
|
834
|
+
this.defaultSystemMessageStatus = "success"
|
835
|
+
this.systemMessages.push(this.getMessage("cmduploadform.system_message.upload_success"))
|
836
|
+
} else if (result === false) {
|
837
|
+
this.defaultSystemMessageStatus = "error"
|
838
|
+
this.systemMessages.push(this.getMessage("cmduploadform.system_message.upload_failed"))
|
272
839
|
}
|
273
|
-
return "success"
|
274
840
|
},
|
275
|
-
|
276
|
-
this
|
841
|
+
resetFields() {
|
842
|
+
if (typeof this.resetForm === "object") {
|
843
|
+
const resetArr = Object.keys(this.resetForm)
|
844
|
+
for (let key of resetArr) {
|
845
|
+
if (typeof this.resetForm[key] === "object") {
|
846
|
+
this[key] = JSON.parse(JSON.stringify(this.resetForm[key]))
|
847
|
+
} else {
|
848
|
+
this[key] = this.resetForm[key]
|
849
|
+
}
|
850
|
+
}
|
851
|
+
}
|
277
852
|
}
|
278
853
|
}
|
279
854
|
}
|
280
855
|
</script>
|
281
856
|
|
282
857
|
<style lang="scss">
|
283
|
-
/* begin cmd-upload-form
|
858
|
+
/* begin cmd-upload-form -------------------------------------------------------------------------------------------- */
|
284
859
|
.cmd-upload-form {
|
285
860
|
.box {
|
286
|
-
|
287
|
-
text-align: center;
|
288
|
-
background: rgba(255, 255, 255, .5);
|
289
|
-
border-style: dashed;
|
290
|
-
|
291
|
-
&.allow-drop {
|
292
|
-
border-style: solid;
|
293
|
-
background: rgba(255, 255, 255, 1);
|
294
|
-
}
|
295
|
-
}
|
861
|
+
background: var(--pure-white-reduced-opacity);
|
296
862
|
|
297
|
-
|
298
|
-
|
863
|
+
dl {
|
864
|
+
justify-content: center;
|
865
|
+
text-align: left;
|
299
866
|
|
300
|
-
|
301
|
-
|
302
|
-
margin-left: 0;
|
867
|
+
.list-of-file-extensions {
|
868
|
+
display: table;
|
303
869
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
align-items: center;
|
308
|
-
justify-content: center;
|
309
|
-
padding: calc(var(--default-padding) / 2);
|
870
|
+
> li:only-child {
|
871
|
+
list-style-type: none;
|
872
|
+
margin: 0;
|
310
873
|
}
|
874
|
+
}
|
875
|
+
}
|
876
|
+
}
|
311
877
|
|
312
|
-
|
313
|
-
|
878
|
+
[class*="list-of-file"] {
|
879
|
+
max-height: 10rem;
|
880
|
+
overflow-x: hidden;
|
881
|
+
overflow-y: auto;
|
882
|
+
border: var(--default-border);
|
883
|
+
padding: calc(var(--default-padding) / 2);
|
884
|
+
margin: 0;
|
314
885
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
886
|
+
> li {
|
887
|
+
flex-wrap: nowrap;
|
888
|
+
margin-right: var(--default-margin); /* avoids text to be placed below scrollbar */
|
889
|
+
|
890
|
+
.progressbar {
|
891
|
+
display: table;
|
892
|
+
align-self: center;
|
320
893
|
|
321
|
-
|
322
|
-
|
894
|
+
progress {
|
895
|
+
&[value] {
|
896
|
+
background: var(--pure-white);
|
323
897
|
|
324
|
-
|
325
|
-
|
326
|
-
|
898
|
+
&::-moz-progress-bar {
|
899
|
+
border-top-left-radius: var(--border-radius);
|
900
|
+
border-bottom-left-radius: var(--border-radius);
|
901
|
+
background: var(--primary-color);
|
902
|
+
}
|
327
903
|
}
|
328
904
|
}
|
329
905
|
|
330
|
-
span
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
906
|
+
& > span {
|
907
|
+
position: absolute;
|
908
|
+
left: 50%;
|
909
|
+
transform: translateX(-50%);
|
910
|
+
z-index: 1;
|
911
|
+
font-size: 1.2rem;
|
912
|
+
display: table;
|
913
|
+
top: 0.2rem;
|
914
|
+
padding: 0.1rem 0.2rem;
|
915
|
+
line-height: 100%;
|
916
|
+
background: var(--pure-white);
|
336
917
|
}
|
337
918
|
}
|
338
919
|
}
|
339
920
|
}
|
921
|
+
|
922
|
+
.list-of-files {
|
923
|
+
display: inline-flex;
|
924
|
+
flex-direction: column;
|
925
|
+
gap: calc(var(--default-gap) / 2);
|
926
|
+
|
927
|
+
&:last-of-type {
|
928
|
+
margin-bottom: var(--default-margin);
|
929
|
+
}
|
930
|
+
|
931
|
+
li {
|
932
|
+
list-style-type: none;
|
933
|
+
margin-left: 0;
|
934
|
+
gap: calc(var(--default-gap) / 2);
|
935
|
+
}
|
936
|
+
|
937
|
+
& + a {
|
938
|
+
display: table;
|
939
|
+
margin: 0 auto;
|
940
|
+
}
|
941
|
+
}
|
942
|
+
|
943
|
+
p {
|
944
|
+
&.text-drag-and-drop {
|
945
|
+
&.disabled {
|
946
|
+
background: none !important; /* overwrite default styling for .disabled */
|
947
|
+
}
|
948
|
+
}
|
949
|
+
}
|
950
|
+
|
951
|
+
.button.upload {
|
952
|
+
align-self: center;
|
953
|
+
|
954
|
+
& ~ p {
|
955
|
+
& > * {
|
956
|
+
display: block;
|
957
|
+
}
|
958
|
+
}
|
959
|
+
}
|
960
|
+
|
961
|
+
.error {
|
962
|
+
color: var(--error-color);
|
963
|
+
}
|
964
|
+
|
965
|
+
& + .cmd-form-element {
|
966
|
+
display: none;
|
967
|
+
}
|
340
968
|
}
|
341
969
|
|
342
|
-
|
970
|
+
.drop-area {
|
971
|
+
border: var(--default-border);
|
972
|
+
border-style: dashed;
|
973
|
+
background: var(--pure-white);
|
974
|
+
padding: (var(--default-padding));
|
975
|
+
text-align: center;
|
976
|
+
|
977
|
+
&.allow-drop {
|
978
|
+
border-style: solid;
|
979
|
+
}
|
980
|
+
|
981
|
+
> span[class*="icon"] {
|
982
|
+
font-size: 5rem;
|
983
|
+
}
|
984
|
+
}
|
985
|
+
|
986
|
+
a.drop-area {
|
987
|
+
display: inline-flex;
|
988
|
+
flex-direction: column;
|
989
|
+
text-decoration: none;
|
990
|
+
background: var(--default-background-color);
|
991
|
+
|
992
|
+
span {
|
993
|
+
margin: 0;
|
994
|
+
}
|
995
|
+
}
|
996
|
+
/* end cmd-upload-form ---------------------------------------------------------------------------------------------- */
|
343
997
|
</style>
|