Skip to content

Commit 957536d

Browse files
committed
[WIP] Align with design feedback
1 parent 3be1a8b commit 957536d

File tree

5 files changed

+223
-102
lines changed

5 files changed

+223
-102
lines changed

contentcuration/contentcuration/frontend/channelList/views/ChannelSet/StudioCollectionsTable.vue

Lines changed: 124 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,51 @@
11
<template>
22

3-
<KPageContainer class="page-container">
4-
<div
5-
:class="{ 'table-header-mobile': isMobile() }"
6-
:style="{
7-
marginTop: windowIsSmall ? '24px' : '32px',
8-
}"
9-
>
10-
<div class="header-top">
11-
<h1 class="page-title">{{ $tr('pageTitle') }}</h1>
12-
<KButton
13-
v-if="!loading"
14-
appearance="raised-button"
15-
primary
16-
:text="$tr('addChannelSetTitle')"
17-
@click="newChannelSet"
18-
/>
19-
</div>
20-
21-
<div class="header-bottom">
22-
<KButton
23-
v-if="tableRows.length > 0"
24-
appearance="basic-link"
25-
:text="$tr('aboutChannelSetsLink')"
26-
@click="infoDialog = true"
27-
/>
28-
</div>
3+
<KPageContainer
4+
class="page-container"
5+
:class="{ 'larger-window': !windowIsSmall }"
6+
>
7+
<div class="header">
8+
<h1>{{ $tr('pageTitle') }}</h1>
9+
<KButton
10+
v-if="!loading"
11+
appearance="raised-button"
12+
primary
13+
class="new-collection-button"
14+
:text="$tr('addChannelSetTitle')"
15+
@click="newChannelSet"
16+
/>
2917
</div>
30-
18+
<KButton
19+
v-if="tableRows.length > 0"
20+
appearance="basic-link"
21+
:text="$tr('aboutChannelSetsLink')"
22+
@click="infoDialog = true"
23+
/>
24+
25+
<!-- Two wrapping divs needed to prevent brief loader shift after content displayed -->
3126
<div v-if="show('loader', loading, 500)">
32-
<KCircularLoader />
27+
<div class="loader">
28+
<KCircularLoader />
29+
</div>
3330
</div>
3431

35-
<div v-else-if="tableRows.length === 0">
36-
<p class="mb-0">
32+
<div
33+
v-else-if="tableRows.length === 0"
34+
class="no-channels"
35+
>
36+
<div>
3737
{{ $tr('noChannelSetsFound') }}
3838
<KButton
3939
appearance="basic-link"
4040
:text="$tr('aboutChannelSetsLink')"
4141
@click="infoDialog = true"
4242
/>
43-
</p>
43+
</div>
4444
</div>
4545

