Challenge Overview
We currently have an iOS and web application built for the Retail 360 app. The Retail 360 app allows customer service representatives for Hercules to manage customer accounts and view customer information. This challenge will implement a simple web application and web service that can map customer service representative IDs to store IDs and to whether or not the customer service representative has access to the application. This information is going to be available in the Hercules services in the future, but it isn't available now, so we are going to build out a simple admin portal to allow Hercules to manage this information until it's available in their services.
Code
This will be an entirely new application, not based on any existing code. It will be deployed in Heroku and will have these general requirements:
* Must be easily deployed to Heroku (git push heroku master)
* Can use MongoDB for data storage
* Should use the latest Node version available on Heroku
* Can use MIT and BSD licensed 3rd party libraries, but *not* GPL
* Must use GraphQL for the service definitions and UI-to-server messaging
Requirements
* Admins can
* Log in
* Upload spreadsheet
* Modify existing records
* Turn Retail360 access on or off
* Turn admin privileges on or off
Data model
User type:
ntid : String (primary key)
hasRetail360Access : Boolean
isAdmin : Boolean
apiKey : String
storeID : String
Store type:
storeid : String (primary key)
storeAddressLine1 : String
storeAddressLine2 : String
storeZipCode : String
storeCity : String
storeState : String
Code
This will be an entirely new application, not based on any existing code. It will be deployed in Heroku and will have these general requirements:
* Must be easily deployed to Heroku (git push heroku master)
* Can use MongoDB for data storage
* Should use the latest Node version available on Heroku
* Can use MIT and BSD licensed 3rd party libraries, but *not* GPL
* Must use GraphQL for the service definitions and UI-to-server messaging
Requirements
* Admins can
* Log in
* Upload spreadsheet
* Modify existing records
* Turn Retail360 access on or off
* Turn admin privileges on or off
Data model
User type:
ntid : String (primary key)
hasRetail360Access : Boolean
isAdmin : Boolean
apiKey : String
storeID : String
Store type:
storeid : String (primary key)
storeAddressLine1 : String
storeAddressLine2 : String
storeZipCode : String
storeCity : String
storeState : String
GraphQL:
The GraphQL service should allow for these query operations and mutations. The definition of the supported queries is at your discretion. Please make sure to properly use GraphQL features like directives to make the API easy to use and understandable.
Helpful links:
* http://graphql.org/learn/
* https://medium.com/@HurricaneJames/graphql-mutations-fb3ad5ae73c4#.4r9xs9jl6
* https://www.compose.com/articles/using-graphql-with-mongodb/
* Search users
Helpful links:
* http://graphql.org/learn/
* https://medium.com/@HurricaneJames/graphql-mutations-fb3ad5ae73c4#.4r9xs9jl6
* https://www.compose.com/articles/using-graphql-with-mongodb/
* Search users
Allow searching users by different criteria. Filter can be either:
* A list of store IDs, which will return all users for all stores in the list. If an ID isn't found, it will be ignored
* A list of ntids, which will return all users whose IDs match. If an ID isn't found, it will be ignored
In addition to the filter above, we can also filter on access to retail360. This can be done by itself, or in conjunction with either a storeID or ntid filter.
* A flag to return all users with access to retail360, or all users without access to retail360
* Get User a user by their NT ID
* Create User
Creates a new user if API key has admin access.
* Update User
Updates user if API key has admin access. `ntid` can never be updated.
* Delete user
Deletes user if API key has admin access.
* Search stores
Allow searching stores by different criteria. Filter can be either:
* A list of store IDs, which will return all stores whose IDs match. If an ID isn't found, it will be ignored
* A list of zip codes, which returns all stores in the given zip codes. If a zip code isn't found, it will be ignored
* A list of states, which returns all stores in the given states. If a state isn't found, it will be ignored
* Get Store by store ID
* Create Store
Creates store if API key has admin access.
* Update Store
Updates store if API key has admin access. `storeid` can never be updated.
* Delete user
Deletes store if API key has admin access.
Logging:
All changes must be logged by timestamp, ip, current user, and action (eg `ntid=somentid hasRetail360Access=true`)
Administrator UI
The admin interface will be accessible on the "/admin" endpoint of the deployed application. All communication must be done with the backend using the GraphQL services.
Pagination should be used and should be configurable. Expect that there will be hundreds of store locations and thousands of users in the database in the production version of the app.
http://graphql.org/learn/pagination/
Administrator UI definition
Please base the administrator interface in Bootstrap and use this theme to define the UI:
https://bootswatch.com/sandstone/
Administrator login
The admin UI must be protected by a username / password. This username and password can be configured manually through a node command after deployment. The username and password should be stored in the MongoDB, and it's important that an unauthenticated user will be redirected back to the login prompt when they attempt to access any admin UI page. The admin login should set a cookie that expires after 2 weeks so the user gets "remembered" when they come back to the admin UI.
If a user is not an admin, they will be able to view the data, but not make changes.
Administrator API:
Each admin user should have an API token associated with their account that is required for all API calls. We need to ensure that the API is secured.
Routes
Please make sure the routes for the admin UI are sensible. For instance, to edit a user, you can choose something like "/admin/user/{ntid}/edit". Or to view the users table, the path could just be "/admin/users". The same would apply to the storesas well.
Header
The UI should have a header with two navigation buttons or tabs:
* Users
* Stores
View the current database
The main goal of the admin interface will be to view and edit the data in the database. This will be the "Users" tab. Please make the first screen a list of the video records on the database, in a table with these columns:
* NTid
* StoreID
* Check mark for isAdmin
* Check mark for hasRetail360Access
* "Edit" button (blue)
* "Delete" button (red)
The admin user should be able to:
* Search the table on the fly by typing in a text box
* Filter to just certain stores or whether or not the user has retail 360 access
Edit
If the user clicks "Edit" for a specific user, they should go to a new screen with a form where they can edit the data for the video record, including:
* StoreID (from a searchable dropdown)
* Checkbox for is admin
* Check box for has retail 360 access
Delete a user
If the admin clicks "Delete" for a user, we will pop up a modal dialog (skinned with the Bootstrap theme, not browser native) that says "Are you sure you want to delete this user? Yes / No". If the user clicks the "Yes" button, the user will be deleted and the table of users will be refreshed. If the user clicks "No", the modal dialog will be closed.
Add a user
Above the table list of users should be an "Add User" (green) button that allows the user to enter the ntID, storeID, and admin and retail 360 access information on a form and then insert it into the database. The "Add User" screen should have the form details and two buttons - "Cancel" and "Save". If the user clicks "Cancel", they will get redirected back to the list of users. If the user clicks "Save", the record will be saved to the database and the user will get redirected back to the list of users. Make sure that the table shown to the user is always up to date - if a record is added, it should show up in the table.
Stores tab
The "Stores" tab will allow the admin to view and manage the stores, in the same way the users are managed above.
Uploading bulk data
One key feature of the admin UI will be the ability to upload data in CSV format to quickly bulk load in stores and users. There should be an option underneath both Stores and Users to "Bulk import". The bulk import will take in a CSV formatted spreadsheet (format should be defined by the competitor) and will add in the data in the spreadsheet. Any duplicates in the existing data will be updated with the values from the spreadsheet, using the ntid or storeid as the key.
Heroku deploy
Make sure the Heroku deployment information works and that the package.json is up to date with the latest package versions as well. Don't expect the deployment to be anything other than "npm install" / "npm start" locally and "git push heroku master" for Heroku deployment.
Swagger
Please submit a Swagger file for the API details in the app.
Video
No video is required for this challenge.