Coder Social home page Coder Social logo

project-phoenix's Introduction

Project-Phoenix

Rising from the ashes of paper RCI's , coming to a college near you.

Table of Contents

Introduction:

Clients:

Director of Residence Life, Michael Curtis and Director of Housing, Marta Peralta,
Gordon College

Team:

Eze Anyanwu
Stephanie Powers
Weiqiu (Rachel) You

Problem Statement:

The Problem:

The current system for documenting the condition of rooms is redundant, ambiguous and tedious. More specifically, students use an RCI (Room Condition Inventory) to document the state of the room when they move in and move out. The RCI is a long double-sided sheet of paper with space to comment on the state of various pieces of furniture in the room.
As a paper-based system, it has become hard to manage for the hundreds of students who live on campus. The current RCI system is redundant because a new RCI is required from each resident every year; information from previous years is not used.
It is ambiguous because the descriptions are subjective. What one student sees as major damage might be seen by another as minor. Accurately describing the extent of the damage also gets tricky. It is common during move-out procedures for students to protest fines for damages by saying "It was there before!".
It is tedious because a lot of manual work has to be put in by Residence Life to make sure information gets gathered.

Vision:

Our goal is to create a new RCI system that would be of benefit to students, Resident Advisors and Resident Directors. What we have in mind is a web-based system with a well thought out user interface that solves the problems presented above while also simplifying the process of recording the damages in a given room.
As further ( but important ) enhancements, the system will also provide an administrative interface for RAs and RDs. The interface will assist Residence Life staff in doing manual tasks ( e.g. finding who hasn’t submitted RCI’s and compiling fines ).

Technical Documentation:

Setup:

Throughout this readme, I'll be assuming that you have been given access to some VM that has permission to access the RCI database. I further assume that you have been given credentials with permission to log in to said Virtual Machine, publish to IIS and access the different tables that the online RCI uses.
If you are not sure, ask whoever your contact at CTS is.

Generally speaking, the online RCI application runs as a Windows process under the user [email protected] (as of August 4th 2018). This user has read/write permissions to the Rci and RciTrain site folders as well as to the Rci and RciTrain databases.

When you are debugging with Visual Studio, make sure that the user you open Visual Studio as also has permissions to read and write to the RCI and RCITrain databases. You'll get Login errors if that is not the case.

How To:

How do I find the project?

The code for this project is hosted in this repository. It is part of the projects hosted by the gordon-cs group, so you will need to be a part of that group and added as a collaborator on the project in order to commit changes to the repository.

How do I make changes and run the project to test?

This assumes you have a working understanding of the basics of git and the way github works. If you don’t, we suggest you start there before moving forward.

This project is written in C# using the ASP.NET framework. We are using the 4.6 version of the .NET framework, so the project can only be run on a windows machine with Visual Studio. If you are reading this, chances are that you have been given access to a Virtual Machine to do development work on the project.

  • Clone the project from the github repository. This should give you all the code you need to work on the project.
  • Start up Visual Studio. Open Project => Navigate to the folder you just cloned => Select the “Phoenix.sln” file.
  • When the project finishes loading, you should see the project files and folders on the right.
  • Make whatever changes you want, save and build.
  • Start debugging by clicking on the Green play button on the top, or Debug => Start Debugging.
  • After a few moments, the bottom status bar should turn orange, and the browser should start.

How do I publish my changes to the live websites?

There are two live websites accessible from within the Gordon network. You need to be connected to GordonNET to access them.

This is an example of the workflow:

  • Make a change and test it locally by running it directly from Visual Studio
  • Once you are confident that it is working, publish it to rcitrain.gordon.edu (See notes on how to publish below).
  • As the name might suggest, rcitrain.gordon.edu is the development site. Use it to make sure the changes work as expected on the web
  • Once you are sure everything works on rcitrain.gordon.edu, publish to rci.gordon.edu

Publish profiles have been set up to make publishing hassle free. When you publish to rcitrain.gordon.edu, the published web application will access the RCITrain database. When you publish to rci.gordon.edu, the published web applicatoin will access the main RCI database. This should happen automatically thanks to the publish profiles.

