Giter Site home page Giter Site logo

sumonst21 / pillar Goto Github PK

View Code? Open in Web Editor NEW

This project forked from da-bao-jian/pillar

0.0 2.0 0.0 120.89 MB

Pillar is a multi channel real time communiaction app exploiting MERN stack's full potential. The app is purposely crafted with the goal to facilitate efficient group communications

Home Page: https://pillrz.herokuapp.com

License: MIT License

JavaScript 87.03% HTML 1.12% CSS 0.86% Shell 0.01% SCSS 10.97%

pillar's Introduction

Pillar

Communication Made Better by Pillar Live

Splash Page Demo

Mission Statement

Pillar was born out of our frustration with using Slack as the primary tool for group communications. Slack is all fine and dandy until users try to migrate a message from one channel to another, and when time is of the essence, this whole quit-current-channel-then-switch-to-another-then-switch-back process could become exponentially more cumbersome.

As software developers, we work in groups, thus having an integrated UI for multi-channeled display comes in extremely handy when coordinating with different personel. To achieve this goal, we took inspiration from TweetDeck, a dashboard application that is capable of receving multiple streams of tweets per user's customization.

In short, you can think of Pillar as our attempt to create a 'dashboarded' Slack that displays multiple channels to better facilitate real time group communications.

Tech Stack

Design roadmap

To enhance user experience, we sketched out a design to optimize the efficiency for ease of use, which includes:

  • a single page dashboard that provides accessibility to all of Pillar's features; all features

  • lightweight indempotent chatroom operations (create, delete, update, show, join/leave, post/delete messages); Chatroom Operations

  • cross device state preservation for chatroom display; state preservation

  • algorithmic solution(Boyer-Moore) for fast seach result lookup. searchbar

Design execution

  • Single page dashboard dashboard

    • For ease of use, we comprised all of Pillar's features into a single dashboard.
    • By design, 'DashBoard' component renders all of the sub-components. Therefore, its main functions are fetching all the necessary data upon mounting and setting up the websocket connection.
    • Below is the code where we fetch data and connect websocket upon mounting:
    componentDidMount(){
        
        getRooms(this.props.user.id)
           .then(rooms => {
              this.setState({
                 roomsJoined: rooms,
              })
           })
           .then(()=>{
              getAvailableRooms(this.props.user.id)                                
              .then(rooms => {
                 this.setState({
                    roomsAvailable: rooms,
                 })
              })
              .then(()=>{
                 this.setState({all: this.state.roomsAvailable.data.concat(this.state.roomsJoined.data)})
              })
           })
        
        this.socket.on("user left", this.userLeft);
        this.socket.on("user joined", this.userJoined);
        this.socket.on("room deleted", this.roomDeleted);
        this.socket.on("room created", this.roomCreated);
     }
  • chartooms operations

    socket.on("Create Message", msg => {
      connect.then(db => {
        try {
    
          const message = new Message({
            message: msg.message,
            sender: msg.userId,
            room: msg.room,
            username: msg.username,
          });
    
          message.save((err, document) => {
            //record error, if any
            if (err) return res.json({ success: false, err });
            io.emit(`MTC_${document.room._id.toString()}`, document);
             
            //add to a rooms array of messages
            Room.findOneAndUpdate(
              { _id: document.room._id },
              { $push: { messages: document } },
              (error, success) => {
                 
                if (error) {
                  console.log("Add message to room array failed: " + error);
                } else {
                  io.emit(`MTC_${document.room._id.toString()}`, document);
                  console.log("Username: "+message.username);
                   
                }
              }
            )
              
          })
        } catch (error) {
          console.log(error);
        }
      })
    
    })
  • cross device state preservation

    • One of Pillar's key features is to preserve the chatroom's state across sessions. In other words, a closed chatroom should remain closed if an user logs back in after logging out.
    • To achieve this, we came up with the design to save the chatroom's state to the database upon an user open/close a room.
    • Below is the code where we save the chatroom state in the backend:
    router.patch('/closedfor', (req, res) => {
      REQ = req; 
      Room.findByIdAndUpdate(req.body.roomId)
      .exec().then(room => {
        if (room.closedFor.includes(req.body.email) ){
          room.closedFor = room.closedFor.filter(match => (match != req.body.email))
      }
      else{
          room.closedFor.push(req.body.email)
      }
      room.save().then(saved => {
        Room.find({})
          .populate({
            path: 'messages',
            model: 'Message',
            populate: {
              path: 'sender',
              model: 'User'
            }
          }).populate({
            path: 'users',
            model: 'User'
          }) 
          .exec((err, rooms) => {
            if (err) {
              res.status(404).json({ noroomsfound: 'No rooms found' });
            } else {
              let roomList = filterRooms(rooms, req.body.id);
              res.json(roomList);
            }
    
          })
      }) 
      })
    });
  • algortithmic solution for searchbar

    • One of the most complained features of Slack is its search being slow. To create a more efficient searchbar, we customized our own Boyer-Moore algotithm implementing its bad character rule.
    • Below is the code where we implement the algorithm:
    boyer_moore(arr, sub) {
          let filteredMessages = [];
          arr.forEach(room => {
              for (let r = 1; r < room.length; r++) {//iterating thru messages in each room
                  if (room[r].slice(0, 8) !== 'https://' && room[r].slice(room[r].length - 4, room[r].length) !== '.gif' &&
                      room[r].slice(0, 4) !== '<img' && room[r].slice(room[r].length - 1, room[r].length) !== '>') {//skipiing gifs
                      room[r] = this.removeEmojis(room[r]);
                      let skip;
                      let bad_char = new Array(265).fill(-1);
    
                      for (let t = 0; t < sub.length; t++) {//constructing a bad character table for each chatacter in the substring at its corresponding place in 256 ASCII characters
                          const index = sub[t].charCodeAt();
                          bad_char[index] = t;
                      };
    
                      for (let i = 0; i <= room[r].length - sub.length; i += skip) {//compare each character from substring to string, if mismatch, then shift to the next    matching character; if no matching character found, shift the entire length of the substring
                          skip = 0;
                          for (let j = sub.length - 1; j >= 0; j--) {
                              if (sub[j].toLowerCase() != room[r][i + j].toLowerCase()) {
                                  const asciiIndex = bad_char[room[r][i + j].charCodeAt()];
                                  skip = 1 > j - asciiIndex ? 1 : j - asciiIndex;
                                  break;
                              }
                          };
                          if (skip === 0) {
                              filteredMessages.push([room[0], r - 1, i]);
                              skip++;
                          };
                      }
                  }
              }
          });
    
          return filteredMessages; 
      };

pillar's People

Contributors

da-bao-jian avatar davidfpease avatar jaelapen0 avatar lynnqueue avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.