This is the user facing portion of the Generix Data Clearinghouse. It is designed to simplify tasks on our system that can be challenging for data producers and data consumers alike.
to get started, make sure you have npm and Angular installed. This app is built with Angular version 7.2.5.
npm install -g @angular/cli
Fork and clone a repo and then install all the necessary dependencies in package.json.
npm install
If you run into dependency problems you can't resolve, try installing an older version of @angular/cli. This app has been successfully deployed with Angular versions 7.2.5 and 7.2.15.
To run a development server, use the ng serve
command and open your preferred browser to localhost:4200
Once you are logged into the server, you can find a clone of the repository at /home/clearinghouse/env/generix-ui/generix-ui
.
Pull your changes and run the following build command:
npm install
sudo ng build --prod --base-href /generix-ui/
The build target directory is configured in angular.json to default to /var/www/html/generix-ui/
. In order for the resources to be loaded correctly, the base href needs to be set to /generix-ui/
. This can either be done with the --base-href
flag as demonstrated above or you can manually change it in the index.html generated by the build command.
Note that everything in the build target directory will be deleted!
The --prod directive above configures the UI with the "prod" environment, which is configured via src/environments/environment.prod.ts
If there is not an .htaccess file in the build target directory, a new one will need to be generated for the page to load. paste
the following code below in a new .htaccess file at /var/www/html/generix-ui/
:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ index.html
</IfModule>
generix-ui is structured into modules that pertain to the part of the site the user is visiting. The following diagram is a high level overview of the structure of the app.
app.module
|__ search.module
| |__ search components
|__ upload.module
| |__ upload components
|__ plot.module
| |__ plot components
|__ shared folder
|__ components
|__ services
|__ directives
|__ models
|__ pipes
-
components that do not require services (a simple display page) are declared at the app.module level and can be found in
/src/app/shared/components
. -
each child module has 1 or more service(s) that act as controllers for the components within the modules. All service files can be found in
/src/app/shared/services/
. -
to encourage type safety, patterns that are commonly used throughout the app are stored as ES6 classes and can be found in
/src/app/shared/models
.
The following is a list of some of the core UI dependencies that our app depends on. It is not a comprehensive list but provides the most widely used 3rd party modules throughout the app.
PlotlyJS
PlotlyJS is used to translate data bricks into data vizualizatoins that can be configured and viewed by the user. it is configured to work with angular using angular-plotly.
Angular-plotly provides us with a simple to use <plotly-plot>
component that takes a data
and layout
input. Server calls typically provide data and layout in sebarate objects in the response.
Important: We are currently running angular-plotly at version 1.3.2 to prevent an issue that breaks changes for angular versions below 8. see here for more details.
jQuery
jQuery is installed in order to support custom UI element plugins, namely DataTables and Select2
DataTables
DataTables is used for rendering HTML tables with javascript to add search, filtering, and pagination to large tables. DataTables is currently implemented in generix-ui wihout an
angular wrapper, so $
will need to be imported from jQuery in order to render a table as a DataTable.
It is best to render a table in the AfterViewInit lifecycle hook with an ElementRef provided by angular
as shown below:
import { ElementRef, ViewChild } from '@angular/core';
import * as $ from 'jquery';
import 'datatables.net';
import 'datatables.net-bs4'; // for bootstrap 4 styles
...
export class SomeComponent implements afterViewInit {
@ViewChild('table') private el: ElementRef;
dataTable: any;
ngAfterViewInit() {
this.someService.getSomeData().subscribe(data => {
// assign data to table
const table: any = $(this.el.nativeElement);
this.dataTable = table.DataTable();
});
}
}
Select2
Select2 is used to create comboboxes that populate with data from our system. It
is configured to work with angular using ng2-select2. Select2
elements can be rendered using a <select2>
tag and take an input of options
and data
, where data is
the data with will populate the dropdown and options take the congiguration for the dropdown. The cssImport
input is necessary for select2 to add styles. User selection can be handled using the (valueChanged)
event handler.
<select2
[data]="data"
[options]="options"
[cssImport]="true"
[value]="selectedValue"
(valueChanged)="setValue($event)"
</select2>
>
import { Select2OptionData } from 'ng2-select2';
@Component({...})
export class ComponentWithSelect2 implements OnInit {
selectedValue = '0';
// typical select 2 options config
public options: Select2Options = {
width: '100%' // width is calculated here
containerCssClass: 'select2-custom-container'
// ^ class defined in styles.css, ensures consistent UI with the rest of app
placeholder: 'placeholders can be put here'
// placeholders only work if there is an empty data element in the data file
query: (options: Select2QueryOptions) => {
// this is the option used to get data asynchronously based on user search term
const text = options.term;
this.someService.getSomeData().subscribe((res: any) => {
options.callback(res.results);
})
}
}
public data: Select2OptionData[] = [
{id: '', text: ''}, // necessary to create placeholders and non default selections
{id: '0', text: 'value that the user sees'}
];
}
Important things to note about Select2:
-
if a default placeholder value is specified, the
valueChanged
event is fired initially. In order to prevent unexpected behavior, it is best to check for an id of''
in your event handler. -
Select 2 option data is in the format of
{id: string, text: string}
. WhenvalueChanged
is fired, the$event
released has a property ofvalue
containing the ID of the item. The data itself can be found in$event.data
. -
In order to populate a select2 dropdown with a predefined element, the
[value]
input must be theid
of the desired data item.
Bootstrap 4 and Ngx-Bootstrap
for CSS UI, Bootstrap 4 is used along with ngx-bootstrap for advanced javascript features (e.g modals and tooltips).