To publish:

  • Open Visual Studio as an administrator.
  • At the top, click on Build => Publish Phoenix.
  • A Publish Web window will open. You will find a drop down at the top with two options: RCI_Publish_DEV and RCI_Publish
  • Select RCI_Publish_DEV and click publish to publish to rcitrain.gordon.edu
  • Select RCI_Publish and click publish to publish to rci.gordon.edu

How do I change the format of the fine email?

Ok, so you have set up shop and received your first task; “Change the format of the fine emails to: so and so”. Your first questions might be: What are fine emais? Where are they and how can I change them? No worries, we anticipated this and got you covered.

When a resident checks out of their room with their Resident Advisor (RA), the Resident Director (RD) and RA eventually walk through the room a second time to finalize charges. Once that is done, the system sends out an automated email to the resident (or residents if it is an apartment common area) with a listing of the charges they owe. The format of the email is pretty much set, but who knows, maybe they want to add a comma somewhere in there.

Open up the project and select the Phoenix node on the right. Right-click on it and select Properties, then Resources. You should see a table with resources the project has. We are using the ASP.NET Resource feature to store the fine email string. This is not necessarily the best way to do it, but that’s what we came up with at the moment.

You should be able to edit the email string in this window. A few things to note:

Use the arrow keys to navigate across multiple lines, trying to click doesn't work as expected in this window. When the email string is used, it is formatted to include dynamic information like the date, the name of the resident, description of charges etc… This information ultimately appears where you see the {SOME DIGIT} symbols. If you are going to edit the fine email extensively, you should probably read more about C# string formatting before doing so. We currently don't do any complex string formatting, so you don't have to read much to understand how it works. The first paragraph of this article should bring you up to speed:

http://azuliadesigns.com/string-formatting-examples/

Point of imporvement: Allow Admins to change the fine email from the web portal.

How do I manually change the furniture that RCIs have?

RCIs come by default with a set of furniture to which you can add damages. It is possible to change that. One of the Admins should be capable of doing this through the web portal, so there should never be a need for you to do it manually. However, we will talk about this here to help introduce you to the different parts of the project.

Each dorm has a different set of furniture and the system reflects this. We use an SQL table as a template to tell the system what furniture needs to be generated for each type of room. The table in question is the RciTypeRoomComponnentTypeMap As the convoluted name suggest, this table maps each type of rci to the different room component types it will have.

There are currently two Rci Types (as of August 4th 2018): Common Area and Dorm Room.
A Room Component is a fancy name for "Furniture". It also refers to more general things like Incomplete checkout and Lost key fins that are "attached" to an Rci.

To add a new Room Component Type to Ferring Dorm Room Rcis, you'll need to add a new row in the RciTypeRoomComponentTypeMap table.

How do I find the user-uploaded pictures?

A better question is: What actually happens when you publish the project?

When you type in “rci.gordon.edu” you are actually accessing files on some remote computer. Specifically, you are accessing files on the CS-RDP-1 Virtual machine, which might be the machine you are using to work on the project. It should come as no surprise then, that you can find the published product on the machine you are using (if you are using CS-RDP-1 to do you development work). Navigate to the F:\Sites and you should see folders for all the sites that are hosted on this machine. There should folders for rci and rcitrain. These correspond to the sites rci.gordon.edu and rcitrain.gordon.edu. The pictures uploaded by users should appear under Content\Images. Images are organized into folders according to date of upload to make navigating easier.

How do I manually query the database?

As you start working in earnest on the project, it will often prove useful to examine the database or update it directly via queries. This can also be done using Microsoft Sql Server Management Studio. Open it up and log in to the adminprodsql.gordon.edu server using Windows authentication. "Windows Authentication" means "Use the same credentials I used to log into Windows".

Both the RCI database or the RCITrain database exist on this server. I would stay away from querying the RCI database completely since it contains real user data (unless you know what you are doing). Naturally, you will need to be familiar with some SQL query the database, and as this is not an SQL tutorial, you will find no help with that here...

Deep Dive

The Database

A distinction must be made between our tables and the views that were provided to us by CTS. Views are basically non-editable tables. The Views can be found under….you guessed it: the Views folder in either the RCITrain or RCI databases. The Tables can be found in the Tables folder. If you find something is missing in a View, it is most likely a CTS person that will have to update it (remember you can’t update it, you can just read).