4646
<KTable
4747
v-else
48+
class="table"
4849
:stickyColumns="stickyColumns"
4950
:caption="$tr('tableCaption')"
5051
:headers="tableHeaders"
@@ -70,6 +71,9 @@
7071
<StudioCopyToken
7172
v-if="content"
7273
:token="content"
74+
:style="copyTokenStyle"
75+
:showLabel="false"
76+
:showCopyButton="showCopyTokenButton"
7377
/>
7478
<em
7579
v-else
@@ -90,7 +94,7 @@
9094
class="actions-cell"
9195
>
9296
<KButton
93-
v-if="!isSmallScreen()"
97+
v-if="windowBreakpoint > 2"
9498
:text="$tr('options')"
9599
appearance="flat-button"
96100
:hasDropdown="true"
@@ -156,8 +160,9 @@
156160
import { mapActions, mapGetters } from 'vuex';
157161
import useKShow from 'kolibri-design-system/lib/composables/useKShow';
158162
import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow';
163+
import useClipboard from '../../../shared/composables/useClipboard';
159164
import { RouteNames } from '../../constants';
160-
import StudioCopyToken from '../../../settings/pages/Account/StudioCopyToken';
165+
import StudioCopyToken from '../../../shared/views/StudioCopyToken';
161166
162167
export default {
163168
name: 'StudioCollectionsTable',
@@ -166,12 +171,14 @@
166171
},
167172
setup() {
168173
const { show } = useKShow();
169-
const { windowBreakpoint, windowIsSmall } = useKResponsiveWindow();
174+
const { windowIsSmall, windowBreakpoint } = useKResponsiveWindow();
175+
const { copyToClipboard } = useClipboard();
170176
171177
return {
172178
show,
173-
windowBreakpoint,
174179
windowIsSmall,
180+
windowBreakpoint,
181+
copyToClipboard,
175182
};
176183
},
177184
data() {
@@ -184,34 +191,44 @@
184191
},
185192
computed: {
186193
...mapGetters('channelSet', ['channelSets', 'getChannelSet']),
187-
194+
showCopyTokenButton() {
195+
return this.windowBreakpoint > 2;
196+
},
197+
tokenInputWidth() {
198+
return this.showCopyTokenButton ? '170px' : '130px';
199+
},
200+
copyTokenStyle() {
201+
return {
202+
position: 'relative',
203+
top: '-6px',
204+
minWidth: this.tokenInputWidth,
205+
};
206+
},
188207
tableHeaders() {
189208
return [
190209
{
191210
label: this.$tr('title'),
192211
dataType: 'string',
193212
minWidth: '200px',
194-
width: '55%',
213+
width: '40%',
195214
columnId: 'name',
196215
},
197216
{
198217
label: this.$tr('token'),
199218
dataType: 'string',
200-
minWidth: '200px',
201-
width: '20%',
219+
width: this.tokenInputWidth,
202220
columnId: 'tokens',
203221
},
204222
{
205223
label: this.$tr('channelNumber'),
206224
dataType: 'number',
207-
minWidth: '100px',
208-
width: '15%',
225+
minWidth: '200px',
226+
width: '20%',
209227
columnId: 'channel_count',
210228
},
211229
{
212230
label: '',
213231
dataType: 'undefined',
214-
width: '10%',
215232
columnId: 'actions',
216233
},
217234
];
@@ -240,7 +257,7 @@
240257
},
241258
242259
dropdownOptions() {
243-
return [
260+
const options = [
244261
{
245262
label: this.$tr('edit'),
246263
value: 'edit',
@@ -252,6 +269,14 @@
252269
icon: 'trash',
253270
},
254271
];
272+
if (!this.showCopyTokenButton) {
273+
options.unshift({
274+
label: this.$tr('copyToken'),
275+
value: 'copy-token',
276+
icon: 'copy',
277+
});
278+
}
279+
return options;
255280
},
256281
},
257282
mounted() {
@@ -261,15 +286,6 @@
261286
},
262287
methods: {
263288
...mapActions('channelSet', ['loadChannelSetList', 'deleteChannelSet']),
264-
265-
isMobile() {
266-
return this.windowBreakpoint <= 0;
267-
},
268-
269-
isSmallScreen() {
270-
return this.windowBreakpoint <= 2;
271-
},
272-
273289
handleOptionSelect(option, collectionId) {
274290
if (option.value === 'edit') {
275291
this.$router.push({
@@ -282,9 +298,24 @@
282298
this.channelSets.find(c => c.id === collectionId) ||
283299
null;
284300
if (this.collectionToDelete) this.deleteDialog = true;
301+
} else if (option.value === 'copy-token') {
302+
const collection =
303+
this.getChannelSet(collectionId) ||
304+
this.channelSets.find(c => c.id === collectionId) ||
305+
null;
306+
if (collection && collection.secret_token) {
307+
this.handleCopyToken(collection.secret_token);
308+
}
285309
}
286310
},
287311
312+
handleCopyToken(value) {
313+
this.copyToClipboard(value, {
314+
successMessage: this.$tr('copiedTokenId'),
315+
errorMessage: this.$tr('copyFailed'),
316+
});
317+
},
318+
288319
confirmDelete() {
289320
if (this.collectionToDelete) {
290321
this.deleteChannelSet(this.collectionToDelete)
@@ -335,6 +366,9 @@
335366
saving: 'Saving',
336367
collectionDeleted: 'Collection deleted',
337368
deleteError: 'Error deleting collection',
369+
copyToken: 'Copy token',
370+
copiedTokenId: 'Token copied',
371+
copyFailed: 'Copy failed',
338372
},
339373
};
340374
@@ -346,52 +380,62 @@
346380
.page-container {
347381
width: 100%;
348382
max-width: 1440px;
383+
min-height: 400px; // TOOD have a look at Kolibri's user table
349384
margin: 0 auto;
350385
}
351386
352-
.header-top {
387+
.header {
353388
display: flex;
389+
flex-direction: column-reverse;
390+
margin-top: 24px;
391+
392+
h1 {
393+
margin-top: 8px;
394+
}
395+
396+
.new-collection-button {
397+
align-self: flex-end;
398+
}
399+
}
400+
401+
.larger-window .header {
402+
flex-direction: row;
354403
align-items: center;
355404
justify-content: space-between;
356-
margin-bottom: 16px;
357-
}
358405
359-
.collection-name {
360-
display: inline-block;
361-
font-size: 16px;
362-
font-weight: 500;
363-
border-radius: 2px;
406+
h1 {
407+
margin-top: 0;
408+
}
364409
}
365410
366-
.header-bottom {
367-
display: flex;
368-
align-items: center;
369-
margin-bottom: 8px;
411+
.loader {
412+
margin-top: 64px;
370413
}
371414
372-
.page-title {
373-
margin: 0;
415+
.no-channels {
416+
margin-top: 24px;
374417
}
375418
376-
.actions-cell {
377-
display: flex;
378-
justify-content: flex-end;
419+
.larger-window .no-channels {
420+
max-width: 800px;
421+
margin: 64px auto 0;
422+
text-align: center;
379423
}
380424
381-
.table-header-mobile {
382-
.header-top {
383-
flex-direction: column;
384-
gap: 12px;
385-
text-align: center;
386-
}
425+
.table {
426+
margin-top: 32px;
427+
}
387428
388-
.header-bottom {
389-
justify-content: center;
390-
}
429+
.collection-name {
430+
display: inline-block;
431+
font-size: 16px;
432+
font-weight: 500;
433+
border-radius: 2px;
391434
}
392435
393-
.page-container .k-table-wrapper {
394-
overflow: hidden;
436+
.actions-cell {
437+
display: flex;
438+
justify-content: flex-end;
395439
}
396440
397441
</style>

contentcuration/contentcuration/frontend/settings/pages/Account/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,10 @@
155155
<script>
156156
157157
import { mapActions, mapState } from 'vuex';
158+
import StudioCopyToken from '../../../shared/views/StudioCopyToken';
158159
import FullNameForm from './FullNameForm';
159160
import ChangePasswordForm from './ChangePasswordForm';
160161
import DeleteAccountForm from './DeleteAccountForm';
161-
import StudioCopyToken from './StudioCopyToken.vue';
162162
163163
export default {
164164
name: 'Account',

0 commit comments

Comments
 (0)