Skip to content

Commit a3b4779

Browse files
committed
Merge branch 'master' into app
2 parents 4ce8cf2 + e7dffd1 commit a3b4779

11 files changed

+682
-1
lines changed

api/GroupAPI.js

+4
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,8 @@ export default class GroupAPI extends BaseAPI {
1010
const { group } = await this.$get('/group', { id, polygon }, log)
1111
return group
1212
}
13+
14+
async patch(params) {
15+
await this.$patch('/group', params)
16+
}
1317
}

components/ModGroupSetting.vue

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<template>
2+
<b-form-group :label="label">
3+
<b-form-text class="mb-2">
4+
{{ description }}
5+
</b-form-text>
6+
<b-input-group v-if="type === 'input'">
7+
<b-input v-model="value" />
8+
<b-input-group-append>
9+
<SpinButton variant="white" name="save" label="Save" :handler="save" />
10+
</b-input-group-append>
11+
</b-input-group>
12+
<div v-else-if="type === 'textarea'">
13+
<b-row>
14+
<b-col>
15+
<b-textarea v-model="value" :rows="rows" />
16+
</b-col>
17+
</b-row>
18+
<b-row>
19+
<b-col>
20+
<SpinButton variant="white" name="save" label="Save" :handler="save" class="mt-2" />
21+
</b-col>
22+
</b-row>
23+
</div>
24+
</b-form-group>
25+
</template>
26+
<script>
27+
import SpinButton from './SpinButton'
28+
export default {
29+
components: { SpinButton },
30+
props: {
31+
name: {
32+
type: String,
33+
required: true
34+
},
35+
groupid: {
36+
type: Number,
37+
required: true
38+
},
39+
label: {
40+
type: String,
41+
required: true
42+
},
43+
description: {
44+
type: String,
45+
required: true
46+
},
47+
type: {
48+
type: String,
49+
required: false,
50+
default: 'input'
51+
},
52+
rows: {
53+
type: Number,
54+
required: false,
55+
default: 3
56+
}
57+
},
58+
data: function() {
59+
return {
60+
value: null
61+
}
62+
},
63+
computed: {
64+
group() {
65+
return this.$store.getters['group/get'](this.groupid)
66+
}
67+
},
68+
watch: {
69+
groupid(newval) {
70+
console.log('Group changed', newval)
71+
this.getValueFromGroup()
72+
}
73+
},
74+
mounted() {
75+
this.getValueFromGroup()
76+
},
77+
methods: {
78+
async save() {
79+
const data = {
80+
id: this.groupid
81+
}
82+
83+
data[this.name] = this.value
84+
85+
await this.$store.dispatch('group/update', data)
86+
},
87+
getValueFromGroup() {
88+
const group = this.$store.getters['group/get'](this.groupid)
89+
this.value = group[this.name]
90+
}
91+
}
92+
}
93+
</script>

components/ModSettingShortlink.vue

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<template>
2+
<div>
3+
<!-- eslint-disable-next-line -->
4+
<a :href="'https://freegle.in/' + shortlink.name">freegle.in/{{ shortlink.name }}</a>
5+
<span class="text-muted small">
6+
created {{ shortlink.created | timeago }}
7+
{{ shortlink.clicks | pluralize('click', { includeNumber: true }) }}
8+
</span>
9+
</div>
10+
</template>
11+
<script>
12+
export default {
13+
props: {
14+
shortlink: {
15+
type: Object,
16+
required: true
17+
}
18+
}
19+
}
20+
</script>

components/ModSettingsGroup.vue