Important: Both RCI and RCITrain databases must have IDENTICAL schemas at all times. So if you make a change to the schema of one, make sure you do it for the other.

Views: Account: Account information for everyone at the college. Does not contain password info.

CurrentRA: The canonical view for which accounts are RAs. If this isn’t up to date, the system won’t be either.

CurrentRD: The canonical view for which accounts are RDs. If this isn’t up to date, the system won’t be either.

Room: A view with all the rooms on campus. We have currently restricted it to only show residential rooms, but it actually also has access to all types of rooms including classrooms and offices. Those are not needed for the purposes of this system though.

RoomAssign: This is an important view. It dictates which resident is assigned to which room. The system depends on this to generate rcis. If a resident does not have a room assignment in this view, one must be created by the Residence Life staff before the resident will see their rci.

Session: Another important view. It is basically a listing of the all sessions present and past. Rci generation depends on this.

RoomChangeHistory: We don’t use this (^_^;)

Tables: These are tables that we created. You have full control over these.

Admin: A listing of the id numbers of the Admins. If someone is listed here, their admin role takes precedence over everything else. E.g. If you want to test the admin functionality, you can add your id number here...of course, this should be done on the RCITrain database

BuildingAssign: A mapping of Job Titles to hall codes for the halls a given RD is responsible for. If I am the RD of “Tavilla and Bromley”, there will be two records in the table that are as follows: “Tavilla and Bromley” : TAV “Tavilla and Bromley” : BRO

CommonAreaSignatures: A table to store common area signatures for common area rcis. A signature is either for Checkout or for Checkin.

Damage: This it the table that stores the damages that users enter. The type can be either TEXT or IMAGE. (WE NEED TO REMOVE THE FINE ASSESSED COLUMN)

Fine: This is the table that stores the charges and fines that RAs and RDs enter for residents.

Rci: This table represents the Rci entity. It has columns for all the Checkin and Checkout signatures so we can keep track of the state of the Rci.

The IsCurrent column is used to differentiate active rcis from old rcis. An rci is active throughout the year until sometime after checkout when the RD decides that they don’t need it anymore. They can then archive it by making it non-current

If an RCI has a GordonID, it is a normal rci. If it’s GordonID column is NULL, it is a common area rci.

RoomComponentType: In the spirit of the paper rci, each rci is made up of different components. These components can then be associated with damages through the Damage table.

RciType: The different types of Rcis we might have

RciTypeRoomComponentTypeMap: A mappipng table between the RciType and RoomComponentType tables.

Stored Procedures:

We only have one stored procedure. Normally, we would try to keep business logic outside the database, but this query was too complex to write through c#. This stored procedure is used to determine if any new rcis need to be created. A more in-depth explanation will be given in the Rci Generation section.

Authentication

Authentication is the process of determining that the user has a valid identity. To help us determine validity, Gordon maintains a directory of all its users and resources. This directory is accessible via the LDAP (Lightweight Directory Access Protocol).

So how does this happen in our application? When the user gets to the login page and inputs some credentials, the credentials are sent via LDAP to Gordon’s user directory. Given a username and a password, the Gordon directory can determine if the user is real and their password is correct. The result of this validation is sent back to our application. If the user is validated, a JWT (Json Web Token) is created for the user and stored in a cookie. You can read about JWTs here. In short, these tokens are a secure way to reliably establish the identity of the user on the server on each request.

Where is the code that does this? Good question. Controllers > LoginController.cs is the file that handles everything authentication.

The first method called “Index” returns the Login page. Notice that it is annotated with [HttpGet]. This indicates that the method is called when a request for /Index is made using the GET http verb. Whenever you enter a url into a browser, you are making a GET request to that address. So you can imagine that this method is responsible for responding to the request “GET rci.gordon.edu/Login/Index”. The default annotation for methods is [HttpGet], so if you don’t see it, assume that’s what it is.

The next method “Authenticate” is annotated with [HttpPost]. This method is responsible for accepting input from the user via a form submit. When the user submits their username and password, they get sent to this method. This is the method that does the actual authenticating. Go through it and try to understand what it does. It makes use of the LoginService class which has helper methods for authenticating.

Controllers and Views

