Compare commits

..

2 Commits

Author SHA1 Message Date
980a5bb14b Removed un-needed files 2024-10-22 20:17:26 +01:00
8afd7c5694 Add support for group imagery 2024-10-22 20:16:44 +01:00
4 changed files with 43 additions and 2 deletions

View File

@ -24,6 +24,7 @@ def create(user, data):
"name": data["name"],
"description": data.get("description", ""),
"closed": data.get("closed", False),
"memberPermissions": ["viewMembers", "viewNoticeboard", "postNoticeboard", "viewProjects", "postProjects"],
}
result = db.groups.insert_one(group)
group["_id"] = result.inserted_id
@ -43,6 +44,10 @@ def get_one(user, id):
group = db.groups.find_one({"_id": id})
if not group:
raise util.errors.NotFound("Group not found")
if group.get("image"):
group["imageUrl"] = uploads.get_presigned_url(
"groups/{0}/{1}".format(id, group["image"])
)
group["adminUsers"] = list(
db.users.find(
{"_id": {"$in": group.get("admins", [])}}, {"username": 1, "avatar": 1}
@ -64,7 +69,7 @@ def update(user, id, update):
raise util.errors.NotFound("Group not found")
if user["_id"] not in group.get("admins", []):
raise util.errors.Forbidden("You're not a group admin")
allowed_keys = ["name", "description", "closed"]
allowed_keys = ["name", "description", "closed", "memberPermissions", "image"]
updater = util.build_updater(update, allowed_keys)
if updater:
db.groups.update_one({"_id": id}, updater)

View File

@ -478,6 +478,8 @@ def group_route(id):
"name": fields.Str(),
"description": fields.Str(),
"closed": fields.Bool(),
"memberPermissions": fields.List(fields.Str()),
"image": fields.Str(allow_none=True),
}
)
def group_route_put(args, id):

View File

@ -1,6 +1,6 @@
import React, { useEffect } from 'react'
import { Helmet } from 'react-helmet'
import { Segment, Loader, Menu, Message, Container, Button, Icon, Grid, Card } from 'semantic-ui-react'
import { Segment, Loader, Menu, Message, Container, Button, Icon, Grid, Card, Image } from 'semantic-ui-react'
import { Outlet, Link, useParams } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { toast } from 'react-toastify'
@ -89,6 +89,8 @@ function Group () {
<Grid stackable>
<Grid.Column computer={4}>
<Card fluid color='yellow'>
{group.imageUrl &&
<Image src={group.imageUrl} wrapped ui={false} />}
{group.description &&
<Card.Content>{group.description}</Card.Content>}
{group.closed &&

View File

@ -6,6 +6,7 @@ import { toast } from 'react-toastify'
import utils from '../../../utils/utils.js'
import actions from '../../../actions'
import api from '../../../api'
import FileChooser from '../../includes/FileChooser'
const PERMISSIONS = [
{ name: 'viewMembers', label: 'Allow members to view other members' },
@ -37,6 +38,7 @@ function Settings () {
dispatch(actions.groups.request(false))
})
}
const savePermission = (permissionName, enabled) => {
const permissions = group.memberPermissions || []
const index = permissions.indexOf(permissionName)
@ -51,6 +53,7 @@ function Settings () {
toast.error(err.message)
})
}
const deleteGroup = () => {
utils.confirm('Really delete this group?', 'You\'ll lose all entries in the group feed and anything else you\'ve added to it.').then(() => {
api.groups.delete(group._id, () => {
@ -61,6 +64,16 @@ function Settings () {
}, () => {})
}
const updatePicture = (image) => {
api.groups.update(group._id, { image }, g => {
if (!image) { // Needed to ensure the avatar is immediately unset
g.image = null
g.imageUrl = null
}
dispatch(actions.groups.updateGroup(group._id, { image: g.image, imageUrl: g.imageUrl }))
})
}
return (
<div>
<Segment color='blue'>
@ -76,6 +89,25 @@ function Settings () {
<Divider hidden />
<Form.Button loading={loading} color='teal' icon='check' content='Save changes' onClick={saveGroup} />
</Form>
<Header>Group picture</Header>
<p>Upload a picture to represent your group. This will be shown on the group page and may be viewable to both members and non-members.</p>
{group.imageUrl &&
<div style={{ marginBottom: 10 }}>
<img src={group.imageUrl} alt='Group' style={{ maxWidth: 200, borderRadius: 5 }} />
</div>
}
<div style={{ display: 'flex', alignItems: 'center' }}>
{group.imageUrl &&
<Button basic color='gray' icon='times' content='Remove image' onClick={() => updatePicture(null)} />
}
<FileChooser
forType='group' forObject={group}
trigger={<Button basic color='yellow' icon='image' content='Choose an image' />}
accept='image/*' onComplete={f => updatePicture(f.storedName)}
/>
</div>
</Segment>
<Segment color='blue'>