+265
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
<template>
2+
<div>
3+
<div class="d-flex justify-content-between flex-wrap">
4+
<GroupSelect v-model="groupid" modonly />
5+
<b-btn variant="white">
6+
<v-icon name="plus" /> Add Group TODO
7+
</b-btn>
8+
</div>
9+
<div v-if="group" class="mt-2">
10+
<b-card no-body class="mb-2">
11+
<b-card-header>
12+
Community Addresses
13+
</b-card-header>
14+
<b-card-body>
15+
<p>Here's how your members can reach you by email:</p>
16+
<p>
17+
<a :href="'mailto:' + group.modsemail">{{ group.modsemail }}</a>
18+
</p>
19+
<p>Members can post by email. Please only use this for members who really need it:</p>
20+
<p>
21+
<a :href="'mailto:' + group.groupemail">{{ group.groupemail }}</a>
22+
</p>
23+
<p v-if="!Object.values(shortlinks).length">
24+
Your community has no shortlinks at the moment.
25+
</p>
26+
<div v-else class="mb-2">
27+
<p>Your community has the following shortlinks:</p>
28+
<ModSettingShortlink v-for="shortlink in shortlinks" :key="'shortlink-' + shortlink.id" :shortlink="shortlink" />
29+
</div>
30+
<p>
31+
You can add more shortlinks
32+
<!-- eslint-disable-next-line -->
33+
<a href="/shortlinks" target="_blank">here</a>.
34+
</p>
35+
</b-card-body>
36+
</b-card>
37+
<b-card no-body class="mb-2">
38+
<b-card-header>
39+
Your Settings
40+
</b-card-header>
41+
<b-card-body>
42+
<p>
43+
These settings affect how this community behaves for you. If you change them, it'll only affect you.
44+
</p>
45+
<b-form-group label="Are you actively moderating this community?">
46+
<b-form-text class="mb-2">
47+
We notify you about work to do for active communities.
48+
</b-form-text>
49+
<OurToggle
50+
v-model="active"
51+
class="mt-2"
52+
:height="30"
53+
:width="150"
54+
:font-size="14"
55+
:sync="true"
56+
:labels="{checked: 'Active', unchecked: 'Backup'}"
57+
color="#61AE24"
58+
/>
59+
</b-form-group>
60+
<b-form-group label="ModConfig to use for this community:">
61+
<b-form-text class="mb-2">
62+
The ModConfig you use controls behaviour such as which standard message buttons you can use.
63+
You can see ModConfig settings on the separate tab.
64+
</b-form-text>
65+
<b-select v-model="modconfig" :options="modConfigOptions" class="mb-2 font-weight-bold" />
66+
</b-form-group>
67+
</b-card-body>
68+
</b-card>
69+
70+
<b-card no-body class="mb-2">
71+
<b-card-header>
72+
Global Settings
73+
</b-card-header>
74+
<b-card-body>
75+
<p>
76+
These settings affect how this group behaves for all mods and members. If you change them,
77+
it'll affect other people.
78+
</p>
79+
<h4>
80+
Appearance
81+
</h4>
82+
<b-form-group label="Profile picture">
83+
<b-form-text class="mb-2">
84+
This is used in emails and on the site. It needs to look good small, like a Facebook profile picture.
85+
Avoid text - it's not readable. Aim for a simple image that people will recognise as relating to your
86+
location.
87+
</b-form-text>
88+
<GroupProfileImage
89+
:image="group.profile ? group.profile : '/placeholder.png'"
90+
:alt-text="'Profile picture for ' + group.namedisplay"
91+
/>
92+
<b-btn variant="primary" class="mt-2 d-block" @click="uploadProfile">
93+
<v-icon name="camera" /> Upload photo
94+
</b-btn>
95+
<OurFilePond
96+
v-if="uploadingProfile"
97+
imgtype="Group"
98+
imgflag="group"
99+
:groupid="groupid"
100+
@photoProcessed="profileUploaded"
101+
/>
102+
</b-form-group>
103+
<ModGroupSetting
104+
:groupid="groupid"
105+
name="tagline"
106+
label="Tagline"
107+
description="This should be short and snappy. Include some local reference that people in your area will feel connected to."
108+
/>
109+
<!-- TODO Worry words in group description-->
110+
<ModGroupSetting
111+
:groupid="groupid"
112+
name="welcomemail"
113+
label="Welcome email"
114+
description="This is emailed out to new members. Keep it short. Positive - use 'do' not 'don't'."
115+
type="textarea"
116+
:rows="10"
117+
/>
118+
</b-card-body>
119+
</b-card>
120+
TODO
121+
</div>
122+
</div>
123+
</template>
124+
<script>
125+
import GroupSelect from './GroupSelect'
126+
import ModSettingShortlink from './ModSettingShortlink'
127+
import GroupProfileImage from './GroupProfileImage'
128+
import OurFilePond from './OurFilePond'
129+
import ModGroupSetting from './ModGroupSetting'
130+
const OurToggle = () => import('@/components/OurToggle')
131+
132+
export default {
133+
components: {
134+
ModGroupSetting,
135+
OurFilePond,
136+
GroupProfileImage,
137+
OurToggle,
138+
ModSettingShortlink,
139+
GroupSelect
140+
},
141+
data: function() {
142+
return {
143+
groupid: null,
144+
uploadingProfile: false
145+
}
146+
},
147+
computed: {
148+
group() {
149+
return this.$store.getters['group/get'](this.groupid)
150+
},
151+
shortlinks() {
152+
return this.$store.getters['shortlinks/list']
153+
},
154+
active: {
155+
get() {
156+
return Boolean(this.group.mysettings.active)
157+
},
158+
set(newval) {
159+
this.saveMembershipSetting('active', newval ? 1 : 0)
160+
}
161+
},
162+
modconfig: {
163+
get() {
164+
return parseInt(this.group.mysettings.configid)
165+
},
166+
set(newval) {
167+
this.saveMembershipSetting('configid', newval)
168+
}
169+
},
170+
tagline: {
171+
get() {
172+
return this.group.tagline
173+
},
174+
set() {}
175+
},
176+
modConfigs() {
177+
return this.$store.getters['modconfigs/configs']
178+
},
179+
modConfigOptions() {
180+
const ret = []
181+
this.modConfigs.forEach(c => {
182+
ret.push({
183+
value: c.id,
184+
text: c.name
185+
})
186+
})
187+
188+
return ret
189+
}
190+
},
191+
watch: {
192+
groupid() {
193+
this.fetchGroup()
194+
}
195+
},
196+
mounted() {
197+
this.fetchConfigs()
198+
},
199+
methods: {
200+
async fetchGroup() {
201+
await this.$store.dispatch('group/fetch', {
202+
id: this.groupid,
203+
polygon: true
204+
})
205+
206+
this.$store.dispatch('shortlinks/fetch', {
207+
groupid: this.groupid
208+
})
209+
},
210+
async fetchConfigs() {
211+
await this.$api.session.fetch({
212+
components: ['configs'],
213+
modtools: true
214+
})
215+
},
216+
async saveMembershipSetting(name, val) {
217+
const settings = this.group.mysettings
218+
settings[name] = val
219+
220+
await this.$store.dispatch('auth/setGroup', {
221+
groupid: this.groupid,
222+
userid: this.myid,
223+
settings
224+
})
225+
226+
await this.$store.dispatch('auth/fetchUser', {
227+
components: ['me', 'groups'],
228+
force: true
229+
})
230+
},
231+
uploadProfile() {
232+
this.uploadingProfile = true
233+
},
234+
profileUploaded(imageid, imagethumb, image) {
235+
// We have uploaded a photo. Remove the filepond instance.
236+
this.uploadingProfile = false
237+
238+
// Set the image id in the group.
239+
this.$store.dispatch('group/update', {
240+
id: this.groupid,
241+
profile: imageid
242+
})
243+
},
244+
saveGroupSetting(name, val) {
245+
// Note that we get a sneaky progress indicator and success from SpinButton even though actually we're doing the
246+
// work here triggered by the set on the computed value.
247+
const data = {
248+
id: this.groupid
249+
}
250+
251+
data[name] = val
252+
253+
this.$store.dispatch('group/update', data)
254+
}
255+
}
256+
}
257+
</script>
258+
<style scoped lang="scss">
259+
@import 'color-vars';
260+
261+
input,
262+
select {
263+
max-width: 300px;
264+
}
265+
</style>

0 commit comments

Comments
 (0)