Controllers and Views are at the center of the ASP.NET MVC framework. Controllers contain the “endpoints” of your application, the accessible url routes. If your controller was called HomeController.cs and had a method called Method1, the url route to access that method would be /Home/Method1. So if you application was running on rci.gordon.edu, the full url would be “rci.gordon.edu/Home/Method1”.

Views represent the html that the user ends up seeing in their browser.

There is no need to go deeper into Controllers and Views here. Microsoft has good documentation on starting out with their ASP.NET framework. If you are not familiar with ASP.NET at all, you should start by reading their guides and walking through their tutorials. Use these search terms to get you started: “ASP.NET MVC 5”. Here are some links to get you started:

https://www.asp.net/mvc

https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/introduction/getting-started

https://mva.microsoft.com/en-US/training-courses/introduction-to-asp-net-mvc-8322?l=VZ2619Zy_8804984382

RCI Generation

How are RCI’s generated? That’s a big question, and we’ll try to break it down here: RCIs are represented first as rows in the database. In ASP.NET, the table of RCIs is interpreted as a list of RCI objects with various properties.
The goal is to detect when a new RCI is needed, create a new RCI object, and save it to the database.

Detect when a new RCI is needed:

A resident needs a new RCI in two cases: They’ve never had an RCI. The date on their most recent room assignment is newer than the creation date of their most recent rci. This means that they have moved rooms since the last time an RCI was created.

Create a new RCI Object:

This is a simple step. Once we detect that someone needs a new RCI, we create a new Rci object in memory and populate it with the appropriate values.

Save to the Database:

Send an SQL query to the database. In this case, it will be something like insert into RCI(column1, column2, etc...) values (value1, value2, etc...)

Code please?

RCI Generation happens in the DashboardController.cs file. Depending on who logs in, different things happen:

If a resident logs in, the system will detect if a new rci is needed for that specific user. If an RA/RD logs in, a stored procedure is run that returns a list of new room assignments for which no rci has been created. RCIs are then created for all of them.

Unit Tests

Testing is important for peace of mind.
The most important part of our application is the part that reads and writes data from/to the database. That logic is all in one place, specifically the DapperDal.cs file. Unit tests have been written for every single function in this file. You can find the tests in the Phoenix.UnitTests project.
Please make sure that if you add a new function, you also add a corresponding unit test.
I use the term unit test loosely here. Historically, unit tests are supposed to only test a single function in a very controlled way. No network requests, no database accesses.
Our unit tests actually hit the RCITrain database. My thought process was that "If I am testing the Data Access Layer, then I better test that the data is accessed properly".
As a consequence, you'll notice that after every test that creates something new in the database, there is a cleanup section to clear all the things that test created. Do you best to follow the same template.

Querying the Database

We were not always making raw SQL queries to the database. We actulally started out using Microsoft's Entity Framework ORM. Once setup, it makes accessing the database intiuitive. The syntax for accessing rows in a table resembles that of accessing a C# list for example. This is all well and good until you need to modify the database in some manner.
I never got around to really mastering Entity Framework. Making schema changes was always a hassle. I doubt any future maintainers working on this project would want to deal with Entity Framework as well.
So, I switched to using Dapper. Dapper does much less than Entity Framework does and requires 0 knowledge other than C# and SQL. You write your sql queries, send them to the database and get your results back. It is as simple as that. No weird setup. No hours wasted trying to figure out Entity Framework migrations (I still don't understand what these are .__.).

Exception Handling

  • In the Data Access Layer (DAL): If I know a specific type of exception might be thrown (e.g. For methods that expect exactly one result and use .Single(), I catch InvalidOperationException, which will be thrown when there are either many or no results), I'll catch it and deal with it. Dealing with it means (a) performing some other action that will fix the problem or (b) wrapping the exception in a custom exception (e.g. UserNotFoundException) and throwing that.
  • In the Services: If I know a DAL method can throw a custom Exception (e.g UserNotFoundException), I catch that, log and either throw or fix the issue if possible. I also always wrap EVERY call in a try/catch for the general exception type, log it and rethrow it.
  • Controllers: I don't think I do any exception handling here.
  • ExceptionFilter: Logs any unhandled exceptions (in case something was missed)

The result is that there are two types of errors:
(1) Error cases I KNOW about. These are caught using Custom Exceptions and handled correctly.
(2) Error cases I DON'T KNOW about. I log these and let the application error out. The logs will give me enough information to identify the error and possibly fix it, thus making it part of (1).

