Filters

I’ve been looking for a way to filter out any posts that don’t include the current user ID in the nested values of firebase, it has been far far more difficult than I could have anticipated. I wanted to create a filter an ng-repeat directive to show only the autherised user by doing the following:

    <div class="meeting" ng-repeat="(key, meeting) in meetings | filter:'user:authUser.uid'">

I thought this would scan the posts that ng-repeat pulls as an array and filter any posts that don’t include the user’s ID in the user value as it shows in firebase:

Screen Shot 2017-04-18 at 02.32.36

As you can see the user variable contains the hash for the user id, shown in javascript as authUser.uid. Of course I thought I would have to convert the user ID to a variable to use with the HTML I inserted the ng-repeat directive into, so I wrote the following.

Javascript:
var userID=authUser.uid
HTML:
    <div class="meeting" ng-repeat="(key, meeting) in meetings | filter:'userID'">

But this didn’t work either, and neither did any variation of it, so I began researching how to create a filter and found a way to filter using Javascript here, hoping I could filter without pulling all data from firebase:

 Javascript:
var meetings = new Firebase("https://speakers-corner.firebaseio.com/")
                      .orderByChild('user')
                          .equalTo(authUser.UID);
HTML:
<div class="meeting" ng-repeat="(key, meeting) in meetings>

But this didn’t work, so I began working on how I could use queries from the Firebase API:

Screen Shot 2017-04-18 at 02.42.22

This is information I took from the Firebase documentation and added some more code into Firebase:

Javascript:

$scope.meetings = function() {
    var filterPosts = new Firebase('https://speakers-corner.firebaseio.com/');
    var userFiler = $firebaseArray(filterPosts);
    userFilter.$ref().orderByChild("user").equalTo(authUser.uid){
        }
    });
  };

This isn’t exactly what I wrote but at the time I was focused on fixing this problem, it didn’t work of course, Firebase documentation tells you to order the results before filtering, which is why I included ‘orderByChild’ before ‘equalTo’.

Instead I found a section on the firebase documentation specifically about filtering by child Key:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="dimensions/height"&startAt=3&print=pretty'

This was the code I found, but I had no clue how to include it in my javascript file, curl isn’t something I’d seen before. After some time trying this I finally found a website that would help me.

Javascript:
$scope.filterByUID = function(post) {
      if (post.user === authUser.uid) {
           return true;
           }
           return false;
      }
HTML:
<div class="meeting" ng-repeat="(key, meeting) in meetings | filter:filterByUID">

Being my first project ever using javascript this took around 2 days to solve, but you learn something new every day. The result is that my meetings page, which I’ll be repurposing as the account page now shows a list of posts submitted by the current user:

The Website:

Screen Shot 2017-04-18 at 03.02.57

Firebase file structure:

Screen Shot 2017-04-18 at 03.04.14

 

As you can see the post created by wut isn’t shown, there is an issue with this however as the delete button deletes the first post in the list whether it is shown or not. Something I’ll have to fix.

Text Boxes

I’ve had an annoying time trying to create a large text box for the content of my letters, the <input> element in html only works for a single line so I’ve had to create a <textarea> as well:

HTML:
<textarea type="text" name="lettercontent"
                placeholder="Write your letter here..."
                ng-model="lettercontent" ng-required="true"></textarea>
CSS:
.addmeeting .inputwrapper textarea {
    resize: none;
    float: left;
    width:100%;
    height:200px;
}

resize: none stops the user from being able to change the size of the text box, the height of 200px is because originality the text box was extremely small. I’ve also coppied the format of the <input> element in CSS which I’ll be changing later on. The result is this:

Screen Shot 2017-04-18 at 03.10.42

How I will structure the back end

Here is the file structure I’ll be creating in the database:

  • Speakers Corner
    • User
      • User id
        • Email
        • First name
        • last name
        • Account creation date
        • type (a value to allow permissions for moderators and allow for representative accounts later)
        • Posts
          • Post id’s created by the user
            • Post type (Origional Letter or reply)
        • Account deleted (true/false for soft delete)
    •  Posts
      • Post id
        • Created user id
        • Post creation date
        • Title
        • Letter
        • type (a value to allow permissions for moderators and allow for representative accounts later)
        • Topic/tags*
        • Replies
          • <created user id>
          • Post creation date
          • Letter
          • Post deleted (true/false for soft delete)
        • Post deleted (true/false for soft delete)

I want to separate the posts from the users so that one can be completely deleted easily without affecting the other, if someone wanted their information deleted permenantly from the database I’d just have to delete the ‘User’ folder without the posts they made or the replies being affected.

There may have to be more added to this file structure but as far as I can tell, this is all I’d need.

