Skip to content

Commit a33e1ea

Browse files
authored
fix: make upload dialog collapsible so it won't overlap certain views (#2688) (#2707)
1 parent 5131eed commit a33e1ea

5 files changed

Lines changed: 172 additions & 135 deletions

File tree

packages/web-pkg/src/components/Modals/FilePickerModal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export default defineComponent({
113113
@apply p-0;
114114
}
115115
.file-picker-modal .oc-modal-body-message {
116-
@apply m-0 h-[85vh];
116+
@apply m-0 h-[70vh];
117117
}
118118
}
119119
</style>

packages/web-pkg/src/components/Modals/LocationPickerModal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ const iframeSrc = iframeUrl.href
105105
@apply p-0;
106106
}
107107
.location-picker-modal .oc-modal-body-message {
108-
@apply m-0 h-[85vh];
108+
@apply m-0 h-[70vh];
109109
}
110110
}
111111
</style>

packages/web-pkg/src/components/Modals/SaveAsModal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ export default defineComponent({
201201
}
202202
203203
.oc-modal.save-as-modal .oc-modal-body-message {
204-
@apply m-0 h-[85vh];
204+
@apply m-0 h-[70vh];
205205
}
206206
}
207207
</style>

packages/web-runtime/src/components/UploadInfo.vue