project-phoenix's People

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

project-phoenix's Issues

Site navigation

  • Improve nav bar
  • Provide ability to navigate back to Dashboard.
  • Make dropdowns consistent and aesthetically pleasing.

Housecleaning

  • Move out helper functions from controllers to services
  • Remove unnecessary using statements
  • Clean up code in general - dust, mop, vacuum

Checkout Subsystem

  • View - essentially same as RCIInput, with ability to add fines.
  • Accessed via button on Dashboard.
  • DB - create fines column in Damages table. Damages entered by resident during check-in will have a null value for fine. A fine that is added by RA then "deleted" by RD will be set to $0.00.
  • Signatures - both Resident and RA will sign on RA's system.
  • Later feature: add option for improper checkout on signing page.

Search on Dashboard broken

  • With the introduction of the UI changes, the search field on the Dashboard no longer works, due to the additional text "Checkout" and "Swap Furniture".
  • When a search is entered, a bunch of blocks that just say "Checkout" and/or "Swap Furniture" populate the dashboard, as well as the actually desired search query

Electronic Signature on Check-in - Resident, RA, and RD

  • View - allows user to input signature and submit
  • Resident signs on their system; RA signs on RA's system; RD on RD's system
  • Once RD signs, RCIInput fields become un-editable.
  • Changes must be reflected in db - perhaps a column in RCI table that indicates SignedByResident and SignedByRA, etc. Or other method.
  • Electronic signature input will be: Gordon username; check this.
  • Investigate legal issues behind electronic signatures.

Photo Upload on Checkout

  • Enable RD/RA users to upload photos when they assign a charge during checkout, in order to document what the Resident is being charged for.
  • This will look very similar to photo upload during the RCI input use cases.
  • It involve adding a new column to the Fine table, which will be something like DamageImagePath
  • Do we want an image modal for each fine? That may be excessive. Perhaps just decently sized images instead of thumbnails.

Generate RCI's on RA log in

  • Generate the whole building's RCI's upon the first login of any RA in the building.
  • Every time when an RA logs in, check if everyone in the building already has an RCI. If not, generate one for each of who has not had one.
  • In order to not generate duplicated RCI's, check to make sure creation date of the latest RCI is always later than the latest room RCI (of each person).

Filtering on Dashboard

  • Allow RD/RA to search for residents.
  • Filter by Room/Resident, or determine other way to filter.

RD select all RCIs for check in

  • Enable an RD to select all RCI's and mark them as "signed"
  • In db, check if a certain RCI has already been signed by the RD and only update the ones that have not yet been signed
  • In UI, show a grayed-out or something clearer to designate that the RCI has already been signed.

Common area signature

  • We need to figure out common area signatures on check-in and checkout.
  • We are planning to follow the current system, and provide signature fields for all residents of a given apartment.
    • To find out who is in an apartment, we will have to do a query based on who has the particular room number.

RCI generation logic

  • When a user logs in, the HomeController checks if any current RCI's exist for user's most recent room and building, as indicated by RoomAssign table
  • If no RCI exists, generate a new one.
  • If user is in an apartment, also check for a current common area RCI. If none, generate a new one.
    Note: we need to think about the case of a common area RCI for someone who moves into/out of an apartment mid-way through the semester. Do they need to fill it out again? Will one be generated for them?

Testing

  • Implement unit tests and other testing methods
  • Cover all the use cases we have implemented thus far.

Set up test data

  • Contact CTS to set up test users for different roles - apartment resident, RA, RD, admin?
  • Set up more RCIs (but once RCI generation is figured out, this would be unnecessary)

Allow empty password

  • Before calling IsValidUser() in LoginController, set a null password to an empty string

Security cleanup

  • The private key is not very secure.
  • I think we need to relocate the value of the key?

Storing Images upon RCI Input

  • Figure out how to store images

  • Image gets uploaded and shown as a thumbnail in the DOM.
  • With an AJAX call, image gets saved to server and the resulting filepath gets saved to the db in a new entry in the Damage table.