*Topic/tags is a difficult one to figure out, I need to create an indexing system that allows for any topic to be seen as easily as any other. I can’t account for every possible topic so I’m considering a tag system where the user adds their own custom tags for finding their post in the search. However this would have problems with people adding the most popular tags without it applying to their post, I’ll look into this more but it’s a difficult one to figure out. Allowing users to create topic catagories would be the best I think, but I cant allow anyone to create any catagory or I’d have a hundred catagories for the same thing. How do you catagorize qualatative data?

Some Updates – Being able to add and remove data from firebase

Over the past few weeks I haven’t worked on Speakers Corner so much, but recently I’ve followed a lynda tutorial and have successfully created the functionality for adding and removing data to firebase through the site. At the moment it adds and removes meeting names and displays them on the site but I’ll post the code to show how I’ll be changing this to fit my site.

Adding and removing meetings

Adding and removing meetings firebase

meetings.js

myApp.controller(‘MeetingsController’ ,
[‘$scope’, ‘$firebaseAuth’, ‘$firebaseArray’,
function($scope, $firebaseAuth, $firebaseArray) {

var ref = firebase.database().ref();//reference to the firebase database
var auth = $firebaseAuth(); //uses the authentication service and places it in the auth variable

auth.$onAuthStateChanged(function(authUser) {//uses a method to run a function when a user logs in, which returns true and is stored in the authUser variable
if(authUser) { //if authUser exists run the following:
var meetingsRef = ref.child(‘users’).child(authUser.uid).child(‘meetings’);//goes to users/(userid)/meetings in firebase
var meetingsInfo = $firebaseArray(meetingsRef);//pulls an array of info from the variable ‘meetingsRef’

$scope.meetings = meetingsInfo; //puts meetingsInfo into meetings

$scope.addMeeting = function() {
meetingsInfo.$add({ //$add is how to push data to the database
name: $scope.meetingname, //pushes the input field meetingname from meeting.html
date: firebase.database.ServerValue.TIMESTAMP //pushes the server time
}).then(function() {
$scope.meetingname=”;//clears the input from the meetingname feild
});//promise
}//addmeeting

$scope.deleteMeeting = function(key) {
meetingsInfo.$remove(key); //$remove is how to delete things from the database
}

}//Authuser
});//onAuthStateChanged
}]); //myApp.controller

Meetings.html

<div class=”card meetings cf”>

<div class=”textintro”>
<h1>Add Meeting</h1>
<p> Type a meeting name and hit +</p>
<form action=”” class=”formgroup addmeeting cf”
name=”myform”
ng-submit=”addMeeting()”
novalidate><!–ng-submit use angular js to submit a form, use a method called addMeeting, novalidate stops the browser validating instead of angular–>
<div class=”inputwrapper”>
<input type =”text” name=”meetingname”
placeholder=”Meeting name”
ng-model=”meetingname” ng-required=”true”>
</div>
<button type=”submit” class=”btn”
ng-disabled=”myform.$invalid”><!–$invalid checks a meeting name has been typed from ng-required=”true” above–>+</button>
</form>
</div>
</div><!– meetings cf –>
<div class=”card meetings cf”>
<h2>Your Meetings</h2>
<div class=”meeting” ng-repeat=”(key, meeting) in meetings”><!–ng-repeat is an angular directive that in this example pulls a key (key is the hash created in the Firebase Database) and the meeting infomation for every instance of the object (in this case the array) called ‘meetings’, created in meetings.js –>
<button class=”btn btn-delete tooltip” name=”button”
ng-click=”deleteMeeting(key)”><span>Delete this meeting</span></button> <!–ng-click executes a methood called deleteMeeting, and passes it the key (the hash) so it knows which one to delete.–>
<span class=”text”>{{meeting.name}}</span>
</div>
</div>

So I can add more text fields to the “addMeeting()” input form, then add those input fields to the addMeeting function (these names will change). Then to display the information I just have to add more to the <span> contatining meeting.name at the bottom.

The issue with this is that the $remove command deletes the information from the database permenantly. I will be working out a way to structure the back end where a soft delete is done; having a deleted variable that changes on pressing delete, then adding a condition to the ng-repeat to not display any with the deleted variable as true.

New flat logo

I’ve designed a new logo to better go with the flat design I intend to use. I have’t chosen the colours yet but they will be synonymous with the rest of the website, each section will be coloured slightly differently.

flatter logoflatter logo2

I wanted to create an optical illusion with negative space, however I’ve been looking at other logos and I think the most well designed ones are self contained inside some kind of border. I’d guess that is so the logo can stand out and not interfer with whatever page its put on.