Lines changed: 154 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -6,153 +6,169 @@
66
>
77
<div class="upload-info-title flex justify-between items-center px-4 py-2 rounded-t-xl">
88
<p v-oc-tooltip="uploadDetails" class="my-1 font-bold" v-text="uploadInfoTitle" />
9-
<oc-button
10-
v-if="!itemsInProgressCount"
11-
id="close-upload-info-btn"
12-
:aria-label="$gettext('Close')"
13-
appearance="raw"
14-
@click="closeInfo"
15-
>
16-
<oc-icon name="close" />
17-
</oc-button>
18-
</div>
19-
<div
20-
class="px-4 pt-4 flex justify-between items-center"
21-
:class="{
22-
'pb-4': !runningUploads
23-
}"
24-
>
25-
<div v-if="runningUploads" class="flex items-center">
26-
<oc-icon v-if="uploadsPaused" name="pause" size="small" class="mr-1" />
27-
<oc-spinner v-else size="small" class="mr-1" />
28-
<span class="text-sm text-role-on-surface-variant leading-7" v-text="remainingTime" />
29-
</div>
30-
<div
31-
v-else
32-
class="upload-info-label"
33-
:class="{
34-
'upload-info-danger text-role-error': Object.keys(errors).length && !uploadsCancelled,
35-
'upload-info-success': !Object.keys(errors).length && !uploadsCancelled
36-
}"
37-
>
38-
{{ uploadingLabel }}
39-
</div>
40-
<div class="flex">
41-
<oc-button
42-
appearance="raw"
43-
class="text-role-on-surface-variant text-sm upload-info-toggle-details-btn"
44-
no-hover
45-
@click="toggleInfo"
46-
>
47-
{{ infoExpanded ? $gettext('Hide details') : $gettext('Show details') }}
48-
</oc-button>
49-
<oc-button
50-
v-if="!runningUploads && Object.keys(errors).length && !disableActions"
51-
v-oc-tooltip="$gettext('Retry all failed uploads')"
52-
class="ml-1 p-1"
53-
appearance="raw"
54-
:aria-label="$gettext('Retry all failed uploads')"
55-
@click="retryUploads"
56-
>
57-
<oc-icon name="restart" fill-type="line" />
58-
</oc-button>
59-
9+
<div class="flex items-center">
6010
<oc-button
61-
v-if="
62-
runningUploads &&
63-
uploadsPausable &&
64-
!inPreparation &&
65-
!inFinalization &&
66-
!disableActions
11+
id="collapse-upload-info-btn"
12+
:aria-label="
13+
bodyCollapsed
14+
? $gettext('Expand upload info body')
15+
: $gettext('Collapse upload info body')
6716
"
68-
id="pause-upload-info-btn"
69-
v-oc-tooltip="uploadsPaused ? $gettext('Resume upload') : $gettext('Pause upload')"
70-
class="ml-1 p-1"
7117
appearance="raw"
72-
:aria-label="uploadsPaused ? $gettext('Resume upload') : $gettext('Pause upload')"
73-
@click="togglePauseUploads"
18+
@click="toggleBodyCollapsed"
7419
>
75-
<oc-icon :name="uploadsPaused ? 'play-circle' : 'pause-circle'" fill-type="line" />
20+
<oc-icon :name="bodyCollapsed ? 'arrow-up-s' : 'arrow-down-s'" fill-type="line" />
7621
</oc-button>
7722
<oc-button
78-
v-if="runningUploads && !inPreparation && !inFinalization && !disableActions"
79-
id="cancel-upload-info-btn"
80-
v-oc-tooltip="$gettext('Cancel upload')"
81-
class="ml-1 p-1"
23+
v-if="!itemsInProgressCount"
24+
id="close-upload-info-btn"
25+
:aria-label="$gettext('Close')"
8226
appearance="raw"
83-
:aria-label="$gettext('Cancel upload')"
84-
@click="cancelAllUploads"
27+
@click="closeInfo"
8528
>
86-
<oc-icon name="close-circle" fill-type="line" />
29+
<oc-icon name="close" />
8730
</oc-button>
8831
</div>
8932
</div>
90-
<div v-if="runningUploads" class="upload-info-progress mx-4 pb-4 mt-2 oc-text">
91-
<oc-progress
92-
:value="totalProgress"
93-
:max="100"
94-
size="small"
95-
:indeterminate="!itemsInProgressCount"
96-
/>
97-
</div>
98-
<div
99-
v-if="infoExpanded"
100-
class="upload-info-items px-4 pb-4 max-h-[50vh] overflow-y-auto"
101-
:class="{ 'max-h-[calc(50vh-100px)]': showErrorLog }"
102-
>
103-
<ul class="oc-list">
104-
<li v-for="(item, idx) in uploads" :key="idx">
105-
<span class="flex items-center">
106-
<oc-icon
107-
v-if="item.status === 'error'"
108-
name="close"
109-
size="small"
110-
color="var(--oc-role-error)"
111-
/>
112-
<oc-icon v-else-if="item.status === 'success'" name="check" size="small" />
113-
<oc-icon v-else-if="item.status === 'cancelled'" name="close" size="small" />
114-
<oc-icon v-else-if="uploadsPaused" name="pause" size="small" />
115-
<div v-else class="flex"><oc-spinner size="small" /></div>
116-
<resource-list-item
117-
v-if="displayFileAsResource(item)"
118-
:key="item.path"
119-
class="ml-2"
120-
:resource="item as Resource"
121-
:is-path-displayed="true"
122-
:is-resource-clickable="isResourceClickable(item)"
123-
:parent-folder-name="parentFolderName(item)"
124-
:link="resourceLink(item)"
125-
:parent-folder-link="parentFolderLink(item)"
126-
/>
127-
<span v-else class="flex items-center truncate">
128-
<resource-icon
129-
:resource="item as Resource"
130-
size="large"
131-
class="file_info__icon mx-2"
33+
<div v-if="!bodyCollapsed" class="upload-info-body">
34+
<div
35+
class="px-4 pt-4 flex justify-between items-center"
36+
:class="{
37+
'pb-4': !runningUploads
38+
}"
39+
>
40+
<div v-if="runningUploads" class="flex items-center">
41+
<oc-icon v-if="uploadsPaused" name="pause" size="small" class="mr-1" />
42+
<oc-spinner v-else size="small" class="mr-1" />
43+
<span class="text-sm text-role-on-surface-variant leading-7" v-text="remainingTime" />
44+
</div>
45+
<div
46+
v-else
47+
class="upload-info-label"
48+
:class="{
49+
'upload-info-danger text-role-error': Object.keys(errors).length && !uploadsCancelled,
50+
'upload-info-success': !Object.keys(errors).length && !uploadsCancelled
51+
}"
52+
>
53+
{{ uploadingLabel }}
54+
</div>
55+
<div class="flex">
56+
<oc-button
57+
appearance="raw"
58+
class="text-role-on-surface-variant text-sm upload-info-toggle-details-btn"
59+
no-hover
60+
@click="toggleInfo"
61+
>
62+
{{ infoExpanded ? $gettext('Hide details') : $gettext('Show details') }}
63+
</oc-button>
64+
<oc-button
65+
v-if="!runningUploads && Object.keys(errors).length && !disableActions"
66+
v-oc-tooltip="$gettext('Retry all failed uploads')"
67+
class="ml-1 p-1"
68+
appearance="raw"
69+
:aria-label="$gettext('Retry all failed uploads')"
70+
@click="retryUploads"
71+
>
72+
<oc-icon name="restart" fill-type="line" />
73+
</oc-button>
74+
75+
<oc-button
76+
v-if="
77+
runningUploads &&
78+
uploadsPausable &&
79+
!inPreparation &&
80+
!inFinalization &&
81+
!disableActions
82+
"
83+
id="pause-upload-info-btn"
84+
v-oc-tooltip="uploadsPaused ? $gettext('Resume upload') : $gettext('Pause upload')"
85+
class="ml-1 p-1"
86+
appearance="raw"
87+
:aria-label="uploadsPaused ? $gettext('Resume upload') : $gettext('Pause upload')"
88+
@click="togglePauseUploads"
89+
>
90+
<oc-icon :name="uploadsPaused ? 'play-circle' : 'pause-circle'" fill-type="line" />
91+
</oc-button>
92+
<oc-button
93+
v-if="runningUploads && !inPreparation && !inFinalization && !disableActions"
94+
id="cancel-upload-info-btn"
95+
v-oc-tooltip="$gettext('Cancel upload')"
96+
class="ml-1 p-1"
97+
appearance="raw"
98+
:aria-label="$gettext('Cancel upload')"
99+
@click="cancelAllUploads"
100+
>
101+
<oc-icon name="close-circle" fill-type="line" />
102+
</oc-button>
103+
</div>
104+
</div>
105+
<div v-if="runningUploads" class="upload-info-progress mx-4 pb-4 mt-2 oc-text">
106+
<oc-progress
107+
:value="totalProgress"
108+
:max="100"
109+
size="small"
110+
:indeterminate="!itemsInProgressCount"
111+
/>
112+
</div>
113+
<div
114+
v-if="infoExpanded"
115+
class="upload-info-items px-4 pb-4 max-h-[50vh] overflow-y-auto"
116+
:class="{ 'max-h-[calc(50vh-100px)]': showErrorLog }"
117+
>
118+
<ul class="oc-list">
119+
<li v-for="(item, idx) in uploads" :key="idx">
120+
<span class="flex items-center">
121+
<oc-icon
122+
v-if="item.status === 'error'"
123+
name="close"
124+
size="small"
125+
color="var(--oc-role-error)"
132126
/>
133-
<resource-name
134-
:name="item.name"
135-
:extension="item.extension"
136-
:type="item.type"
137-
full-path=""
138-
:is-path-displayed="false"
127+
<oc-icon v-else-if="item.status === 'success'" name="check" size="small" />
128+
<oc-icon v-else-if="item.status === 'cancelled'" name="close" size="small" />
129+
<oc-icon v-else-if="uploadsPaused" name="pause" size="small" />
130+
<div v-else class="flex"><oc-spinner size="small" /></div>
131+
<resource-list-item
132+
v-if="displayFileAsResource(item)"
133+
:key="item.path"
134+
class="ml-2"
135+
:resource="item as Resource"
136+
:is-path-displayed="true"
137+
:is-resource-clickable="isResourceClickable(item)"
138+
:parent-folder-name="parentFolderName(item)"
139+
:link="resourceLink(item)"
140+
:parent-folder-link="parentFolderLink(item)"
139141
/>
142+
<span v-else class="flex items-center truncate">
143+
<resource-icon
144+
:resource="item as Resource"
145+
size="large"
146+
class="file_info__icon mx-2"
147+
/>
148+
<resource-name
149+
:name="item.name"
150+
:extension="item.extension"
151+
:type="item.type"
152+
full-path=""
153+
:is-path-displayed="false"
154+
/>
155+
</span>
140156
</span>
141-
</span>
142-
<span
143-
v-if="getUploadItemMessage(item)"
144-
class="upload-info-message ml-1 text-sm"
145-
:class="getUploadItemClass(item)"
146-
v-text="getUploadItemMessage(item)"
147-
></span>
148-
</li>
149-
</ul>
157+
<span
158+
v-if="getUploadItemMessage(item)"
159+
class="upload-info-message ml-1 text-sm"
160+
:class="getUploadItemClass(item)"
161+
v-text="getUploadItemMessage(item)"
162+
></span>
163+
</li>
164+
</ul>
165+
</div>
166+
<oc-error-log
167+
v-if="showErrorLog"
168+
class="upload-info-error-log pt-4 pb-4 px-4"
169+
:content="uploadErrorLogContent"
170+
/>
150171
</div>
151-
<oc-error-log
152-
v-if="showErrorLog"
153-
class="upload-info-error-log pt-4 pb-4 px-4"
154-
:content="uploadErrorLogContent"
155-
/>
156172
</div>
157173
</template>
158174

