EPIC: `groups`: how to collaborate with one or more `people`
Story
As a person wanting to collaborate with others,
I want a way to create a group
that I can add people to
and then share a list of items with
So that I can keep track of who sees, can edit and work on what items.
Note: the initial "MVP" version of this feature is just a basic
groupthat has 1 or morepeople. No permissions, complexRBAC,LDAPor other "Enterprise" features, yet! We can iterate from our simple version and add more advanced/complex features later. For now we just need something we can start using internally and collect feedback from ourselves.
Todo
- [ ] When a
personfirst tries to share anitemorlist(ofitems) in theApp,- [ ] Automatically and transparently create a new
groupfor them with their name as thegroup.name - [ ] Inviting someone to collaborate on an
itemwill automatically add them to thegroup - [ ] Once the initial share has occurred, we can inform the
person: 🤖 "By the way I created this group for you and you can add morepeopleto it by visiting:/groups/:id"
- [ ] Automatically and transparently create a new
- [ ] Create endpoint to manage
groups. - [ ] Create an interface to allow
peopleto manually create a newgroup
Proposed Schema (please comment/discuss!)
group
- [ ]
name:Fields.Encrypted- the name of the group. - [ ]
description:Fields.Encrypted- the description - [ ]
kind:String- e.g.family,friends,personal,sports,work, etc. - we will havedefaultkinds that can help thepersonto categorise theirgroup; we could consider making this a free-text field in the future or adding more kinds via Pull Request (so they are hard-coded) because, let's be fair, there are't that many kinds ofgroupwe will need.
group_members
The lookup table that lists the people who are members of a group
- [ ]
group_idIntfk: theidof thegroup - [ ]
person_idInt: theperson.idof the person in thegroup - [ ]
inserted_atDateTime: defaultPhoenixfield for the insertion of a record. - [ ]
adminBool: if the person can administer (add/remove others from) thegroup - [ ]
added_byInt: theperson.idof thepersonwho added thememberto thegroup - [ ]
removedDateTime:default:nullthe date when a person is removed from agroup(it happens ...) - [ ]
removed_byInt:default:nulltheperson.idthat removed thispersonfrom thegroup
Features
- [ ] Build mini SPA for creating/managing
groupsusingLivView:
@SimonLab thoughts? Am I missing anything? Am I over-complicating it? or is this "just enough" to get started? Thanks! 🙏
When a person first tries to share an item or list (of items) in the App,
Here is how I view the relations between items, lists and groups
- An item must belongs to a list. Depending on the UI, the user can create manually the
defaultlist or we can create it automatically when the first item is created. We might want to review what we want to display on the main page now that we will have groups, lists and items - There is a
many_to_manyrelationship between list and group (a list can belongs to many groups, and a group has many lists) (or do we only want to have a list belonging to only one group?) - A group as many person, and a person has many groups.
So from the issue above, I would add the list and person table/schema.
The person table as for primary key the id already returned by the auth app, however we need to add a name unique field to allow
Inviting someone to collaborate on an item will automatically add them to the group
@SimonLab agreed. These should all be many-to-many relationships. ✅
for now an item is "owned" by a single person 🥇
but when that item gets added to a list (or more than one list) and shared with a group, 👥
it can be edited by anyone in the group. 📝
We only need a people schema/table in the sense that it's a Foreign Key of these other tables. 🔑
but otherwise we could continue not having the people table. 💭
I think in terms of building an MVP, the buildit.md log
makes it clear that we didn't need the people schema/table until now,
but as the App evolves, we are beginning to need it. 💭
I've created the following PR https://github.com/dwyl/mvp/pull/162 which created the people table and person schema.
This table contains the name field which will be used to search and share items with other people.
The next step is to create the list and group structure, as we mentioned this morning on our call an item belongs to many list and a list can belongs to many groups (ie many_to_many relations between items-list and list-group)
@SimonLab on further reflection, groups is the domain of auth application. 👤
Yes, it will be used in the App/MVP, 👌
but it relates to people which are the domain of the auth App. 🫂
Duplicating the people table in the App/MVP is "mixing concerns" ...
Instead we need to:
-
Create
groupsandgroup_membersin theauthApp. 🆕 -
Create an excellent UI/UX for adding
peopleto agroup. ➕ -
Add a new field
gids("group ids") to theJWTreturned when someone signs in withauth -
Use the
gidsin theMVP. 📱 -
Create a
GET /groupsREST API endpoint inauththat accepts aJWTas Auth Token and returns an Array [using JS parlance as the response will be JSON] ofgroupsthatpersonis a member of:
- Group IDs
- Group Names
- Array of Members with their:
-
id:int -
admin:boolean -
name:string
-
Sample data response:
[
{
"gid": 1,
"name": "DwylTeam",
"members": [
{
"pid": 1,
"name": "Alex",
"admin" true
},
{
"pid": 2,
"name": "Jane",
"admin" false
},
],
},
{
"gid": 2,
"name": "FootballSquad",
"members": [
{
"pid": 1,
"name": "Alex",
"admin" false
},
{
"pid": 2,
"name": "Jo",
"admin" true
},
],
}
]
This way the App/MVP does not store any personally identifiable information
and is focussed on one thing: getting things done.
Whereas auth which already handles personal data will manage groups and group_members.
Making an attempt to write this up in the BUILDIT.md dev log ... ✍️
Minor side-track: https://github.com/dwyl/auth/issues/229
Next side-quest: https://github.com/dwyl/auth/issues/230 ⏳
https://fontawesome.com/v3/icon/group

Rather than import all of font awesome ... 🤷♂️
Just going to in-line the SVG for the icons we need from https://heroicons.com e.g:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
<path fill-rule="evenodd" d="M8.25 6.75a3.75 3.75 0 117.5 0 3.75 3.75 0 01-7.5 0zM15.75 9.75a3 3 0 116
0 3 3 0 01-6 0zM2.25 9.75a3 3 0 116 0 3 3 0 01-6 0zM6.31 15.117A6.745 6.745 0 0112 12a6.745 6.745 0
016.709 7.498.75.75 0 01-.372.568A12.696 12.696 0 0112 21.75c-2.305 0-4.47-.612-6.337-1.684a.75.75
0 01-.372-.568 6.787 6.787 0 011.019-4.38z" clip-rule="evenodd" />
<path d="M5.082 14.254a8.287 8.287 0 00-1.308 5.135 9.687 9.687 0 01-1.764-.44l-.115-.04a.563.563
0 01-.373-.487l-.01-.121a3.75 3.75 0 013.57-4.047zM20.226 19.389a8.287 8.287 0 00-1.308-5.135
3.75 3.75 0 013.57 4.047l-.01.121a.563.563 0 01-.373.486l-.115.04c-.567.2-1.156.349-1.764.441z" />
</svg>

Reeeeeeeally want to get back to this ... ⏳ 😢