RetroMatic is used for real-time retrospectives. See how to leverage Angular and Firebase for syncing data across all the participants. Retrospective's are held at the end of sprints in Agile software development. The team reflects on what happened in the sprint and determines actions for improvement.
To clone and run this application locally, you'll need Git and Node.js (which comes with npm) installed on your computer. From your command line:
Create a free Firebase project. In Firebase console, enable Email/Password, Google, and Anonymous sign-in under the sign-in method tab of the Auth section.
Update firebase config values in firebase.ts
. This config file will be ignored from Git. Copy firebase.example.ts
and rename it to firebase.ts
. These values can be found in Firebase console here: Firebase Console > Overview > Add Firebase to your web app
.
firebase: {
apiKey: '',
authDomain: '',
databaseURL: '',
projectId: '',
storageBucket: '',
messagingSenderId: ''
}
npm install
npm start
$
are Firebase-generated unique IDs.
├── retroboards
│ └── $retroboardId
│ ├── creator (username)
│ ├── creatorId ($userId)
│ ├── noteCount
│ ├── dateCreated
│ ├── name
│ └── timeZone
├── buckets
│ └── $bucketId
│ ├── retroboardId ($retroboardId)
│ ├── creator (username)
│ ├── creatorId ($userId)
│ └── name
├── notes
│ └── $noteId
│ ├── creator (username)
│ ├── creatorId ($userId)
│ ├── retroboardId ($retroboardId)
│ ├── bucketId ($bucketId)
│ ├── message
│ ├── voteCount
│ └── votes
│ └── $userId
└── users
└── $userId
├── favorites
│ └── $retroboardId
├── md5hash
└── displayName
{
"rules": {
"retroboards": {
".read": "auth != null",
".indexOn": ["creatorId"],
"$retroboardId": {
".write": "(auth != null && !data.exists()) || data.child('creatorId').val() === auth.uid",
".validate": "newData.hasChildren(['creator', 'creatorId', 'noteCount', 'dateCreated', 'name', 'timeZone'])",
"creator": {
".validate": "newData.isString()"
},
"creatorId": {
".validate": "auth.uid === newData.val() && root.child('users/' + newData.val()).exists()"
},
"noteCount": {
".validate": "newData.isNumber()"
},
"dateCreated": {
".validate": "newData.isString()"
},
"name": {
".validate": "newData.isString()"
},
"timeZone": {
".validate": "newData.isString()"
}
}
},
"notes": {
".read": "auth != null",
".indexOn": ["bucketId", "retroboardId"],
"$noteId": {
".write": "(auth != null && !data.exists()) || (data.child('creatorId').val() === auth.uid || root.child('retroboards/' + data.child('retroboardId').val()).child('creatorId').val() === auth.uid)",
".validate": "newData.hasChildren(['creator', 'creatorId', 'retroboardId', 'bucketId', 'message', 'voteCount'])",
"creatorId": {
".validate": "auth.uid === newData.val()"
},
"votes": {
".write": "auth != null"
},
"voteCount": {
".write": "auth != null"
}
}
},
"buckets": {
".read": "auth != null",
".indexOn": ["retroboardId"],
"$bucketId": {
".write": "(auth != null && !data.exists()) || data.child('creatorId').val() === auth.uid",
".validate": "newData.hasChildren(['creator', 'creatorId', 'retroboardId', 'name'])",
"creatorId": {
".validate": "auth.uid === newData.val()"
}
}
},
"users": {
"$userId": {
".read": "$userId === auth.uid",
".write": "$userId === auth.uid",
".validate": "newData.hasChildren(['displayName', 'md5hash'])",
"displayName": {
".validate": "newData.isString()"
},
"md5hash": {
".validate": "newData.isString()"
}
}
},
"$other": { ".validate": false }
}
}
To set up users, from your Firebase dashboard:
- Click Authentication
- Click Sign-in method
- Enable Email/Password, Google, and Anonymous
MIT.