Skip to content

RetroMatic's 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.

License

Notifications You must be signed in to change notification settings

MassiveNerds/RetroMatic

Repository files navigation

Massive Nerds

RetroMatic, a real-time retrospective tool.

Build Status npm Twitter Ko-fi


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.

Local Development

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

Firebase Structure

$ 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

Firebase Security Rules

{
  "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 }
  }
}

Firebase Authentication

To set up users, from your Firebase dashboard:

  1. Click Authentication
  2. Click Sign-in method
  3. Enable Email/Password, Google, and Anonymous

License

MIT.

About

RetroMatic's 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.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published