- Overview
- Transcript
3.5 Add Customer Interaction
In this lesson, we'll review the implementation of the task list, and then we'll implement the final piece of our application: customer interactions.
1.Introduction2 lessons, 04:28
1.1Introduction01:05
1.2Project Overview03:23
2.Rails Back-End5 lessons, 54:28
2.1Generate and Prepare the Application09:19
2.2Create Companies and Contacts10:35
2.3Add Projects, Tasks, and Offers14:47
2.4Track Customer Interaction12:01
2.5Secure API Access07:46
3.Ember Front-End5 lessons, 1:13:33
3.1Generate and Prepare the Ember-CLI Application08:34
3.2Application Layout and Authentication15:36
3.3Manage Companies and Contacts15:54
3.4Manage Projects, Tasks, and Offers19:18
3.5Add Customer Interaction14:11
4.Deployment1 lesson, 08:28
4.1Deploy to Heroku and Amazon S308:28
5.Conclusion1 lesson, 03:02
5.1Conclusion03:02
3.5 Add Customer Interaction
Hi and welcome back to create a Full-Stack Rails and Ember app. In the last lesson, we added projects and tasks to the front end application, and you got the task to add route for the offer model yourself as an exercise. Now I will show you my results. First, I edited the sidebar task list to be more concise and use the project's or offer's initials instead of the full name. Projects are also in bold, and offers are in italic. It also has a little delay built in, before it removes itself. So you can uncheck it again, if you marked it as complete by accident. In the Projects show page, I added a simple list of contacts and a way to assign them to the project. When you click that, you get a nice model view. There is also a list of offers that are assigned to the project, and they are linked to the details page. Here you can add tasks and assign contacts as well on a Contact screen. You now also have a list of projects and offers the contact is assigned to, if any. I used no new concepts of functionality while doing that. So I won't take into the source code but feel free to have a look if you are interested how I did it in detail. And in this lesson, we want to add our customer interaction functionality for project. I wanted to show underneath the tasks, contacts, and offers like a typical comment feed. So let's get started by adding the models. The first model we need is the base note one. It gets its properties, namely, title, description, and a createdAt date which is provided by race, and finally a belongsTo relationship to some topic which is polymorphic. What is this topic exactly? Well, it is either a project or offer. When we leave it there like this, Ember will complain that there is no model name topic. So how can we solve this? Well, let's create a dummy model that offers no additional functionality, although it could if you wanted to. For instance, we could set the assignment to notes here, you can then import it into your project model file and really place DS.Model of topic. Here we can also add the hasMany relationship to notes. Let me also do this to the offer model. Now we need to add some templating. I could do this in a component, of course, and it would probably be the better idea. Remember, components are cool, but I won't do it this time. I am only going to add this to the project right now, and won't reuse it. You could practice extracting something into a component after this lesson though, and add the same functionality to offers. So first, I need to use an each loop to loop through all my notes. To separate them nicely, I'm going to put a horizontal line above each. Now starts to formatting. First, we want the box on the top right it contains the date. Of course, I lied before, I added moment as an Ember addon to be able to format my dates nicely at moment yes. I'm also going to add a button to delete the note here. Next, I want to have the note.title and an h6 tag as well as a conditional to check if there is a contact. I can do that right now although there is no relation on any model because those properties default to now and are therefore ignored by Handlebars. So let's add a link to the contact and then print out the full name. After that, I'm adding a clear fix. So the description won't wrap around the date but just below it, even if there's no title or contact. Afterwards, I'm putting the description into a paragraph tag. Let's try this out. When we visit the project's show page in the browser, you can immediately see there is an error that there is no model personal conversation. It picked up some notes from the race backend and wants to instantiate it with the real type, provided there trace an API payload. So we have to create the note subclasses right now to make it work. We can just duplicate the note class, and then import the note from relationship/models/note. After renaming the class variable, we just extend from note. Remove the attributes and change the relation to contact. Now we can duplicate the file again or personal conversation, email message, and general note. But this one doesn't need a contact relationship. In the interest of time, I won't bother renaming the class variables since it won't affect functionality. When we now visit the project's page, it loads again, but fetching the notes is broken. It uses an URL for the special note type we don't have. We needed to use notes. To fix that, we can add special adapters for those models. Therefore, we just have to import the application adapter and extend it. There is a nice function called pathForType, we can override, where you can, for instance, transform all your types to the underscored instead of their first format. Since we don't need that, we can simply return notes. Unfortunately, this won't hierarchically traverse through a parent classes, so we have to duplicate this one for all note types. Now the page shows some notes that are present in the database. The final feature is to add a form to add new notes. In the show template, we can add a form that gets an add note action which triggers on submit. Now it's time for the fields, first we need a select field to set the note type. I'm giving it an id because I want to reference it later as well as an action called changeNoteType that triggers on change. For the options, I'm going to add the note type as values and some labels. Those are the exact name of the classes. Afterwards, I'm going to add an input helper that will hold the title. I won't set this to a model property just yet, but store it in a controllor property. For the description, it is almost the same thing, only that I'm using a textarea instead. Now we need to set the contact if it's possible. I'm going to surround the select field with the condition noteTypeAllowsContacts. I'm going to use a collection-select component, which is essentially the company select field, with a bit more conditional functionality. For instance, you can set an emptyValueDescription, and when this is set, it allows to also set now, which we don't always want. Finally, we need a submit button to actually save the note. This will automatically trigger the form submit action. So we don't need a separate one on the button itself. So this is how it looks in the browser. We can't see the contact select field since the conditional defaults to false. Now we need to set up the controller logic to make this thing actually work. In the ProjectShowController, I first add the property defaults for the fields, newNoteType is going to be a general note. newNoteTitle and newNoteDescription are going to be empty strings, and newNoteContact is going to be null. Now I want the noteTypeAllowsContact property that depends on newNoteType. I want it to return false if the newNoteType property is undefined, which might happen in edge cases are the type is general-note. I also just remembered that I wanted to sort the notes in a better way, so let's add that very quickly. I want the newest notes on the top. Here, I can add an array proxy that always gives us the array functionality. Whatever the content may be in our case, it is going to be models.notes. Then I want to sort it by createdAt, and finally reversed the array to get the newest first. In the template, we just have to replace notes with notesByNewest. Now I need to create my actions. First, changeNoteType, it will set the note type to the value of the select field which we can fetch with jQuery ntid. Then deleteNote, which is just a one liner. We already provide the note object within the function and just call DestroyRecord on it. Finally, the main function, add note. Here, we want to create a new note record via the store and use the new note type as the type parameter. Then we need to set the values, title, description, and the contact. We can do this because whenever the contact is not present in a model, it won't get serialized and therefore, not sent to the server. Finally, we also have to set the topic to be the model. The note was created locally. Now we need to save it, and after we receive a response, we can add it to the project of pushObject. It won't get set automatically because of polymorphism. When the project is reloaded, it will get fetched though. Finally, we have to reset the form values to the defaults. Now we can test it in the browser. But before we do that, I made a little mistake in the show template. It isn't model.notesByNewest but only notesByNewest and status as a controller property. Let's try it out by setting the note type to Phone Call. And you can see the contact select field appear. That's change that to myself, add a title and copy of some content from below. Now when we save, you can see it was added below, and the form was reset. Let's also add a general-note without the title, and it will look like this. For testing the deletion, let's just remove a note. That works great. In this lesson, we added some customer interaction for project and overall, created a pretty decent application for a few hours work. If you want, you can add the notes to offers as well. In the next lesson, we are going to deploy the whole thing, the backend and the index page to Heroku with a neat little trick. And the assets to Amazon S3 within another Embassy add-on. See you there.







