Challenge Overview
Project Background
Our customer has a legacy app built in 1998 and it’s time to re-write this application to a modern web app. For this project, we are going to rewrite a small part of the application called FOBO Worksheet.Challenge Objectives
For the purpose of this challenge, we need the community to help integrate the API with the prototype previously built with Angular 7 / HTML5 / CSS, so that we can have the final working application.Technology Stack
- .NET 4.5.2
- SQL
- Docker
- Sybase 15.7
- REST
- Angular 7
- HTML5
- Javascript
- Bootstrap
- CSS
Challenge Scope
All screens from the prototype are in scope of this integration challenge.General Requirements
- The prototype must be fully integrated with the API so that all data comes from the backend. Local json files and all other files that are no longer needed should be removed from the prototype code.
- The main content should have fluid width to fill all available space, minimum supported resolution: 1366 * 768
- Pagination should work
- Must use Angular 7 and follow the provided design
- The pages should clearly indicate invalid input data to users, for example: if user tries to submit a page without providing a required text field, the textbox should be highlighted with an error message. Do NOT use browser alert for errors.
- Must follow Angular best coding practices
- You are expected to create a detailed README file including information on how to setup, run and verify your application.
Individual requirements
See below for more details on screens that are supposed to be integrated in this challenge.Selection Criteria Screen
- The drop down fields in the filter panel will use the following endpoints to get values from the backend:
- System Source: GET /systemSource
- Product Types: GET /productType
- For the tabs on the right side, you will call the following endpoint to get list of business units from backend based on the bu_type_cd (decided by tab name):
- GET /businessUnit?buTypeCd=:bu_type_cd
- The selected business unit will populate into the Business Unit field in the filter panel on the left side
- The root of the tree view shows the name of the selected Business Unit, and the tree view will be populated using records returned by the following endpoint:
- GET /book?bu=:bu_name
- About the fields in the filter panel, here are some more details:
- System Source: this is populated based on the values returned by the API
- Profit and Loss: text field with a default value of 2, must be integer
- Present Value: text field with a default value of 2, must be integer
- Product Types: this will open in a new pop up showing the list of product types retrieved from backend
- Business Unit is a readonly field, and value is auto populated based on the value you select on the right panel.
- The right panel has many different tabs, for each tab, the list of values come from the API response as mentioned above. One of the tabs will be in active / selected mode by default and the 1st row in the tab is selected (and the value of this selected row will be populated into the Business Unit field in the leftmost panel).
- The Product Type Selection popup allows users to check which product types to select, and whether it’s Include or Exclude, when user clicks OK to dismiss the product type selection pop up, main screen will be updated:
- The section below the “Product Types” control in leftmost panel will show the list of selected product types
- One of the Include / Exclude buttons will be shown in active state based on the selection in the product type selection pop up
- Profiles tab is out of scope and just make it disabled
- Profiles section on bottom right corner of screen is out of scope, just implement the buttons as disabled
- For the buttons on top right corner:
- Clicking the OK button will call the POST /bucCriteriaLine endpoint to insert records into the database and navigate to the next screen - Summary screen
- Make Close button disabled
- The Clear Exclude button will clear the product types if they are in Exclude mode
Summary Screen
The data for this screen comes from the response of this endpoint:GET /bookSummary?uid=:uid&pageSize=:pageSize&offset=:offset
Here are a bit more details about the screen:
- On clicking the top left logo it should go back to the Selection Criteria page (same applies to the other screens below)
- There’s a Refresh button on the right side of the page, it’s in disabled state by default. When any of the values for P&L, PV and BreaksOnly criteria changes the button should be enabled, and clicking on it will trigger the following actions in sequence, same works for the other pages with a Refresh button:
- Call POST /bucCriteriaLine to insert new records into database based on the new values, other parameters should still come from the previous Selectoin Criteria page.
- Call GET /bookSummary?uid=:uid&pageSize=:pageSize&offset=:offset to get latest data and show it on the UI
- Here are the details about the table:
- Row one is a summary row, just sum up the values of all numeric columns
- For other rows, here’s the mapping from table columns to json fields:
- Books -> trading_book
- Description -> description
- Breaks -> no_brk
- W\Reason -> no_brk_wd
- Matched -> no_match
- Position -> position
- Price -> price
- P&L -> pandl
- PV -> pv
- Hugo Search -> hugo_code, and searching by hugo will filter rows based on hugo_code column
- Each non-zero break value on Summary screen needs to be a hyperlink, when clicked it will navigate to the Details Screen with the rows that belong to this summary group shown on the Details screen.
Details Screen
- The data on this screen comes from this API call:
- GET /bookDetail?uid=:uid&pageSize=:pageSize&offset=:offset
- About pagination option on details screen, there should be an extra option to show All rows (missing in prototype)
- On clicking the top left logo it should go back to the Selection Criteria page
- Refresh button works the same as Summary Screen
- Save Reason button is disabled by default, but when user clicks the Reason field (note that the Reason drop down should be editable only if there is a break, i.e. breaks columns from Summary page is not 0), a dropdown is shown for users to pick a value, then Save Reason is enabled and upon clicking it the reason is saved to backend by calling the following endpoint:
- PUT /bookDetail
- Here’s the mapping from table columns to json fields for the main table (on top):
- Books -> centre
- Hugo -> hugo_code
- Description -> description
- Currency -> ccy
- Position -> posn_diff
- Price -> price_diff
- P&L -> pandl_diff
- PV -> pv_diff
- Age -> posn_age_break
- Details -> narrative
- Updated By -> last_upd_username
- Updated Date -> last_upd_date
- Source -> rec_source
- Here’s the mapping for Details tab at the bottom:
- ISIN -> isin
- Ticker (RIC) -> ticker
- Multiplier -> multi
- Pool Factor -> pool_factor
- Factor -> fctr
- Product Type -> prod_type and prod_type_desc
- Ticker (BBG) -> ticker_code
- For Source, Position, Price, P&L and PV on the right side, mappings are as below (left to right, top to bottom):
- fo_source, fo_posn, fo_price, fo_pandl, fo_value
- bo_source, bo_posn, bo_price, bo_pandl, bo_value
- posn_diff, price_diff, pandl_diff, pv_diff
- posn_age_break, price_age_break, pv_age_break
- Data for ageing tab comes from GET /bookDetail, and here’s the mapping for the Ageing tab at the bottom:
- COB (design is wrong, should be COB instead of CDB) -> dt_loaded
- Position FTS -> fo_posn
- Position NTPA -> bo_posn
- Price FTS -> fo_price
- Price NTPA -> bo_price
- P&L FTS -> fo_panl
- P&L NTPA -> bo_panl
- PV FTS -> fo_value
- PV NTPA -> bo_value
- Comment -> narrative
- Last Updated by -> last_upd_username
- Last Updated -> last_upd_date
- Data for feeds tab comes from GET /bookDetail and the mapping is very straightforward. Please do note that each feed section may have more than 1 row though.
Break Reason Screen
- The break reason related operations on this page will use the /breakReason endpoints.
- On clicking the top left logo it should go back to the Selection Criteria page.
- Refresh button works the same as Summary Screen.
- When a row in the top table is clicked (in selected mode), the bottom shows the records from the main-data.json whose narrative column matches the code of that reason, the mapping is straightforward:
- Hugo -> hugo_code
- Description -> description
- Currency -> ccy
- Position -> posn_diff
- Price -> price_diff
- P&L -> panl_diff
- PV -> pv_diff
- Reason -> narrative
- Source -> rec_source (the design is wrong)
Product Type Screen
- On clicking the top left logo it should go back to the Selection Criteria page
- Refresh button works the same as Summary Screen
- Product type values also come from the same api call we used for the Selection Criteria page
- Mapping from top table column to json fields should be straightforward except for Count, which would the number of records whose prod_type column matches the type field of the product type
- When a row in the top table’s filter field is checked, the bottom shows the records whose prod_type column matches the type of the row. If multiple rows are being filtered the bottom section shows a union of all such records. The mapping is straightforward:
- Hugo -> hugo_code
- Description -> description
- Currency -> ccy
- Position -> posn_diff
- Price -> price_diff
- P&L -> panl_diff
- PV -> pv_diff
- Reason -> narrative
- Source -> rec_source (the design is wrong)
Reports Screen - All Details
This screen simply shows the data the same api call we used for details screen, here’s the mapping:- Position at CCB -> dt_loaded
- Database: leave empty
- System: hardcode to “Polar”
- User ID: leave empty
- Printed: current date time
- For the table, we need to group records by centre and ccy column, and then for each of the group, here’s the mapping:
- Hugo Code -> hugo_code
- Description -> description
- Prod Code -> prod_code
- Prod Cat -> product_category
- Ticker -> ticker_code
- Position -> posn_diff
- P&L -> pandl_diff
- PV -> pv_diff
- Price -> price_diff
- Position FO -> fo_posn
- Position BO -> bo_posn
- P&L FO -> fo_panl
- P&L BO -> bo_panl
- PV FO -> fo_value
- PV BO -> bo_value
- Price FO -> fo_price
- Price BO -> bo_price
- rec_source
Reports Screen - Posn rec with Narrative
This screen simply shows the data the same api call we used for details screen, here’s the mapping:- Position at CCB -> dt_loaded
- Database: leave empty
- System: hardcode to “Polar”
- User ID: leave empty
- Printed: current date time
- For the table, we need to group records by centre and ccy column, and then for each of the group, here’s the mapping:
- Hugo Code -> hugo_code
- Description -> description
- Prod Code -> prod_code
- Prod Cat -> product_category
- Ticker -> ticker_code
- BO Posn -> bo_posn
- FO Posn -> fo_posn
- Posn Diff -> posn_diff
- Age -> posn_age_break
- Narrative -> narrative
- Upd User -> last_upd_username
- Upd Date -> last_upd_date
- rec_source
HTML Requirements
- HTML should be valid HTML5 compliant.
- Provide comments on the page elements to give clear explanation of the code usage. The goal is to help future developers understand the code.
- Please use clean INDENTATION for all HTML code so future developers can follow the code.
- All HTML code naming should not have any conflicts or errors.
- Element and Attribute names should be in lowercase and use a "-" or camel naming to separate multiple-word classes (i.e.. "main-content", or "mainContent)
- Use semantically correct tags- use H tags for headers, etc. Use strong and em tags instead of bold and italic tags.
- No inline CSS styles- all styles must be placed in an external stylesheet.
- Validate your code- reviewers may accept minor validation errors, but please comment your reason for any validation errors. Use the validators listed in the scorecard.
Code Requirements
- Provide comments on the CSS code. We need CSS comments to give a clear explanation of the code usage. The goal is to help future developers understand the code.
- Please use clean INDENTATION for all CSS so developers can follow the code.
- Do not create a single .css/.scss file for the whole app. Each component should have its own stylesheet file.
- Ensure that there are no lint errors.
- All CSS naming should not have any conflicts.
- You’re free to choose between CSS & SCSS but you need to use flex instead of float.
- Follow a clean folder structure.
- Use CSS3 Media Queries to load different styles for each page and don't build different page for different device/layout.
- Use CSS to space out objects, not clear/transparent images (GIFs or PNGs) and use proper structural CSS to lay out your page.
- Make sure npm run build works without any errors.
Javascript Requirements
- All JavaScript must not have a copyright by a third party. You are encouraged to use your own scripts, or scripts that are free, publicly available and do not have copyright statements or author recognition requirements anywhere in the code.
- Use typescript and linter for code quality
Licenses & Attribution
- Third-party assets used to build your item must be properly licensed or free for commercial use. MIT, some modified BSD, Apache 2 licenses are ok, but if a library is not commercial friendly you need to get our approval first.
- Sufficient information regarding third-party assets must be present in your documentation. This includes the author, license info and a direct link to the asset online.
Browser Requirements
Windows: IE 11+, Edge, Chrome Latest, Firefox LatestMac: Safari Latest, Chrome Latest, Firefox Latest
Documentation
Register to download the following documents we provided in the forum- API Code
- Prototype Code
Final Submission Guidelines
What To Submit
- Full code that covers all the requirements.
- A detailed README file in markdown format including information on how to configure, build and and run your application.
- A verification document in markdown format that shows how to verify your submission. Note that a video is NOT acceptable for the purpose of this.