Skip to content

Commit d213706

Browse files
committed
Improve ux of camp share
1 parent 70546e6 commit d213706

File tree

11 files changed

+211
-79
lines changed

11 files changed

+211
-79
lines changed

frontend/src/components/camp/CampListItem.vue

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
<v-chip
77
v-if="camp.isShared === true"
88
x-small
9-
outlined
10-
color="primary"
11-
:to="adminRoute(camp)"
12-
class="align-self-center px-1"
9+
class="align-self-center px-1 v-btn--has-bg"
1310
>{{ $tc('components.camp.campListItem.public') }}</v-chip
1411
>
1512
<span class="flex-grow-1"></span>
@@ -24,7 +21,7 @@
2421
</template>
2522

2623
<script>
27-
import { campRoute, adminRoute } from '@/router.js'
24+
import { campRoute } from '@/router.js'
2825
export default {
2926
name: 'CampListItem',
3027
props: {
@@ -46,7 +43,7 @@ export default {
4643
.join(' | ')
4744
},
4845
},
49-
methods: { campRoute, adminRoute },
46+
methods: { campRoute },
5047
}
5148
</script>
5249

frontend/src/components/camp/FooterSharedCamp.vue

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
<template>
22
<v-footer v-if="isOutsider || showSharedWarning" app class="shared-camp">
3-
<p v-if="isOutsider" class="mb-0">
4-
<strong>{{ $tc('components.camp.footerSharedCamp.outsider') }}</strong>
5-
{{ $tc('components.camp.footerSharedCamp.outsiderDescription') }}
6-
</p>
7-
<p v-if="showSharedWarning" class="mb-0">
8-
<strong>{{ $tc('components.camp.footerSharedCamp.shared') }}</strong>
9-
{{ $tc('components.camp.footerSharedCamp.sharedDescription') }}
3+
<p class="mb-0">
4+
<v-icon left small class="currentColor--text">mdi-earth</v-icon>
5+
<strong>{{ $tc(`components.camp.footerSharedCamp.${key}`) }}</strong>
6+
{{ $tc(`components.camp.footerSharedCamp.${key}Description`) }}
107
</p>
118
</v-footer>
129
</template>
@@ -22,6 +19,9 @@ export default {
2219
camp() {
2320
return campFromRoute(this.$route)
2421
},
22+
key() {
23+
return this.isOutsider ? 'outsider' : this.showSharedWarning ? 'shared' : ''
24+
},
2525
showSharedWarning() {
2626
// The warning is intended for people with write access to the camp,
2727
// so that they know that the data they enter is publicly accessible.
@@ -41,4 +41,9 @@ export default {
4141
color: #7a4f0f;
4242
font-size: 80%;
4343
}
44+
45+
/* eslint-disable-next-line vue-scoped-css/no-unused-selector */
46+
.v-icon {
47+
margin-top: -2px;
48+
}
4449
</style>

frontend/src/components/campAdmin/CampSharingSettings.vue

Lines changed: 80 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,82 @@
11
<template>
22
<content-group
33
:title="$tc('components.campAdmin.campSharingSettings.title')"
4-
icon="mdi-share-variant"
4+
icon="mdi-earth"
55
>
66
<v-skeleton-loader v-if="camp._meta.loading" type="article" />
7-
<v-list class="py-0" color="transparent">
7+
<v-list class="py-0" color="transparent" two-line>
88
<v-list-item class="px-0">
99
<v-list-item-content>
1010
<v-list-item-title>
1111
{{ $tc(`components.campAdmin.campSharingSettings.${sharingStatus}.title`) }}
1212
</v-list-item-title>
13-
<i18n
14-
:path="`components.campAdmin.campSharingSettings.${sharingStatus}.description`"
15-
tag="div"
16-
class="body-2 grey--text text--darken-3"
17-
>
18-
<template #team>
19-
<span v-if="isOutsider">{{
20-
$tc('components.campAdmin.campSharingSettings.team')
21-
}}</span>
22-
<router-link v-else :to="teamRoute">{{
23-
$tc('components.campAdmin.campSharingSettings.team')
24-
}}</router-link>
25-
</template>
26-
</i18n>
27-
<v-list-item-subtitle v-if="camp.isShared" class="pb-1 whitespace-normal">{{
28-
$tc('components.campAdmin.campSharingSettings.sharedSince', 1, {
29-
sharedSince,
30-
sharedBy,
31-
})
32-
}}</v-list-item-subtitle>
13+
<v-list-item-subtitle v-if="camp.isShared" class="pb-1 whitespace-normal">
14+
{{
15+
$tc('components.campAdmin.campSharingSettings.sharedSince', 1, {
16+
sharedSince,
17+
sharedBy,
18+
})
19+
}}
20+
</v-list-item-subtitle>
3321
</v-list-item-content>
34-
<v-list-item-action v-if="camp.isShared" class="align-self-start">
35-
<v-tooltip top>
22+
<v-list-item-action>
23+
<DialogShare :title="$tc('components.campAdmin.campSharingSettings.title')">
3624
<template #activator="{ on, attrs }">
37-
<v-btn
38-
icon
25+
<ButtonEdit
26+
color="primary--text"
27+
text
28+
class="my-n1 v-btn--has-bg"
29+
icon="mdi-earth"
3930
v-bind="attrs"
40-
small
4131
v-on="on"
42-
@click="copyCampUrlToClipboard()"
32+
>{{
33+
camp.isShared ? $tc('global.button.edit') : $tc('global.button.share')
34+
}}</ButtonEdit
4335
>
44-
<v-icon>mdi-clipboard-check-multiple-outline</v-icon>
45-
</v-btn>
4636
</template>
47-
{{ $tc(`components.campAdmin.campSharingSettings.copyCampLink`) }}
48-
</v-tooltip>
49-
</v-list-item-action>
50-
<v-list-item-action v-if="isManager" class="align-self-start">
51-
<api-form :entity="camp">
52-
<api-switch
53-
path="isShared"
54-
icon="mdi-share-variant"
55-
:disabled="disabled"
56-
class="mt-1"
57-
/>
58-
</api-form>
37+
<p>
38+
<strong>{{
39+
$tc(`components.campAdmin.campSharingSettings.${sharingStatus}.title`)
40+
}}</strong
41+
>{{
42+
$tc(
43+
`components.campAdmin.campSharingSettings.${sharingStatus}.description`
44+
)
45+
}}
46+
</p>
47+
<p>
48+
<v-btn
49+
v-if="isManager"
50+
:color="camp.isShared ? '' : 'error'"
51+
elevation="0"
52+
text
53+
class="v-btn--has-bg"
54+
:loading="loading"
55+
@click="toggleShare"
56+
><v-icon left>mdi-alert</v-icon
57+
>{{
58+
camp.isShared
59+
? $tc('components.campAdmin.campSharingSettings.deactivate')
60+
: $tc('components.campAdmin.campSharingSettings.activate')
61+
}}</v-btn
62+
>
63+
</p>
64+
<p v-if="!camp.isShared">
65+
{{ $tc('components.campAdmin.campSharingSettings.implications') }}
66+
</p>
67+
<template v-if="camp.isShared" #more-actions>
68+
<div class="d-flex gap-2 align-center w-100">
69+
<small class="flex-shrink-1 flex-grow-1 w-0"
70+
><a :href="campUrl">{{ campUrl }}</a></small
71+
>
72+
73+
<v-btn text class="v-btn--has-bg" @click="copyCampUrlToClipboard()">
74+
<v-icon left>mdi-clipboard-check-multiple-outline</v-icon>
75+
{{ $tc('global.button.copy') }}
76+
</v-btn>
77+
</div>
78+
</template>
79+
</DialogShare>
5980
</v-list-item-action>
6081
</v-list-item>
6182
</v-list>
@@ -64,29 +85,29 @@
6485

6586
<script>
6687
import ContentGroup from '@/components/layout/ContentGroup.vue'
67-
import ApiForm from '../form/api/ApiForm.vue'
68-
import router, { adminRoute, campRoute } from '@/router.js'
88+
import router, { campRoute } from '@/router.js'
6989
import { campRoleMixin } from '@/mixins/campRoleMixin.js'
7090
import userDisplayName from '@/common/helpers/userDisplayName.js'
91+
import DialogShare from '@/components/campAdmin/DialogShare.vue'
92+
import ButtonEdit from '@/components/buttons/ButtonEdit.vue'
7193
7294
export default {
7395
name: 'CampSharingSettings',
74-
components: { ApiForm, ContentGroup },
96+
components: { ButtonEdit, DialogShare, ContentGroup },
7597
mixins: [campRoleMixin],
7698
props: {
7799
camp: { type: Object, required: true },
78100
disabled: { type: Boolean, default: false },
79101
},
80102
data() {
81-
return {}
103+
return {
104+
loading: false,
105+
}
82106
},
83107
computed: {
84108
sharingStatus() {
85109
return this.camp.isShared ? 'shared' : 'notShared'
86110
},
87-
teamRoute() {
88-
return adminRoute(this.camp, 'collaborators')
89-
},
90111
campUrl() {
91112
return window.location.origin + router.resolve(campRoute(this.camp)).href
92113
},
@@ -100,6 +121,16 @@ export default {
100121
},
101122
},
102123
methods: {
124+
toggleShare() {
125+
this.loading = true
126+
this.api
127+
.patch(this.camp._meta.self, {
128+
isShared: !this.camp.isShared,
129+
})
130+
.then(() => {
131+
this.loading = false
132+
})
133+
},
103134
async copyCampUrlToClipboard() {
104135
await navigator.clipboard.writeText(this.campUrl)
105136
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<template>
2+
<dialog-form
3+
v-model="showDialog"
4+
:loading="false"
5+
:error="error"
6+
icon="mdi-earth"
7+
:title="title"
8+
:submit-action="null"
9+
submit-color="success"
10+
:cancel-action="close"
11+
:cancel-label="$tc('global.button.close')"
12+
:cancel-visible="false"
13+
close-visible-on-mobile
14+
>
15+
<template #activator="scope">
16+
<slot name="activator" v-bind="scope" />
17+
</template>
18+
<slot />
19+
<template #moreActions>
20+
<slot name="more-actions" />
21+
</template>
22+
</dialog-form>
23+
</template>
24+
25+
<script>
26+
import DialogBase from '@/components/dialog/DialogBase.vue'
27+
import DialogForm from '@/components/dialog/DialogForm.vue'
28+
29+
export default {
30+
name: 'DialogShare',
31+
components: {
32+
DialogForm,
33+
},
34+
extends: DialogBase,
35+
props: {
36+
title: { type: String, required: true },
37+
},
38+
}
39+
</script>
40+
41+
<style scoped></style>

frontend/src/components/dialog/DialogForm.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
{{ title }}
2525
</v-toolbar-title>
2626
<v-btn
27-
v-if="$vuetify.breakpoint.smAndUp && cancelAction != null"
27+
v-if="
28+
(closeVisibleOnMobile || $vuetify.breakpoint.smAndUp) &&
29+
cancelAction != null
30+
"
2831
icon
2932
class="ml-auto"
3033
:title="$tc('global.button.cancel')"

frontend/src/components/dialog/DialogUiBase.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default {
2828
cancelColor: { type: String, default: 'secondary', required: false },
2929
cancelEnabled: { type: Boolean, default: true, required: false },
3030
cancelVisible: { type: Boolean, default: true, required: false },
31+
closeVisibleOnMobile: { type: Boolean, default: false, required: false },
3132
3233
savingOverride: { type: Boolean, default: false, required: false },
3334

frontend/src/locales/de.json

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"outsider": "Du arbeitest in diesem Lager nicht mit:",
6767
"outsiderDescription": "Du kannst keine Daten ändern, aber das Programm anschauen und kopieren.",
6868
"shared": "Lager ist öffentlich freigegeben:",
69-
"sharedDescription": "Alle Personen, die über den Link verfügen, können sämtliche Daten im Lager einsehen."
69+
"sharedDescription": "Fremde Personen können sämtliche Daten im Lager einsehen und kopieren."
7070
}
7171
},
7272
"campAdmin": {
@@ -126,18 +126,19 @@
126126
"title": "Beschreibung"
127127
},
128128
"campSharingSettings": {
129-
"copyCampLink": "Öffentlichen Link zum Lager kopieren",
129+
"activate": "Freigabe aktivieren",
130+
"deactivate": "Freigabe deaktivieren",
131+
"implications": "Wenn du die Freigabe aktivierst, dann können fremde Personen das Programm, das Team, die Materiallisten und Verantwortlichkeiten und alles andere in diesem Lager ansehen und kopieren. Nur Personen im Team können Daten ändern.",
130132
"notShared": {
131-
"description": "Link-Freigabe ist nicht aktiviert. Nur Personen im {team} können das Programm und die Daten in diesem Lager ansehen.",
132-
"title": "Lager öffentlich freigeben"
133+
"description": ": Nur Personen im Team können das Programm und die Daten in diesem Lager ansehen.",
134+
"title": "Freigabe ist nicht aktiviert"
133135
},
134136
"publicCampUrl": "Sharing-Link zum Lager",
135137
"shared": {
136-
"description": "Alle Personen, die den Link zum Lager kennen, können das Programm, das Team, die Materiallisten und Verantwortlichkeiten und alles andere in diesem Lager ansehen. Nur Personen im {team} können Daten ändern.",
138+
"description": ": Fremde Personen können das Programm, das Team, die Materiallisten und Verantwortlichkeiten und alles andere in diesem Lager ansehen und kopieren. Nur Personen im Team können Daten ändern.",
137139
"title": "Lager ist öffentlich freigegeben"
138140
},
139-
"sharedSince": "Zuletzt freigegeben am {sharedSince} von {sharedBy}",
140-
"team": "Team",
141+
"sharedSince": "Am {sharedSince} von {sharedBy}",
141142
"title": "Lager teilen"
142143
},
143144
"createCampPeriods": {
@@ -565,6 +566,7 @@
565566
"close": "Schliessen",
566567
"content": "Inhalt",
567568
"continue": "Weiter",
569+
"copy": "Kopieren",
568570
"create": "Erstellen",
569571
"delete": "Löschen",
570572
"discard": "Verwerfen",
@@ -584,6 +586,7 @@
584586
"save": "Speichern",
585587
"saving": "Speichert",
586588
"search": "Suchen",
589+
"share": "Freigeben",
587590
"submit": "Abschicken",
588591
"tryagain": "Erneut versuchen",
589592
"unlock": "Entsperren",

0 commit comments

Comments
 (0)