Kanban style boat management system that allows drag and drop of boat card between docked, inbound, outbound and maintenance swim lanes.
The system aims to solve the following two user stories:
- As a user, they can view a list of boat statuses so they know at a glance what status each boat is in
- As a boat operator, be able to create boat card to describe the status and be able to move them between swim lanes
The following assumptions were used while building the system:
- The boats can be created and removed at any time. There is no limitation on the number of boats that can be on the board at any moment.
- Even though the company might have a finite amount of boats, there is no logic to limit creation to this number.
- There is no need to edit boat names or operators as they can just be deleted and re-created.
- Operators can be assigned to any boat
- Boats use names/nicknames to uniquely identify them on the board, nevertheless boats can have the same name. It is assumed the boat names meaning are known by the operators.
- At a glance provide the number of boats by status to quickly get an overview without having to use the board.
- No authentication/authorization or registration is required. The users all share one system.
The backend is built with Node.JS + Express.JS using TypeScript and follows a RESTful API approach. The endpoints are used using a versioned approach, for example /boats/v1/
The backend is connected to a mongoDB database for persisting boats.
The following endpoints are available once deployed
Property | Description |
---|---|
Endpoint | GET /boats/v1 |
Purpose | Retrieve all boats stored in the database |
Request parameters | None |
Response | A list of all boats stored in the database |
Error handling | If there is an error during the retrieval operation, a "500 Internal Server Error" message will be sent in the response |
The endpoint is currently not used by the frontend. It was implemented for full and future functionality.
Property | Description |
---|---|
Endpoint | GET /boats/v1/:id |
Purpose | Retrieve a single boat from the database by its id |
Request parameters | id - the id of the boat to retrieve |
Response | The boat with the specified id |
Error handling | 404 - If the boat with the given id is not found in the database, a "Boat not found" message will be sent in the response. |
Error handling | 500 - If there is an error during the retrieval operation, a "500 Internal Server Error" message will be sent in the response. |
Property | Description |
---|---|
Endpoint | POST /boats/v1 |
Purpose | Create a new boat |
Request parameters | operator and boat name - the operator and name for the new boat |
Response | The inserted id of the new boat |
Error handling | 400 - If the operator or boat name is missing in the request body, a "Bad Request" message will be sent in the response. |
Error handling | 500 - If there is an error during the creation operation, a "500 Internal Server Error" message will be sent in the response. |
Property | Description |
---|---|
Endpoint | PUT /boats/v1/:id |
Purpose | Update a boat's information |
Request parameters | id - the id of the boat to update; name , operator , status - the new information for the boat |
Response | The id of the updated boat |
Error handling | 400 - If either name, operator, or status is not provided in the request body, a "Bad Request" message will be sent in the response. |
Error handling | 500 - If there is an error during the update operation, a "500 Internal Server Error" message will be sent in the response. |
Property | Description |
---|---|
Endpoint | DELETE /boats/v1/:id |
Purpose | Delete a boat |
Request parameters | id - the id of the boat to delete |
Response | The id of the deleted boat |
Error handling | 400 - If the boat failed to delete, a "Bad Request" message will be sent in the response. |
Error handling | 404 - If the boat with the given id is not found in the database, a "Boat not found" message will be sent in the response. |
Error handling | 500 - If there is an error during the deletion operation, a "500 Internal Server Error" message will be sent in the response. |
The frontend is built with Vite + React using TypeScript. It is mobile-friendly and uses Bootstrap as the CSS framework.
The frontend provides two routes:
/
which is the landing page as well as an overview page of boat statuses./boatStatus
which is the Kanban board style page where boats can be created and managed.
Backend testing uses Jest, a code coverage summary generated by it is shown below. In short, the backend has a 90% code coverage on statements.
View Code Coverage
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---|---|---|---|---|---|
All files | 90.16 | 72.54 | 95 | 87.09 | |
controllers | 100 | 95 | 100 | 100 | |
boats.controller.ts | 100 | 95 | 100 | 100 | 67 |
db | 58.33 | 50 | 0 | 58.33 | |
db.ts | 58.33 | 50 | 0 | 58.33 | 16-21 |
services | 86.27 | 60 | 100 | 81.08 | |
boats.service.ts | 86.27 | 60 | 100 | 81.08 | 11,24,41,59,71-74 |
The frontend does not currently have any automated testing. Nevertheless, the following tests can be considered for each story:
Pre-requisite: Create a boat, status will default to docked.
- Visit the home page
- Navigate to the boat status page
- Assert outbound, inbound, and maintenance columns are empty.
- Assert one item in docked column.
- End Test
Pre-requisite: Create a boat and move it to the outbound lane.
- Visit the home page
- Navigate to the boat status page
- Click Add Boat button
- Fill Boat Name as
Story2
and Operator Name asJohn
- Click Create Boat
- Assert one item in the docked column.
- Assert no items in the inbound column.
- Assert one item in the outbound column.
- Drag boat named
Story2
into the maintenance column. - Assert one item in the maintenance lane.
- Assert no items in the docked lane.
- Trigger page refresh.
- Assert no items in the docked column.
- Assert no items in the inbound column.
- Assert one item in the outbound column.
- Assert one item in the maintenance column.
- End Test
A CI/CD Pipeline has been implemented using GitHub Actions and is part of this repository. The pipeline tests, builds, configures, and triggers a deployment into Digital Ocean.
A high level representation of the pipeline:
The pipeline assumes a mongoDB database has already been deployed on a cloud provider and a connection string is available to be used by the API. A deployment and configuration of a database is considered out of scope.
To run this repository locally follow these steps:
- Deploy a mongoDB
Deploy a mongoDB locally either using docker or a database install. Take note of your port
, username
, and password
.
- Clone this repo
- From a terminal at the top level of the repo run
npm install
this should install all required dependencies. Tested on Node v16 and v18. - Create a .env file under
packages/api/
as follows:
Replace {VARIABLE} with your mongo specific values
DB_CONNECTION_STRING="mongodb://{YOUR_MONGO_USER}:{YOUR_MONGO_PASS}@{MONGO_HOST}:{YOUR_MONGO_PORT}"
DB_NAME="boats"
COLLECTION_NAME="boats"
- Create a .env file under
packages/frontend/
as follows:
Note: assumes API will run on port 8000
VITE_API_BASE_URL="http://{YOUR_HOST}:8000/boats/v1"
- Start the api by running
nodemon
ornpm start
if running with the later you might need to build first by runningnpm build
- Start the frontend by running
npm dev
- Done!