@@ -190,6 +206,7 @@ export default defineComponent({
190206
const { options: configOptions } = storeToRefs(configStore)
191207
192208
const showInfo = ref(false) // show the overlay?
209+
const bodyCollapsed = ref(false)
193210
const infoExpanded = ref(false) // show the info including all uploads?
194211
const uploads = ref<Record<string, UploadResult>>({}) // uploads that are being displayed via "infoExpanded"
195212
const errors = ref<Record<string, HttpError>>({}) // all failed files
@@ -225,6 +242,7 @@ export default defineComponent({
225242
return {
226243
configOptions,
227244
showInfo,
245+
bodyCollapsed,
228246
infoExpanded,
229247
uploads,
230248
errors,
@@ -545,6 +563,7 @@ export default defineComponent({
545563
},
546564
closeInfo() {
547565
this.showInfo = false
566+
this.bodyCollapsed = false
548567
this.infoExpanded = false
549568
this.cleanOverlay()
550569
this.resetProgress()
@@ -647,6 +666,9 @@ export default defineComponent({
647666
toggleInfo() {
648667
this.infoExpanded = !this.infoExpanded
649668
},
669+
toggleBodyCollapsed() {
670+
this.bodyCollapsed = !this.bodyCollapsed
671+
},
650672
retryUploads() {
651673
this.itemsInProgressCount += Object.keys(this.errors).length
652674
this.runningUploads += 1

packages/web-runtime/tests/unit/components/UploadInfo.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { HttpError } from '@opencloud-eu/web-client'
77
const selectors = {
88
overlay: '#upload-info',
99
title: '.upload-info-title p',
10+
body: '.upload-info-body',
11+
collapseButton: '#collapse-upload-info-btn',
1012
progress: '.upload-info-progress',
1113
success: '.upload-info-success',
1214
error: '.upload-info-danger',
@@ -30,6 +32,19 @@ describe('UploadInfo component', () => {
3032
const overlay = wrapper.find(selectors.overlay)
3133
expect(overlay.exists()).toBeTruthy()
3234
})
35+
it('should keep title visible and hide body when collapsed', async () => {
36+
const { wrapper } = getShallowWrapper()
37+
wrapper.vm.showInfo = true
38+
await nextTick()
39+
40+
expect(wrapper.find(selectors.title).exists()).toBeTruthy()
41+
expect(wrapper.find(selectors.body).exists()).toBeTruthy()
42+
43+
await wrapper.find(selectors.collapseButton).trigger('click')
44+
45+
expect(wrapper.find(selectors.title).exists()).toBeTruthy()
46+
expect(wrapper.find(selectors.body).exists()).toBeFalsy()
47+
})
3348
describe('title', () => {
3449
it('should show that an upload is in progress', async () => {
3550
const { wrapper } = getShallowWrapper()

0 commit comments

Comments
 (0)