Photo upload not working consistently

  • Initially, the bug was that nothing seemed to be happening when photo upload is called on Safari.
  • In fixing that, the behavior has become inconsistent - when photos are uploaded and someone tries to open the modal, it will not always open on the correct picture.
  • I think this is because of the way I set the click handlers on the openModal and the index being passed.

Ability to delete images

Allow users to delete an image once they have uploaded it.
This will involve a call to the db to delete the entry that contains the damage image.

Chrome Stay/Leave Behavior

  • On Chrome, when the site is live it was demonstrating buggy behavior when the user tries to leave the RCIInput page.

Prefill RCI

  • Dearly beloved, we are gathered here today to tackle everyone's favorite use case: PREFILL RCI's.

Authorization

  • Research on how to do authorization
  • Add fields to JWT tokens
  • Applying authorization filters to controllers
  • Instead of applying filters, we used controller logic to determine which view gets displayed for RA and RD.

Photo compression

  • Figure out the specifics on photo size.
  • Apparently there is a limit on photos, as Adam was not able to add a picture bigger than 21 MB, but where is this set?

UI - Login, Dashboard, RCIInput

  • Improve UI design for Login, Dashboard page, and RCIInput which are relatively set.
  • Implement necessary css and javascript
    • Mobile first
    • Gordon branding

Admin

  • Create admin functionality, so that if certain users with admin privileges log in, they can:
    • All past RCI's - how to organize these? By year?
    • Edit any RCI at any time

Gordon Branding

  • Revisit the notion of branding, to align better with other Gordon web apps
  • See possible mock ups here

Get HTTPS

Currently we are sending over http. This needs to change to https, stat.

Auto save

  • Allow for auto saving on both RCI input and checkout use cases.
  • We tried this on reload, but it caused some weird behavior (#49) .

Unit tests

  • Identify and implement possible unit tests for controllers
  • For many tests, this will involve updating/installing packages in the Phoenix.Tests project, as they do not automatically mirror those in Phoenix projects.

Adjust export fines spreadsheet

  • Meet with Marta to get clarification on fines vs. charges - do we want separate spreadsheets?
  • Slightly related - who should receive emails when?

RCI State

First: Have an rci reflect its correct state when you click on it from the dashboard.
Second: Have some visual clue on the dashboard as to what state an rci is in.

States and what someone might see when they click on an rci from the dashboard:

RCI_UNSIGNED:

  • Resident sees: RciInput View
  • RA sees: RciInput View
  • RD sees: RciInput View

RCI_SIGNGED_BY_RES_CHECKIN

  • Resident sees: RciInput View
  • RA sees: RciInput View
  • RD sees: RciInput View

RCI_SIGNGED_BY_RA_CHECKIN

  • Resident sees: RciReviewCheckin View
  • RA sees: RciReviewCheckin View
  • RD sees: RciInput View

RCI_SIGNGED_BY_RD_CHECKIN

  • Resident sees: RciReviewCheckin View
  • RA sees: RciCheckout View
  • RD sees: RciCheckout View

RCI_SIGNED_BY_RES_CHECKOUT

  • Resident sees: RciReviewCheckout View
  • RA sees: RciCheckout View
  • RD sees: RciCheckout View

RCI_SIGNED_BY_RA_CHECKOUT

  • Resident sees: RciReviewCheckout View
  • RA sees: RciCheckout View RciReviewCheckout View
  • RD sees: RciCheckout View

RCI_COMPLETE

  • Resident sees: RciReviewCheckout View
  • RA sees: RciReviewCheckout View
  • RD sees: RciReviewCheckout View

Let me know if you disagree/ have comments/ questions etc...

Custom auth filters

  • Instead of all the redirects in the controllers, we can implement custom authorization filters
  • In this issue, we should also take care of an admin auth filter, which would allow the admin to see all residents.
    • Perhaps we will want to look into more sorting options in that case? Like ability to sort by building or something? It could get overwhelming to have so many residents.
    • Admin should also be able to see past RCI's.

Export Fines

  • Gathers fines from db into .csv file
  • Accessed via RD's dashboard
  • To start: all RCI's for this past session. We can figure out selectivity later.
    • To get at specific session, add Session col to RCI table. Reference Session table for Session dates. Eze already wrote this code for Gordon360. 🙆

Populate correct components

  • Using the old RCI's given to us from MC, implement logic to check user's building and create corresponding component upon RCI generation

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.