mirror of
https://gitlab.silvrtree.co.uk/martind2000/ft.git
synced 2025-01-25 16:16:16 +00:00
Initial commity
This commit is contained in:
commit
854d0e2a4c
13
.babelrc
Normal file
13
.babelrc
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"sourceMap": true,
|
||||
"moduleIds": false,
|
||||
"comments": false,
|
||||
"compact": false,
|
||||
"code": true,
|
||||
"presets": [ ["es2015", {"loose": true}], "stage-1"],
|
||||
"plugins": [
|
||||
"syntax-flow",
|
||||
"transform-decorators-legacy",
|
||||
"transform-flow-strip-types"
|
||||
]
|
||||
}
|
20
.editorconfig
Normal file
20
.editorconfig
Normal file
@ -0,0 +1,20 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# 2 space indentation
|
||||
[**.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# 4 space indentation
|
||||
[**.html]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
9
.eslintrc.json
Normal file
9
.eslintrc.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./node_modules/aurelia-tools/.eslintrc.json",
|
||||
"rules": {
|
||||
"dot-notation": ["warn"],
|
||||
"no-unused-vars": ["error"],
|
||||
"no-console": ["error"],
|
||||
"no-debugger": ["error"]
|
||||
}
|
||||
}
|
180
.gitignore
vendored
Normal file
180
.gitignore
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Archives template
|
||||
# It's better to unpack these files and commit the raw source because
|
||||
# git has its own built in compression methods.
|
||||
*.7z
|
||||
*.jar
|
||||
*.rar
|
||||
*.zip
|
||||
*.gz
|
||||
*.bzip
|
||||
*.bz2
|
||||
*.xz
|
||||
*.lzma
|
||||
*.cab
|
||||
|
||||
#packing-only formats
|
||||
*.iso
|
||||
*.tar
|
||||
|
||||
#package management formats
|
||||
*.dmg
|
||||
*.xpi
|
||||
*.gem
|
||||
*.egg
|
||||
*.deb
|
||||
*.rpm
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
### Windows template
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
### OSX template
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
||||
|
||||
*.iml
|
||||
|
||||
## Directory-based project format:
|
||||
.idea/
|
||||
# if you remove the above rule, at least ignore the following:
|
||||
|
||||
# User-specific stuff:
|
||||
# .idea/workspace.xml
|
||||
# .idea/tasks.xml
|
||||
# .idea/dictionaries
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
# .idea/dataSources.ids
|
||||
# .idea/dataSources.xml
|
||||
# .idea/sqlDataSources.xml
|
||||
# .idea/dynamic.xml
|
||||
# .idea/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
# .idea/gradle.xml
|
||||
# .idea/libraries
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
# .idea/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
### Node template
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directory
|
||||
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
|
||||
node_modules
|
||||
bower_components
|
||||
|
||||
### VisualStudioCode template
|
||||
.settings
|
||||
|
||||
### Xcode template
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
|
||||
dist
|
27
.jsbeautifyrc
Normal file
27
.jsbeautifyrc
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"indent_size": 4,
|
||||
"html": {
|
||||
"end_with_newline": true,
|
||||
"js": {
|
||||
"indent_size": 2
|
||||
},
|
||||
"css": {
|
||||
"indent_size": 4
|
||||
}
|
||||
},
|
||||
"css": {
|
||||
"preserve_newlines": true,
|
||||
"end_with_newline": true,
|
||||
"space_in_paren": true,
|
||||
"newline_between_rules": true,
|
||||
"space_around_selector_separator": true,
|
||||
"space_around_combinator": true
|
||||
},
|
||||
"js": {
|
||||
"indent_size": 2,
|
||||
"end_with_newline": true,
|
||||
"max_preserve_newlines": 2,
|
||||
"keep_array_indentation": true,
|
||||
"space_in_paren": true
|
||||
}
|
||||
}
|
10
.jsinspectrc
Normal file
10
.jsinspectrc
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"threshold": 30,
|
||||
"identifiers": true,
|
||||
"literals": true,
|
||||
"color": true,
|
||||
"minInstances": 2,
|
||||
"ignore": "test|spec.js|mock|.json",
|
||||
"reporter": "default",
|
||||
"truncate": 100
|
||||
}
|
11
.project
Normal file
11
.project
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>web-platform</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
</natures>
|
||||
</projectDescription>
|
13
.stylelintrc
Normal file
13
.stylelintrc
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "stylelint-config-standard",
|
||||
"rules": {
|
||||
"indentation": 4,
|
||||
"block-no-empty": null,
|
||||
"at-rule-no-vendor-prefix": true,
|
||||
"media-feature-name-no-vendor-prefix": true,
|
||||
"property-no-vendor-prefix": true,
|
||||
"selector-no-vendor-prefix": true,
|
||||
"value-no-vendor-prefix": true,
|
||||
"no-duplicate-selectors": true
|
||||
}
|
||||
}
|
13
.vscode/launch.json
vendored
Normal file
13
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:9000",
|
||||
"webRoot": "${workspaceRoot}"
|
||||
}
|
||||
]
|
||||
}
|
43
.vscode/tasks.json
vendored
Normal file
43
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "0.1.0",
|
||||
"command": "npm",
|
||||
"isShellCommand": true,
|
||||
"showOutput": "always",
|
||||
"suppressTaskName": true,
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "install",
|
||||
"args": ["install"]
|
||||
},
|
||||
{
|
||||
"taskName": "update",
|
||||
"args": ["update"]
|
||||
},
|
||||
{
|
||||
"taskName": "au-build",
|
||||
"args": ["run", "au-build"]
|
||||
},
|
||||
{
|
||||
"taskName": "au-build-dev",
|
||||
"args": ["run", "au-build-dev"]
|
||||
},
|
||||
{
|
||||
"taskName": "au-test",
|
||||
"args": ["run", "au-test"]
|
||||
},
|
||||
{
|
||||
"taskName": "au-run",
|
||||
"args": ["run", "au-run"]
|
||||
},
|
||||
{
|
||||
"taskName": "au-run-dev",
|
||||
"args": ["run","au-run-dev"]
|
||||
},
|
||||
{
|
||||
"taskName": "au-lint-js",
|
||||
"args": ["run", "au-lint-js"]
|
||||
}
|
||||
]
|
||||
}
|
BIN
Dungeon8807construction.gif
Normal file
BIN
Dungeon8807construction.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
98
README.md
Normal file
98
README.md
Normal file
@ -0,0 +1,98 @@
|
||||
# Installation and set up
|
||||
|
||||
## prerequisites
|
||||
1. Nodejs > 6.5
|
||||
2. Git
|
||||
|
||||
## steps
|
||||
1. npm install aurelia-cli -g
|
||||
2. npm install
|
||||
3. ~~copy built assets folder from responsive-web to assets~~
|
||||
4. au run --watch
|
||||
5. au test
|
||||
|
||||
## build details
|
||||
The build creates web-platform.js in the assets/js folder
|
||||
|
||||
## commands
|
||||
|
||||
### `au run`
|
||||
Runs the build process, then starts a local dev server on port 9000 i.e. http://localhost:9000/
|
||||
* Add flag `--js` to only rebuild javascript and markup when developing. This speeds up the rebuild.
|
||||
* ~~Add flag `--alan` to only rebuild css, assets and markup when developing. This speeds up the rebuild.~~
|
||||
* Add flag `--dev` to only transpile js and process markup without linting when developing. This speeds up the rebuild. Run a full build before committing.
|
||||
* Add flag `--docs` to only build the markdown files. This speeds up the documentation.
|
||||
|
||||
Run a full build before committing.
|
||||
|
||||
### `au run --watch`
|
||||
Same as `au run`, but will rebuild when code changes
|
||||
See `au run` task for `--js` and `--docs` and `--dev` flags
|
||||
|
||||
### `au run --watch --use-test-server`
|
||||
Same as `au run --watch --use-test-server`, but will use test server data
|
||||
Type `au help run` for more details
|
||||
|
||||
### `au build`
|
||||
Runs the build process. This includes linting, processing, transpiling and bundling, but not tests
|
||||
See `au run` task for `--js` and `--docs` and `--dev` flags
|
||||
|
||||
### `au test`
|
||||
Runs ALL test suites (*.spec.js files).
|
||||
~~Append a spec filename to this command to run that suite only e.g. `au test src\components\products\common\elements\ft-footnote.spec.js`~~
|
||||
|
||||
### `au test --ui`
|
||||
Runs test suites for UI components using Jasmine and Karma. This will open and close a browser window while running tests.
|
||||
~~Append a spec filename to this command to run that suite only e.g. `au test src\components\products\common\elements\ft-footnote.spec.js --ui`~~
|
||||
NB: Doesn't run the Business Logic (reducer) test suites.
|
||||
|
||||
### `au test --bl`
|
||||
Runs test suites for Business Logic JS files (reducers, value-converters etc) using Jest.
|
||||
~~Append a spec filename to this command to run that suite only e.g. `au test --bl src\components\products\distributions\ft-distributions\lib\en-us-retail\distribution-rate.spec.js`~~
|
||||
NB: These tests run very fast, as they only use NodeJS.
|
||||
|
||||
### `au lint-css`
|
||||
Lints all `scss` files within `src` folder using http://stylelint.io/
|
||||
Configuration is based on [stylelint-config-standard](https://github.com/stylelint/stylelint-config-standard) with custom configuration in `.stylelintrc` file
|
||||
|
||||
### `au lint-js`
|
||||
Uses [ESLint](http://eslint.org/) to lint all `.js` files within `src` and `test` folders.
|
||||
Configuration is on '.eslintrc' and based on the Aurelia eslint configuration.
|
||||
|
||||
### `au lint-markup`
|
||||
Lints html files using [gulp-lintspaces](https://www.npmjs.com/package/gulp-lintspaces)
|
||||
All this really lints is whitespace and indentation, but at the moment there aren't any suitable html snippet linters.
|
||||
|
||||
### `au process-assets`
|
||||
At present, this just copies the bootstrap fonts from the `node_modules` folder to `assets`.
|
||||
In future it will likely copy more font and image files as part of the build.
|
||||
|
||||
### `au process-css`
|
||||
This applies the following to the scss files in the `src` folder:
|
||||
* runs the `lint-css` task
|
||||
* compiles the sass into css
|
||||
* applies [autoprefixer](https://github.com/postcss/autoprefixer) via [postcss](https://github.com/postcss/postcss)
|
||||
* minifies the css via [cssnano](http://cssnano.co/)
|
||||
* generates css sourcemaps
|
||||
* saves the css files and sourcemaps to the `assets` folder
|
||||
|
||||
### `au process-markup`
|
||||
This just applies the `lint-markup` task, before passing the markup off to the bundler
|
||||
|
||||
### `au generate redux-component`
|
||||
This is used to generate a redux component or sub-component. Tests, documentation, sass and (optionally) reducer files are also generated. See `lib/redux-component-base.md` for more details.
|
||||
|
||||
### `au proxy-server`
|
||||
This is used to test the dev assets against the live or dev site.
|
||||
|
||||
Example proxying live site with dev css assets
|
||||
|
||||
au proxy-server --proxy-target http://rcovlnx0188:8202 --dev-css-assets-server http://pattern-library.corp.frk.com/
|
||||
|
||||
Example proxying dev site with dev css assets
|
||||
|
||||
au proxy-server --dev-css-assets-server http://pattern-library.corp.frk.com/
|
||||
|
||||
Example proxying live site with dev js assets, and aurelia etf config
|
||||
|
||||
au proxy-server --override-aurelia-config configuration/etf/main --dev-js-assets-server http://localhost:9000/
|
319
assets/docs.json
Normal file
319
assets/docs.json
Normal file
File diff suppressed because one or more lines are too long
59
assets/js/application_form_download.js
Normal file
59
assets/js/application_form_download.js
Normal file
@ -0,0 +1,59 @@
|
||||
function downloadPdfApplication(data , id, option, site) {
|
||||
var j ;
|
||||
var i ;
|
||||
var val;
|
||||
var fid;
|
||||
var cid;
|
||||
var ls;
|
||||
var fs;
|
||||
var fill;
|
||||
var d;
|
||||
var path;
|
||||
var file;
|
||||
var pdfNumtool;
|
||||
for(j=0; j<=data.length; j++){
|
||||
if(data[j].checked == true){
|
||||
if(site == "OF"){
|
||||
val = data[j].id;
|
||||
i = j+1;
|
||||
fid = document.getElementById('fid'+id+i).value;
|
||||
cid = document.getElementById('cid'+id+i).value;
|
||||
fs = document.getElementById('fs'+id+i).value;
|
||||
ls = document.getElementById('ls'+id+i).value;
|
||||
fill = document.getElementById('fill'+id+i).value;
|
||||
d = document.getElementById('d'+id).value;
|
||||
path = document.getElementById('path'+id+i).value;
|
||||
} else{
|
||||
val = data[j].id;
|
||||
fid = document.getElementById('fid'+id).value;
|
||||
cid = document.getElementById('cid'+id).value;
|
||||
fs = document.getElementById('fs'+id).value;
|
||||
ls = document.getElementById('ls'+id).value;
|
||||
fill = document.getElementById('fill'+id).value;
|
||||
d = document.getElementById('d'+id).value;
|
||||
path = document.getElementById('path'+id).value;
|
||||
}
|
||||
file = d +".pdf";
|
||||
|
||||
//alert(val+fid+cid+fs+ls+fill+d+path);
|
||||
pdfNumtool=document.getElementById('pdfNumtool').value;
|
||||
if(option=="true"){
|
||||
file = "1.pdf";
|
||||
document.downloadAccApp.action = pdfNumtool+"?fid=" + fid + "&cid=" + cid + "&fs=" + fs + "&ls=" + ls + "&fill=1&d=1"+"&path="+path+file;
|
||||
}else{
|
||||
document.downloadAccApp.action = pdfNumtool+"?fid=" + fid + "&cid=" + cid + "&fs=" + fs + "&ls=" + ls + "&fill=" + fill + "&d="+d+"&path="+path+file;
|
||||
}
|
||||
document.downloadAccApp.submit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//fixes chrome browser issue with checked input values
|
||||
$(document).ready(function () {
|
||||
$('form input[type="radio"]').each(function () {
|
||||
if ($(this).attr("data-hack") == 'checked') {
|
||||
$(this).attr('checked', true);
|
||||
}
|
||||
});
|
||||
});
|
2166
assets/js/jquery-ui.js
vendored
Normal file
2166
assets/js/jquery-ui.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
636
assets/js/livesite-modules.js
Normal file
636
assets/js/livesite-modules.js
Normal file
@ -0,0 +1,636 @@
|
||||
'use strict';
|
||||
|
||||
function downloadPdfApplication(data, id, option, site) {
|
||||
var j = void 0;
|
||||
var i = void 0;
|
||||
|
||||
var fid = void 0;
|
||||
var cid = void 0;
|
||||
var ls = void 0;
|
||||
var fs = void 0;
|
||||
var fill = void 0;
|
||||
var d = void 0;
|
||||
var path = void 0;
|
||||
var file = void 0;
|
||||
var pdfNumtool = void 0;
|
||||
for (j = 0; j <= data.length; j++) {
|
||||
if (data[j].checked === true) {
|
||||
if (site === 'OF') {
|
||||
i = j + 1;
|
||||
fid = document.getElementById('fid' + id + i).value;
|
||||
cid = document.getElementById('cid' + id + i).value;
|
||||
fs = document.getElementById('fs' + id + i).value;
|
||||
ls = document.getElementById('ls' + id + i).value;
|
||||
fill = document.getElementById('fill' + id + i).value;
|
||||
d = document.getElementById('d' + id).value;
|
||||
path = document.getElementById('path' + id + i).value;
|
||||
} else {
|
||||
fid = document.getElementById('fid' + id).value;
|
||||
cid = document.getElementById('cid' + id).value;
|
||||
fs = document.getElementById('fs' + id).value;
|
||||
ls = document.getElementById('ls' + id).value;
|
||||
fill = document.getElementById('fill' + id).value;
|
||||
d = document.getElementById('d' + id).value;
|
||||
path = document.getElementById('path' + id).value;
|
||||
}
|
||||
file = d + '.pdf';
|
||||
|
||||
pdfNumtool = document.getElementById('pdfNumtool').value;
|
||||
if (option === 'true') {
|
||||
file = '1.pdf';
|
||||
document.downloadAccApp.action = pdfNumtool + '?fid=' + fid + '&cid=' + cid + '&fs=' + fs + '&ls=' + ls + '&fill=1&d=1' + '&path=' + path + file;
|
||||
} else {
|
||||
document.downloadAccApp.action = pdfNumtool + '?fid=' + fid + '&cid=' + cid + '&fs=' + fs + '&ls=' + ls + '&fill=' + fill + '&d=' + d + '&path=' + path + file;
|
||||
}
|
||||
document.downloadAccApp.submit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('form input[type="radio"]').each(function () {
|
||||
if ($(this).attr('data-hack') === 'checked') {
|
||||
$(this).attr('checked', true);
|
||||
}
|
||||
});
|
||||
});
|
||||
'use strict';
|
||||
|
||||
(function ($, document, window) {
|
||||
var componentName = 'backToTop';
|
||||
var defaults = {
|
||||
offset: '300',
|
||||
duration: '300' };
|
||||
|
||||
function Component(element, options) {
|
||||
this.element = element;
|
||||
this.options = $.extend({}, defaults, options);
|
||||
this._defaults = defaults;
|
||||
this._name = componentName;
|
||||
this.btnTopScroll = $(this.element).find('.back-to-top');
|
||||
this.init();
|
||||
}
|
||||
|
||||
Component.prototype = {
|
||||
init: function init() {
|
||||
var _this = this;
|
||||
|
||||
this.btnTopScroll.click(function (event) {
|
||||
event.preventDefault();
|
||||
_this.scroll(_this._defaults.duration);
|
||||
return false;
|
||||
});
|
||||
$(window).scroll(function () {
|
||||
if ($(window).scrollTop() > _this._defaults.offset) {
|
||||
$('.back-to-top').fadeIn(_this._defaults.duration);
|
||||
} else {
|
||||
$('.back-to-top').fadeOut(_this._defaults.duration);
|
||||
}
|
||||
});
|
||||
},
|
||||
scroll: function scroll(duration) {
|
||||
$('html, body').animate({ scrollTop: 0 }, duration);
|
||||
}
|
||||
};
|
||||
|
||||
$.fn[componentName] = function (options) {
|
||||
return this.each(function () {
|
||||
if (!$.data(this, 'component_' + componentName)) {
|
||||
$.data(this, 'component_' + componentName, new Component(this, options));
|
||||
} else {
|
||||
$.data(this, 'component_' + componentName).scroll();
|
||||
}
|
||||
});
|
||||
};
|
||||
})(jQuery, document, window);
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
function _getActiveSlideTilte() {
|
||||
var slideTitle = $('[data-fti-component="carousel"]').find($('#ft-carousel')).find($('.item.active'))[0].attributes['slide-title'].value;
|
||||
return slideTitle;
|
||||
}
|
||||
|
||||
function _getSlidesNames() {
|
||||
var slides = $('[data-fti-component="carousel"]').find($('#ft-carousel')).find($('.item'));
|
||||
var slideNames = [];
|
||||
for (var i = 0; i < slides.length; i++) {
|
||||
var slide = slides[i];
|
||||
slideNames.push(slide.attributes['slide-title'].value);
|
||||
}
|
||||
return slideNames;
|
||||
}
|
||||
|
||||
function _getActiveSlideNR(activeSlide, slidesNames) {
|
||||
if (!activeSlide || !slidesNames) return;
|
||||
var counter = 0;
|
||||
var activeNR = 0;
|
||||
for (var i = 0; i < slidesNames.length; i++) {
|
||||
var slide = slidesNames[i];
|
||||
if (slide === activeSlide) {
|
||||
activeNR = counter;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
return activeNR;
|
||||
}
|
||||
|
||||
$.fn.carouselNav = function (direction) {
|
||||
if (!direction) return;
|
||||
var activeSlide = _getActiveSlideTilte();
|
||||
var slideNames = _getSlidesNames();
|
||||
var activeSlideNR = _getActiveSlideNR(activeSlide, slideNames);
|
||||
var newSlideNR = void 0;
|
||||
if (direction === 'left') newSlideNR = activeSlideNR - 1;
|
||||
if (direction === 'right') newSlideNR = activeSlideNR + 1;
|
||||
$(this).setNewTitleAndNav(newSlideNR, slideNames);
|
||||
};
|
||||
|
||||
$.fn.setNewTitleAndNav = function (slideNR, slideNames) {
|
||||
if (!slideNames) slideNames = _getSlidesNames();
|
||||
var newSlideNR = parseInt(slideNR, 10);
|
||||
var nrOfSlides = slideNames.length - 1;
|
||||
var nextSlide = parseInt(slideNR, 10) + 1;
|
||||
var prevSlide = parseInt(slideNR, 10) - 1;
|
||||
if (prevSlide < 0) prevSlide = nrOfSlides;
|
||||
if (newSlideNR < 0) {
|
||||
newSlideNR = nrOfSlides;
|
||||
prevSlide--;
|
||||
}
|
||||
if (nextSlide > nrOfSlides) nextSlide = 0;
|
||||
if (newSlideNR > nrOfSlides) {
|
||||
newSlideNR = 0;
|
||||
nextSlide++;
|
||||
}
|
||||
$('#ft-carousel-header').text(slideNames[newSlideNR]);
|
||||
$('#carouselLeft').find('span').text(slideNames[prevSlide]);
|
||||
$('#carouselRight').find('span').text(slideNames[nextSlide]);
|
||||
};
|
||||
})(jQuery);
|
||||
|
||||
(function ($) {
|
||||
$.fn.removeActiveFromOWL = function () {
|
||||
$('li.owl-item.active').removeClass('active');
|
||||
return;
|
||||
};
|
||||
|
||||
$.fn.removeActiveFromRole = function () {
|
||||
var presentationTab = $('li.owl-item').find($('[role="presentation"]'));
|
||||
presentationTab.removeClass('active');
|
||||
return;
|
||||
};
|
||||
|
||||
$.fn.tabDirectionMove = function (owlTabbedOBJ, direction) {
|
||||
var activeTab = owlTabbedOBJ.find('.owl-tab.active');
|
||||
var activeTabName = activeTab.find('a')[0].getAttribute('aria-controls');
|
||||
var activeTabNR = activeTabName.substring(activeTabName.length - 1);
|
||||
var tabOperator = 1;
|
||||
if (direction === 'prev') tabOperator = -1;
|
||||
var directTabName = activeTabName.substring(0, activeTabName.length - 1) + (parseInt(activeTabNR, 10) + parseInt(tabOperator, 10));
|
||||
var directTab = owlTabbedOBJ.find('[aria-controls="' + directTabName + '"]');
|
||||
return directTab;
|
||||
};
|
||||
})(jQuery);
|
||||
|
||||
$('#carouselLeft').click(function () {
|
||||
$(this).carouselNav('left');
|
||||
});
|
||||
|
||||
$('#carouselRight').click(function () {
|
||||
$(this).carouselNav('right');
|
||||
});
|
||||
|
||||
$('[data-target="#ft-carousel"]').click(function () {
|
||||
if (typeof this.attributes['data-slide-to'] !== 'undefined') {
|
||||
var card = this.attributes['data-slide-to'].value;
|
||||
$(this).setNewTitleAndNav(card);
|
||||
}
|
||||
});
|
||||
|
||||
$('#carousel-announcements').owlCarousel({
|
||||
loop: false,
|
||||
margin: 0,
|
||||
responsiveClass: true,
|
||||
navElement: 'i class="ft-icon ft-icon-right-carrot"',
|
||||
navText: '',
|
||||
responsive: {
|
||||
0: {
|
||||
items: 1,
|
||||
dots: true,
|
||||
nav: false
|
||||
},
|
||||
768: {
|
||||
items: 2,
|
||||
dots: false,
|
||||
nav: true
|
||||
},
|
||||
992: {
|
||||
items: 3,
|
||||
dots: false,
|
||||
nav: true
|
||||
},
|
||||
1200: {
|
||||
items: 4,
|
||||
dots: false,
|
||||
nav: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#carousel-announcements-tabbed').owlCarousel({
|
||||
loop: false,
|
||||
margin: 0,
|
||||
responsiveClass: true,
|
||||
navElement: 'i class="tabbed ft-icon ft-icon-right-carrot"',
|
||||
navText: ['', ''],
|
||||
itemElement: 'li',
|
||||
touchDrag: false,
|
||||
mouseDrag: false,
|
||||
responsive: {
|
||||
0: {
|
||||
items: 1,
|
||||
dots: true,
|
||||
nav: false
|
||||
},
|
||||
768: {
|
||||
items: 2,
|
||||
dots: false,
|
||||
nav: true
|
||||
},
|
||||
992: {
|
||||
items: 4,
|
||||
dots: false,
|
||||
nav: true
|
||||
},
|
||||
1200: {
|
||||
items: 4,
|
||||
dots: false,
|
||||
nav: true
|
||||
}
|
||||
},
|
||||
onInitialized: rmActive,
|
||||
onResized: function onResized() {
|
||||
rmActive;
|
||||
$('#carousel-announcements-tabbed').trigger('to.owl.carousel', 0);
|
||||
$('#carousel-announcements-tabbed').find('[aria-controls="tabs-content-1"]').trigger('click');
|
||||
}
|
||||
});
|
||||
|
||||
function rmActive() {
|
||||
$('#carousel-announcements-tabbed').removeActiveFromOWL();
|
||||
}
|
||||
|
||||
$('.owl-next').click(function () {
|
||||
var owlTabbed = $('#carousel-announcements-tabbed');
|
||||
owlTabbed.removeActiveFromOWL();
|
||||
var nextTab = owlTabbed.tabDirectionMove(owlTabbed, 'next');
|
||||
nextTab.trigger('click');
|
||||
});
|
||||
$('.owl-prev').click(function () {
|
||||
var owlTabbed = $('#carousel-announcements-tabbed');
|
||||
owlTabbed.removeActiveFromOWL();
|
||||
var prevTab = owlTabbed.tabDirectionMove(owlTabbed, 'prev');
|
||||
prevTab.trigger('click');
|
||||
});
|
||||
$('li.owl-item').find($('[role="presentation"]')).find($('a')).click(function () {
|
||||
$(this).removeActiveFromRole();
|
||||
});
|
||||
$('#carousel-announcements-tabbed').find('.owl-dots').click(function () {
|
||||
var owlTabbed = $('#carousel-announcements-tabbed');
|
||||
var activatedTab = owlTabbed.find('.owl-item.active');
|
||||
var activatedTabLink = activatedTab.find('a');
|
||||
activatedTabLink.trigger('click');
|
||||
});
|
||||
$('[data-fti-component="carousel"]').setNewTitleAndNav('0');
|
||||
'use strict';
|
||||
|
||||
(function ($, document) {
|
||||
var componentName = 'leavingSite';
|
||||
var defaults = {
|
||||
leavingSiteText: 'Clicking OK below will take you to an independent site. Information and services provided on this independent site are not reviewed by, guaranteed by, or endorsed by Franklin Templeton or its affiliates. Please keep in mind that this independent site\'s terms and conditions, privacy and security policies, or other legal information may be different from those of Franklin Templeton\'s site. Franklin Templeton is not liable for any direct or indirect technical or system issues, consequences, or damages arising from your use of this independent website.',
|
||||
leavingSiteOk: 'OK',
|
||||
leavingSiteCancel: 'Cancel'
|
||||
};
|
||||
|
||||
function Component(element, options) {
|
||||
this.element = element;
|
||||
this.options = $.extend({}, defaults, options);
|
||||
this._defaults = defaults;
|
||||
this._name = componentName;
|
||||
this.btnaExternalLink = $(this.element);
|
||||
this.init();
|
||||
}
|
||||
|
||||
Component.prototype = {
|
||||
init: function init() {
|
||||
this.btnaExternalLink.click(function (e) {
|
||||
e.preventDefault();
|
||||
$('ft-modal')[0].au.controller.viewModel.externalopen(e.target.href);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$.fn[componentName] = function (options) {
|
||||
return this.each(function () {
|
||||
if (!$.data(this, 'component_' + componentName)) {
|
||||
$.data(this, 'component_' + componentName, new Component(this, options));
|
||||
}
|
||||
});
|
||||
};
|
||||
})(jQuery, document);
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
var componentName = 'header';
|
||||
var defaults = {};
|
||||
|
||||
function Component(element, options) {
|
||||
this.element = element;
|
||||
this.options = $.extend({}, defaults, options);
|
||||
this._defaults = defaults;
|
||||
this._name = componentName;
|
||||
this.navTitles = $('#mega').find('.title');
|
||||
this.init();
|
||||
}
|
||||
|
||||
function isMobile() {
|
||||
return $('#navbar-hamburger').is(':visible');
|
||||
}
|
||||
|
||||
Component.prototype = {
|
||||
init: function init() {
|
||||
var _self = this;
|
||||
|
||||
$('ul.nav li.dropdown').on('click touch', function () {
|
||||
if (!$(this).hasClass('open') && !isMobile()) {
|
||||
$(this).addClass('currentlyHovering');
|
||||
|
||||
if ($('#mega').find('li.open').length === 0) {
|
||||
$(this).queue(function () {
|
||||
if ($(this).hasClass('currentlyHovering') && !isMobile()) {
|
||||
$(this).find('.dropdown-toggle').attr('aria-expanded', 'true');
|
||||
$(this).addClass('open').dequeue();
|
||||
if ($(this).hasClass('search')) {
|
||||
$(this).find('input').focus();
|
||||
}
|
||||
} else {
|
||||
$(this).dequeue();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if ($(this).hasClass('currentlyHovering') && !isMobile()) {
|
||||
$(this).find('.dropdown-toggle').attr('aria-expanded', 'true');
|
||||
$('#mega').find('li.open').removeClass('open');
|
||||
$(this).addClass('open').dequeue();
|
||||
if ($(this).hasClass('search')) {
|
||||
$(this).find('input').focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, function () {
|
||||
$(this).removeClass('currentlyHovering');
|
||||
$(this).delay(250).queue(function () {
|
||||
if (!$(this).is(':hover') && !isMobile()) {
|
||||
$(this).removeClass('open').dequeue();
|
||||
$(this).find('.dropdown-toggle').attr('aria-expanded', 'false');
|
||||
} else {
|
||||
$(this).dequeue();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#slide-nav.navbar').after($('<div id="navbar-height-col"></div>'));
|
||||
|
||||
var toggler = '.navbar-toggle';
|
||||
var pagewrapper = '#page-content';
|
||||
var navigationwrapper = '.navbar-header';
|
||||
var slidewidth = '85%';
|
||||
var menuneg = '-100%';
|
||||
var slideneg = '-85%';
|
||||
|
||||
$('#slide-nav').on('click', toggler, function () {
|
||||
var selected = $(this).hasClass('offcanvas-active');
|
||||
|
||||
$('#navbar-close').toggleClass('hidden');
|
||||
$('#navbar-hamburger').toggleClass('hidden');
|
||||
|
||||
$('#offcanvas-menu').stop().animate({
|
||||
left: selected ? menuneg : '0px'
|
||||
});
|
||||
|
||||
$('#navbar-height-col').stop().animate({
|
||||
left: selected ? slideneg : '0px'
|
||||
});
|
||||
|
||||
$(pagewrapper).stop().animate({
|
||||
left: selected ? '0px' : slidewidth
|
||||
});
|
||||
|
||||
$(navigationwrapper).stop().animate({
|
||||
left: selected ? '0px' : slidewidth
|
||||
});
|
||||
|
||||
$(this).toggleClass('offcanvas-active', !selected);
|
||||
$('#offcanvas-menu').toggleClass('offcanvas-active');
|
||||
$('#page-content, .navbar, body, .navbar-header').toggleClass('offcanvas-active');
|
||||
});
|
||||
|
||||
$('form[data-fti-element=sign-in-form]').on('submit', function (e) {
|
||||
var _form = this;
|
||||
e.preventDefault();
|
||||
|
||||
var postData = $(_form).serialize();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/api/account/prelogin',
|
||||
data: postData,
|
||||
dataType: 'json'
|
||||
}).done(function (e2, data) {
|
||||
if (e2.location) {
|
||||
window.location = e2.location;
|
||||
} else {
|
||||
$(_form).attr('action', e2.loginUrl);
|
||||
$(_form).off('submit');
|
||||
$(_form).find('input[name="rememberMe"]')[0].value = postData.indexOf('_rememberMe=on') > -1;
|
||||
$(_form).submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var selected = '#slidemenu, #page-content, body, .navbar, .navbar-header';
|
||||
|
||||
_self.setToggleCollapse();
|
||||
_self.resizeHandler(selected);
|
||||
_self.initTooltip();
|
||||
},
|
||||
setToggleCollapse: function setToggleCollapse() {
|
||||
var _self = this;
|
||||
|
||||
if (isMobile()) {
|
||||
_self.navTitles.data('toggle', 'collapse');
|
||||
|
||||
_self.navTitles.on('click', function (e) {
|
||||
var el = $(e.target);
|
||||
while (!el.is('a')) {
|
||||
el = el.parent();
|
||||
}
|
||||
|
||||
el.next('.collapse').collapse('toggle');
|
||||
el.attr('aria-expanded', function (i, attr) {
|
||||
return attr === 'true' ? 'false' : 'true';
|
||||
});
|
||||
el.parent('.dropdown').toggleClass('open');
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
} else {
|
||||
_self.navTitles.data('toggle', 'disabled');
|
||||
_self.navTitles.off('click');
|
||||
}
|
||||
},
|
||||
resizeHandler: function resizeHandler(selected) {
|
||||
var _self = this;
|
||||
$(window).on('resize', function () {
|
||||
if (!isMobile() && $('.navbar-toggle').is(':hidden')) {
|
||||
$(selected).removeClass('offcanvas-active');
|
||||
}
|
||||
_self.setToggleCollapse();
|
||||
});
|
||||
},
|
||||
|
||||
initTooltip: function initTooltip() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$.fn[componentName] = function (options) {
|
||||
return this.each(function () {
|
||||
if (!$.data(this, 'component_' + componentName)) {
|
||||
$.data(this, 'component_' + componentName, new Component(this, options));
|
||||
}
|
||||
});
|
||||
};
|
||||
})(jQuery);
|
||||
'use strict';
|
||||
|
||||
$(function () {
|
||||
$('*[data-fti-module="header"]').header();
|
||||
$('*[data-fti-module="back-to-top"]').backToTop();
|
||||
$('*[data-fti-module="rich_text"]').rich_text();
|
||||
|
||||
$('*[data-fti-component="tabs"]').tabs();
|
||||
|
||||
$('*[data-fti-component="rich-text"][data-fti-module="tabs"]').tabs();
|
||||
|
||||
$('a.external-link').each(function () {
|
||||
$(this).leavingSite();
|
||||
});
|
||||
});
|
||||
'use strict';
|
||||
|
||||
(function ($, window, document) {
|
||||
var componentName = 'rich_text';
|
||||
|
||||
function Component(element, options) {
|
||||
this.element = element;
|
||||
this.options = options;
|
||||
this._name = componentName;
|
||||
this.init();
|
||||
}
|
||||
|
||||
Component.prototype = {
|
||||
init: function init() {
|
||||
var _this = this;
|
||||
|
||||
$('.collapseAll', this.element).on('click', function () {
|
||||
$('.panel-collapse.in', _this.element).collapse('hide');
|
||||
});
|
||||
$('.expandAll', this.element).on('click', function () {
|
||||
$('.panel-collapse:not(".in")', _this.element).collapse('show');
|
||||
});
|
||||
}
|
||||
};
|
||||
$.fn[componentName] = function (options) {
|
||||
return this.each(function () {
|
||||
if (!$.data(this, 'component_' + componentName)) {
|
||||
$.data(this, 'component_' + componentName, new Component(this, options));
|
||||
} else {
|
||||
$.data(this, 'component_' + componentName).init();
|
||||
}
|
||||
});
|
||||
};
|
||||
})(jQuery, window, document);
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
var componentName = 'tabs';
|
||||
var defaults = {};
|
||||
|
||||
function Component(element, options) {
|
||||
this.element = element;
|
||||
this.options = $.extend({}, defaults, options);
|
||||
this._defaults = defaults;
|
||||
this._name = componentName;
|
||||
|
||||
this.navCollapse = $(this.element).find('.navbar-collapse');
|
||||
this.navTabLinks = $(this.element).find('.nav-tabs-top-level, .nav.nav-pills.nav-stacked').find('a');
|
||||
this.tabContent = $(this.element).find('.tab-content');
|
||||
this.headerTextContainer = $(this.element).find('.mobile-menu + span');
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
Component.prototype = {
|
||||
init: function init() {
|
||||
var _this = this;
|
||||
|
||||
this.setHeaderText();
|
||||
|
||||
if (this.navCollapse.find('ul').hasClass('nav-stacked--no-panel')) {
|
||||
this.adjustContentHeight();
|
||||
|
||||
$(window).on('resize', function () {
|
||||
_this.adjustContentHeight();
|
||||
});
|
||||
}
|
||||
},
|
||||
setHeaderText: function setHeaderText() {
|
||||
var _self = this;
|
||||
|
||||
this.navTabLinks.on('click', function (e) {
|
||||
var elParent = $(this).parent('li');
|
||||
var headerText = $(this).text();
|
||||
|
||||
_self.headerTextContainer.text(headerText);
|
||||
elParent.siblings().removeClass('hidden-xs');
|
||||
elParent.addClass('hidden-xs');
|
||||
|
||||
_self.navCollapse.collapse('hide');
|
||||
});
|
||||
},
|
||||
adjustContentHeight: function adjustContentHeight() {
|
||||
if (this.headerTextContainer.is(':visible')) {
|
||||
$(this.tabContent).css('min-height', 'auto');
|
||||
} else {
|
||||
var navTabsHeight = this.navCollapse.height();
|
||||
var bottomMargin = 5;
|
||||
|
||||
$(this.tabContent).css('min-height', navTabsHeight - bottomMargin);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.fn[componentName] = function (options) {
|
||||
return this.each(function () {
|
||||
if (!$.data(this, 'component_' + componentName)) {
|
||||
$.data(this, 'component_' + componentName, new Component(this, options));
|
||||
}
|
||||
});
|
||||
};
|
||||
})(jQuery);
|
||||
"use strict";
|
||||
//# sourceMappingURL=livesite-modules.js.map
|
1
assets/js/livesite-modules.js.map
Normal file
1
assets/js/livesite-modules.js.map
Normal file
File diff suppressed because one or more lines are too long
189
assets/js/local-test.js
Normal file
189
assets/js/local-test.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/local-test.js.map
Normal file
1
assets/js/local-test.js.map
Normal file
File diff suppressed because one or more lines are too long
34806
assets/js/web-platform-app.js
Normal file
34806
assets/js/web-platform-app.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/web-platform-app.js.map
Normal file
1
assets/js/web-platform-app.js.map
Normal file
File diff suppressed because one or more lines are too long
56562
assets/js/web-platform.js
Normal file
56562
assets/js/web-platform.js
Normal file
File diff suppressed because one or more lines are too long
9
assetsSymLink.bat
Normal file
9
assetsSymLink.bat
Normal file
@ -0,0 +1,9 @@
|
||||
REM Symbolic links solution for web-platform/pattern-lab integration in the same branch
|
||||
REM To create symbolic links as non admin:
|
||||
REM 1. Bring up your run box, type “secpol.msc” and click OK.
|
||||
REM 2. Navigate under the Security Settings \ Local Policies \ User Rights Assignment folder.
|
||||
REM 3. Find “Create symbolic links” and add the Users group to it.
|
||||
REM 4. Restart system.
|
||||
|
||||
mklink /D assets ..\pattern-library\public\assets
|
||||
mklink /D ..\pattern-library\public\data ..\..\web-platform\test\data
|
348
aurelia_project/aurelia.json
Normal file
348
aurelia_project/aurelia.json
Normal file
@ -0,0 +1,348 @@
|
||||
{
|
||||
"name": "web-platform",
|
||||
"source": "cli",
|
||||
"path": "C:\\Users\\bstjohn\\Documents\\eclipse\\GW",
|
||||
"folder": "C:\\Users\\bstjohn\\Documents\\eclipse\\GW",
|
||||
"type": "project:application",
|
||||
"transpiler": {
|
||||
"id": "babel",
|
||||
"displayName": "Babel",
|
||||
"fileExtension": ".js",
|
||||
"options": {
|
||||
"plugins": [
|
||||
"transform-es2015-modules-amd"
|
||||
]
|
||||
},
|
||||
"source": "src/**/*.js"
|
||||
},
|
||||
"livesiteJS": {
|
||||
"id": "babel",
|
||||
"displayName": "Babel",
|
||||
"fileExtension": ".js",
|
||||
"options": {
|
||||
"presets": [
|
||||
"es2015"
|
||||
]
|
||||
},
|
||||
"source": [
|
||||
"src/livesite/**/*.js"
|
||||
],
|
||||
"output": "assets/js"
|
||||
},
|
||||
"jsLinter": {
|
||||
"id": "eslint",
|
||||
"displayName": "ESLint",
|
||||
"fileExtension": ".js",
|
||||
"source": [
|
||||
"src/**/*.js",
|
||||
"test/**/*.js",
|
||||
"!src/**/*.spec.js",
|
||||
"!test/aurelia-karma.js",
|
||||
"!test/**/*.spec.js",
|
||||
"!node_modules/**",
|
||||
"!src/livesite/application_form_download.js"
|
||||
],
|
||||
"testSource": [
|
||||
"aurelia_project/**/*.js",
|
||||
"src/**/*.spec.js",
|
||||
"test/**/*.spec.js",
|
||||
"!node_modules/**"
|
||||
]
|
||||
},
|
||||
"markupProcessor": {
|
||||
"id": "none",
|
||||
"displayName": "None",
|
||||
"fileExtension": ".html",
|
||||
"source": "src/**/*.html"
|
||||
},
|
||||
"cssProcessor": {
|
||||
"id": "sass",
|
||||
"displayName": "SASS",
|
||||
"fileExtension": ".scss",
|
||||
"source": [
|
||||
"src/**/*.scss",
|
||||
"!src/**/lib/*"
|
||||
],
|
||||
"output": "assets/css",
|
||||
"browsers": {
|
||||
"browsers": [
|
||||
"last 1 version"
|
||||
]
|
||||
},
|
||||
"sassIncludePaths": [
|
||||
"./node_modules/bootstrap-sass/assets/stylesheets/"
|
||||
]
|
||||
},
|
||||
"docsProcessor": {
|
||||
"source": [
|
||||
"README.md",
|
||||
"src/**/*.md"
|
||||
],
|
||||
"outputDir": "assets/",
|
||||
"jsonFile": "docs.json",
|
||||
"index": {
|
||||
"index": [
|
||||
{
|
||||
"section": "General",
|
||||
"regex": "^README.md|developer-notes/general|lib"
|
||||
},
|
||||
{
|
||||
"section": "Common Components",
|
||||
"regex": "^components/common"
|
||||
},
|
||||
{
|
||||
"section": "Marketing",
|
||||
"regex": "^components/marketing"
|
||||
},
|
||||
{
|
||||
"section": "Products",
|
||||
"subs": [
|
||||
{
|
||||
"section": "General",
|
||||
"regex": "^developer-notes/products"
|
||||
},
|
||||
{
|
||||
"section": "Common components",
|
||||
"regex": "^components/products/common/elements"
|
||||
},
|
||||
{
|
||||
"section": "Value converters",
|
||||
"regex": "^components/products/common/value-converters"
|
||||
},
|
||||
{
|
||||
"section": "PPSS",
|
||||
"regex": "^components/products/ppss"
|
||||
},
|
||||
{
|
||||
"section": "Overview",
|
||||
"regex": "^components/products/overview"
|
||||
},
|
||||
{
|
||||
"section": "Portfolio",
|
||||
"regex": "^components/products/portfolio"
|
||||
},
|
||||
{
|
||||
"section": "Performance",
|
||||
"regex": "^components/products/performance|components/products/historical"
|
||||
},
|
||||
{
|
||||
"section": "Pricing & Distribution",
|
||||
"regex": "^components/products/pricing-distribution"
|
||||
},
|
||||
{
|
||||
"section": "Price",
|
||||
"regex": "^components/products/pricing"
|
||||
},
|
||||
{
|
||||
"section": "Distributions",
|
||||
"regex": "^components/products/distributions"
|
||||
},
|
||||
{
|
||||
"section": "Documents",
|
||||
"regex": "^components/products/documents"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"section": "Uncategorized"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"assetsProcessor": {
|
||||
"id": "assets",
|
||||
"displayName": "Assets",
|
||||
"clean": "assets",
|
||||
"assets": [
|
||||
{
|
||||
"src": [
|
||||
"./static-assets/js/**"
|
||||
],
|
||||
"dest": "assets/js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"packager": {
|
||||
"src": [
|
||||
"assets/**/*",
|
||||
"coverage/**/*",
|
||||
"test/**/*",
|
||||
"index.html",
|
||||
"docs.html"
|
||||
],
|
||||
"zipfile": "web-platform.zip",
|
||||
"outputDir": "."
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"id": "karma",
|
||||
"displayName": "Karma",
|
||||
"source": "src/**/*.js"
|
||||
},
|
||||
"testFramework": {
|
||||
"id": "jasmine",
|
||||
"displayName": "Jasmine"
|
||||
},
|
||||
"editor": {
|
||||
"id": "atom",
|
||||
"displayName": "Atom"
|
||||
},
|
||||
"platform": {
|
||||
"id": "default",
|
||||
"displayName": "Default",
|
||||
"output": "assets/js"
|
||||
},
|
||||
"workflow": null,
|
||||
"defaultOrCustom": "custom",
|
||||
"paths": {
|
||||
"root": "src"
|
||||
},
|
||||
"build": {
|
||||
"targets": [
|
||||
{
|
||||
"id": "default",
|
||||
"displayName": "Default",
|
||||
"output": "assets/js",
|
||||
"useAbsolutePath": true
|
||||
}
|
||||
],
|
||||
"loader": {
|
||||
"type": "require",
|
||||
"configTarget": "web-platform.js",
|
||||
"config": {
|
||||
"waitSeconds": 60
|
||||
},
|
||||
"includeBundleMetadataInConfig": "auto",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "text",
|
||||
"extensions": [
|
||||
".html",
|
||||
".css"
|
||||
],
|
||||
"stub": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"minify": "stage & prod",
|
||||
"sourcemaps": "dev & stage",
|
||||
"bundleReport": "dev & stage & prod"
|
||||
},
|
||||
"bundles": [
|
||||
{
|
||||
"name": "local-test.js",
|
||||
"source": {
|
||||
"include": [
|
||||
"[**/test/**/*.js]",
|
||||
"**/test/**/*.{css,html}"
|
||||
]
|
||||
},
|
||||
"dependencies": [
|
||||
],
|
||||
"options": {
|
||||
"inject": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "web-platform-app.js",
|
||||
"source": {
|
||||
"include": [
|
||||
"[**/*.js]",
|
||||
"**/*.{css,html}"
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.spec.js",
|
||||
"**/test/**/*.*",
|
||||
"**/livesite/**/*.*"
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"inject": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "web-platform.js",
|
||||
"prepend": [
|
||||
"node_modules/bluebird/js/browser/bluebird.core.js",
|
||||
"node_modules/whatwg-fetch/fetch.js",
|
||||
"node_modules/requirejs/require.js"
|
||||
],
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "text",
|
||||
"path": "../node_modules/requirejs-text/text",
|
||||
"packageRoot": "../"
|
||||
},
|
||||
"aurelia-binding",
|
||||
"aurelia-bootstrapper",
|
||||
"aurelia-dependency-injection",
|
||||
"aurelia-event-aggregator",
|
||||
"aurelia-fetch-client",
|
||||
"aurelia-framework",
|
||||
"aurelia-loader",
|
||||
"aurelia-loader-default",
|
||||
"aurelia-logging",
|
||||
"aurelia-logging-console",
|
||||
"aurelia-metadata",
|
||||
"aurelia-pal",
|
||||
"aurelia-pal-browser",
|
||||
"aurelia-path",
|
||||
"aurelia-polyfills",
|
||||
{
|
||||
"name": "redux",
|
||||
"path": "../node_modules/redux/dist/redux.min"
|
||||
},
|
||||
"aurelia-task-queue",
|
||||
"aurelia-templating",
|
||||
"aurelia-templating-binding",
|
||||
{
|
||||
"name": "aurelia-testing",
|
||||
"path": "../node_modules/aurelia-testing/dist/amd",
|
||||
"main": "aurelia-testing"
|
||||
},
|
||||
{
|
||||
"name": "aurelia-templating-resources",
|
||||
"path": "../node_modules/aurelia-templating-resources/dist/amd",
|
||||
"main": "aurelia-templating-resources"
|
||||
},
|
||||
{
|
||||
"name": "lodash",
|
||||
"path": "../node_modules/lodash",
|
||||
"main": "noop"
|
||||
},
|
||||
"jquery",
|
||||
{
|
||||
"name": "jquery-ui",
|
||||
"path": "../static-assets/js/",
|
||||
"main": "jquery-ui",
|
||||
"deps": ["jquery"],
|
||||
"packageRoot": "../static-assets"
|
||||
},
|
||||
"attrchange",
|
||||
"highcharts",
|
||||
"moment",
|
||||
{
|
||||
"name": "moment-parseformat",
|
||||
"path": "../node_modules/moment-parseformat/dist/moment-parseformat"
|
||||
},
|
||||
"bootstrap-sass",
|
||||
"owl.carousel",
|
||||
"responsive-toolkit"
|
||||
],
|
||||
"options": {
|
||||
"inject": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"sonar": {
|
||||
"id": "sonar-runner",
|
||||
"sonarURL": "http://rcolnx89006:9005",
|
||||
"sonarDB": "jdbc:mysql://rcolnx89006:3306/sonar?useUnicode=true&characterEncoding=utf8",
|
||||
"sonarUser": "sonar",
|
||||
"sonarPasswd": "sonar",
|
||||
"sources": "src/components,src/lib,src/livesite",
|
||||
"exclusions": "**/*.md,**/*.spec.js,**/*.html,**/*.json",
|
||||
"reportPath": "coverage/sonar_report/lcov.info"
|
||||
}
|
||||
}
|
6
aurelia_project/environments/dev.js
Normal file
6
aurelia_project/environments/dev.js
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
debug: true,
|
||||
testing: true,
|
||||
cssRoot: 'http://pattern-library.corp.frk.com'
|
||||
// cssRoot: 'http://localhost:3000'
|
||||
};
|
5
aurelia_project/environments/prod.js
Normal file
5
aurelia_project/environments/prod.js
Normal file
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
debug: false,
|
||||
testing: false,
|
||||
cssRoot: ''
|
||||
};
|
5
aurelia_project/environments/stage.js
Normal file
5
aurelia_project/environments/stage.js
Normal file
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
debug: true,
|
||||
testing: false,
|
||||
cssRoot: ''
|
||||
};
|
44
aurelia_project/generators/attribute.js
Normal file
44
aurelia_project/generators/attribute.js
Normal file
@ -0,0 +1,44 @@
|
||||
import {inject} from 'aurelia-dependency-injection';
|
||||
import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli';
|
||||
|
||||
@inject(Project, CLIOptions, UI)
|
||||
export default class AttributeGenerator {
|
||||
constructor(project, options, ui) {
|
||||
this.project = project;
|
||||
this.options = options;
|
||||
this.ui = ui;
|
||||
}
|
||||
|
||||
execute() {
|
||||
return this.ui
|
||||
.ensureAnswer(this.options.args[0], 'What would you like to call the custom attribute?')
|
||||
.then(name => {
|
||||
let fileName = this.project.makeFileName(name);
|
||||
let className = this.project.makeClassName(name);
|
||||
|
||||
this.project.attributes.add(
|
||||
ProjectItem.text(`${fileName}.js`, this.generateSource(className))
|
||||
);
|
||||
|
||||
return this.project.commitChanges()
|
||||
.then(() => this.ui.log(`Created ${fileName}.`));
|
||||
});
|
||||
}
|
||||
|
||||
generateSource(className) {
|
||||
return `import {inject} from 'aurelia-framework';
|
||||
|
||||
@inject(Element)
|
||||
export class ${className}CustomAttribute {
|
||||
constructor(element) {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
valueChanged(newValue, oldValue) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
4
aurelia_project/generators/attribute.json
Normal file
4
aurelia_project/generators/attribute.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "attribute",
|
||||
"description": "Creates a custom attribute class and places it in the project resources."
|
||||
}
|
41
aurelia_project/generators/binding-behavior.js
Normal file
41
aurelia_project/generators/binding-behavior.js
Normal file
@ -0,0 +1,41 @@
|
||||
import {inject} from 'aurelia-dependency-injection';
|
||||
import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli';
|
||||
|
||||
@inject(Project, CLIOptions, UI)
|
||||
export default class BindingBehaviorGenerator {
|
||||
constructor(project, options, ui) {
|
||||
this.project = project;
|
||||
this.options = options;
|
||||
this.ui = ui;
|
||||
}
|
||||
|
||||
execute() {
|
||||
return this.ui
|
||||
.ensureAnswer(this.options.args[0], 'What would you like to call the binding behavior?')
|
||||
.then(name => {
|
||||
let fileName = this.project.makeFileName(name);
|
||||
let className = this.project.makeClassName(name);
|
||||
|
||||
this.project.bindingBehaviors.add(
|
||||
ProjectItem.text(`${fileName}.js`, this.generateSource(className))
|
||||
);
|
||||
|
||||
return this.project.commitChanges()
|
||||
.then(() => this.ui.log(`Created ${fileName}.`));
|
||||
});
|
||||
}
|
||||
|
||||
generateSource(className) {
|
||||
return `export class ${className}BindingBehavior {
|
||||
bind(binding, source) {
|
||||
|
||||
}
|
||||
|
||||
unbind(binding, source) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
4
aurelia_project/generators/binding-behavior.json
Normal file
4
aurelia_project/generators/binding-behavior.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "binding-behavior",
|
||||
"description": "Creates a binding behavior class and places it in the project resources."
|
||||
}
|
288
aurelia_project/generators/element.js
Normal file
288
aurelia_project/generators/element.js
Normal file
@ -0,0 +1,288 @@
|
||||
import {inject} from 'aurelia-dependency-injection';
|
||||
import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli';
|
||||
import mkdirp from 'mkdirp';
|
||||
|
||||
@inject(Project, CLIOptions, UI)
|
||||
export default class ElementGenerator {
|
||||
constructor(project, options, ui) {
|
||||
this.project = project;
|
||||
this.options = options;
|
||||
this.ui = ui;
|
||||
}
|
||||
|
||||
execute() {
|
||||
return this.ui
|
||||
.ensureAnswer(this.options.args[0], 'What is the name of the element? (in hyphen format. ft- will be prefixed automatically)')
|
||||
.then(name => {
|
||||
let area = 'common/';
|
||||
let subarea = 'elements/';
|
||||
let fileName = this.project.makeFileName(name);
|
||||
let className = this.project.makeClassName(name);
|
||||
// let funcName = this.project.makeFunctionName(name);
|
||||
|
||||
let subDir = (subarea) ? area + '/' + subarea : area;
|
||||
let relDir = 'components/' + subDir + '/ft-' + fileName;
|
||||
let dir = 'src/' + relDir;
|
||||
mkdirp.sync(dir);// quick fix incase parent folder doesn't exist.
|
||||
|
||||
this.project.locations.push(this.project[dir] = ProjectItem.directory(dir));
|
||||
this.project[dir].add(
|
||||
ProjectItem.text(`ft-${fileName}.js`, this.generateComponentJsSource(className)),
|
||||
ProjectItem.text(`ft-${fileName}.spec.js`, this.generateComponentTestJsSource(className, fileName, relDir)),
|
||||
ProjectItem.text(`ft-${fileName}.html`, this.generateComponentHtmlSource(fileName)),
|
||||
ProjectItem.text(`ft-${fileName}.md`, this.generateComponentMdSource('ft-' + fileName)),
|
||||
);
|
||||
|
||||
return this.project.commitChanges()
|
||||
.then(() => this.ui.log(`Created ${fileName}.`));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* source for top level component js
|
||||
* @param className
|
||||
* @returns {string}
|
||||
*/
|
||||
generateComponentJsSource(className) {
|
||||
return `import {bindable, inject} from 'aurelia-framework';
|
||||
|
||||
@inject(Element)
|
||||
export class Ft${className} {
|
||||
@bindable nameThisBindable;
|
||||
|
||||
constructor(element) {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
callBackFunction() {
|
||||
this.element.innerHTML = this.nameThisBindable;
|
||||
}
|
||||
}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for top level component js unit test
|
||||
* @param className
|
||||
* @param fileName
|
||||
* @returns {string}
|
||||
*/
|
||||
generateComponentTestJsSource(className, fileName, relDir) {
|
||||
return `import {StageComponent} from 'aurelia-testing';
|
||||
import {LogManager} from 'aurelia-framework';
|
||||
import {bootstrap} from 'aurelia-bootstrapper';
|
||||
const logger = LogManager.getLogger('${fileName}');
|
||||
|
||||
describe('${className}', () => {
|
||||
let component;
|
||||
let mockStore = {
|
||||
dispatch: function(action) {
|
||||
expect(action.type).toBeDefined();
|
||||
logger.info('actions should have a type: ' + action.type);
|
||||
},
|
||||
subscribe: function(callback) {
|
||||
logger.info('subscription request to the store');
|
||||
}
|
||||
};
|
||||
let beans = { // see configuration/en-us-retail/beans.js for example
|
||||
component: {
|
||||
${className}: []
|
||||
},
|
||||
bean: {
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
component = StageComponent
|
||||
.withResources('${relDir}/ft-${fileName}')
|
||||
.inView('<ft-${fileName} id="test1" fund-id="817"></ft-${fileName}>');
|
||||
component.configure = (aurelia) => {
|
||||
aurelia.container.registerInstance('Store', mockStore);
|
||||
aurelia.container.registerInstance('Beans', beans);
|
||||
aurelia.use.standardConfiguration()
|
||||
.feature('components/common')
|
||||
.feature('components/products/common');
|
||||
};
|
||||
});
|
||||
|
||||
it('should render something', done => {
|
||||
component.create(bootstrap).then(() => {
|
||||
const testElement = document.getElementById('test1');
|
||||
expect(testElement.innerText).toMatch(/replace me/);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
component.dispose();
|
||||
});
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for top level component html
|
||||
* @returns {string}
|
||||
*/
|
||||
generateComponentHtmlSource(fileName) {
|
||||
return `<template>
|
||||
<div>ft-${fileName}: replace me</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for reducer
|
||||
* @param funcName, fileName
|
||||
*/
|
||||
generateReducerJsSource(funcName, fileName) {
|
||||
return `/**
|
||||
* Data Reducer for ${funcName}
|
||||
* Takes site specific json data and creates model for components
|
||||
* after applying business and presentation logic and data mapping
|
||||
*/
|
||||
import {LogManager} from 'aurelia-framework';
|
||||
|
||||
const logger = LogManager.getLogger('${fileName}');
|
||||
|
||||
export function ${funcName}(state, action) {
|
||||
switch (action.type) {
|
||||
case 'CHANGE_ME_TO_PROPER_ACTION_NAME_SUCCESS':
|
||||
logger.debug('Reducing: CHANGE_ME_TO_PROPER_ACTION_NAME_SUCCESS');
|
||||
|
||||
return Object.assign({}, state, {
|
||||
${funcName}: action.data
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for reducer unit test
|
||||
* @param funcName
|
||||
*/
|
||||
generateReducerTestJsSource(funcName, fileName) {
|
||||
return `import {${funcName}} from './${fileName}.reducer';
|
||||
|
||||
describe('${funcName}', () => {
|
||||
it('should return unchanged state if action does not apply', done => {
|
||||
let action = {
|
||||
type: 'ANOTHER_ACTION'
|
||||
};
|
||||
let oldState = {};
|
||||
let newState = ${funcName}(oldState, action, {});
|
||||
expect(newState).toBe(oldState);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return some stuff', done => {
|
||||
let action = {
|
||||
type: 'CHANGE_ME_TO_PROPER_ACTION_NAME_SUCCESS',
|
||||
data: {
|
||||
stuff: 'some stuff'
|
||||
}
|
||||
};
|
||||
let newState = ${funcName}({}, action, {});
|
||||
expect(newState.${funcName}.stuff).toBe('some stuff');
|
||||
done();
|
||||
});
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for reducer
|
||||
* @param funcName, fileName
|
||||
*/
|
||||
generateAppStateReducerJsSource(funcName, fileName) {
|
||||
return `/**
|
||||
* App State Reducer for ${funcName}
|
||||
* Takes application state data and creates model for components
|
||||
*/
|
||||
import {LogManager} from 'aurelia-framework';
|
||||
|
||||
const logger = LogManager.getLogger('${fileName}');
|
||||
|
||||
export function ${funcName}(state, action) {
|
||||
switch (action.type) {
|
||||
case 'SOME_ACTION':
|
||||
logger.debug('Reducing: SOME_ACTION');
|
||||
|
||||
return Object.assign({}, state, {
|
||||
${funcName}: action.data
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for reducer unit test
|
||||
* @param funcName
|
||||
*/
|
||||
generateAppStateReducerTestJsSource(funcName, fileName) {
|
||||
return `import {${funcName}} from './${fileName}.reducer';
|
||||
|
||||
describe('${funcName}', () => {
|
||||
it('should return unchanged state if action does not apply', done => {
|
||||
let action = {
|
||||
type: 'ANOTHER_ACTION'
|
||||
};
|
||||
let oldState = {};
|
||||
let newState = ${funcName}(oldState, action, {});
|
||||
expect(newState).toBe(oldState);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return some stuff', done => {
|
||||
let action = {
|
||||
type: 'SOME_ACTION',
|
||||
data: {
|
||||
stuff: 'some stuff'
|
||||
}
|
||||
};
|
||||
let newState = ${funcName}({}, action, {});
|
||||
expect(newState.${funcName}.stuff).toBe('some stuff');
|
||||
done();
|
||||
});
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate markdown stub
|
||||
* @param fileName
|
||||
* @returns {string}
|
||||
*/
|
||||
generateComponentMdSource(fileName) {
|
||||
return `# ${ fileName }
|
||||
|
||||
## Usage
|
||||
${'```'}html
|
||||
<${ fileName} fund-id="817" cid="uniqueId"></${ fileName}>
|
||||
${'```'}
|
||||
*The cid is guaranteed to be unique to this page even if multiple instances of the component are added to the same page.*
|
||||
|
||||
## Developer notes
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate sass partial stub
|
||||
* @param fileName
|
||||
* @returns {string}
|
||||
*/
|
||||
generateComponentSassSource(fileName, name) {
|
||||
return `
|
||||
// CSS specific to the ${ fileName } component goes here
|
||||
[data-fti-component="${ name }"] {
|
||||
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
4
aurelia_project/generators/element.json
Normal file
4
aurelia_project/generators/element.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "element",
|
||||
"description": "Creates a custom element class and template, placing them in the project resources."
|
||||
}
|
73
aurelia_project/generators/generator.js
Normal file
73
aurelia_project/generators/generator.js
Normal file
@ -0,0 +1,73 @@
|
||||
import {inject} from 'aurelia-dependency-injection';
|
||||
import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli';
|
||||
|
||||
@inject(Project, CLIOptions, UI)
|
||||
export default class GeneratorGenerator {
|
||||
constructor(project, options, ui) {
|
||||
this.project = project;
|
||||
this.options = options;
|
||||
this.ui = ui;
|
||||
}
|
||||
|
||||
execute() {
|
||||
return this.ui
|
||||
.ensureAnswer(this.options.args[0], 'What would you like to call the generator?')
|
||||
.then(name => {
|
||||
let fileName = this.project.makeFileName(name);
|
||||
let className = this.project.makeClassName(name);
|
||||
|
||||
this.project.generators.add(
|
||||
ProjectItem.text(`${fileName}.js`, this.generateSource(className))
|
||||
);
|
||||
|
||||
return this.project.commitChanges()
|
||||
.then(() => this.ui.log(`Created ${fileName}.`));
|
||||
});
|
||||
}
|
||||
|
||||
generateSource(className) {
|
||||
return `import {inject} from 'aurelia-dependency-injection';
|
||||
import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli';
|
||||
|
||||
@inject(Project, CLIOptions, UI)
|
||||
export default class ${className}Generator {
|
||||
constructor(project, options, ui) {
|
||||
this.project = project;
|
||||
this.options = options;
|
||||
this.ui = ui;
|
||||
}
|
||||
|
||||
execute() {
|
||||
return this.ui
|
||||
.ensureAnswer(this.options.args[0], 'What would you like to call the new item?')
|
||||
.then(name => {
|
||||
let fileName = this.project.makeFileName(name);
|
||||
let className = this.project.makeClassName(name);
|
||||
|
||||
this.project.elements.add(
|
||||
ProjectItem.text(\`\${fileName}.js\`, this.generateSource(className))
|
||||
);
|
||||
|
||||
return this.project.commitChanges()
|
||||
.then(() => this.ui.log(\`Created \${fileName}.\`));
|
||||
});
|
||||
}
|
||||
|
||||
generateSource(className) {
|
||||
return \`import {bindable} from 'aurelia-framework';
|
||||
|
||||
export class \${className} {
|
||||
@bindable value;
|
||||
|
||||
valueChanged(newValue, oldValue) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
\`
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
4
aurelia_project/generators/generator.json
Normal file
4
aurelia_project/generators/generator.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "generator",
|
||||
"description": "Creates a generator class and places it in the project generators folder."
|
||||
}
|
355
aurelia_project/generators/redux-component.js
Normal file
355
aurelia_project/generators/redux-component.js
Normal file
@ -0,0 +1,355 @@
|
||||
import {inject} from 'aurelia-dependency-injection';
|
||||
import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli';
|
||||
import mkdirp from 'mkdirp';
|
||||
|
||||
@inject(Project, CLIOptions, UI)
|
||||
export default class ReduxComponentGenerator {
|
||||
constructor(project, options, ui) {
|
||||
this.project = project;
|
||||
this.options = options;
|
||||
this.ui = ui;
|
||||
}
|
||||
|
||||
execute() {
|
||||
return this.ui
|
||||
.ensureAnswer(this.options.args[0], 'What is the name of the redux component? (in hyphen format. ft- will be prefixed automatically)')
|
||||
.then(name => {
|
||||
let area = 'products';
|
||||
this.ui.ensureAnswer(this.options.args[1], 'Which sub area? (blank sub area will add it at the area level)', 'portfolio')
|
||||
.then(subarea => {
|
||||
this.ui.ensureAnswer(this.options.args[2], 'Do you want a site specific data reducer? (Y/N)', 'Y')
|
||||
.then(siteSpecificReducer => {
|
||||
this.ui.ensureAnswer(this.options.args[3], 'Do you want an app state reducer? (Y/N)', 'N')
|
||||
.then(appStateReducer => {
|
||||
let fileName = this.project.makeFileName(name);
|
||||
let className = this.project.makeClassName(name);
|
||||
let funcName = this.project.makeFunctionName(name);
|
||||
let makeSiteSpecificReducer = (siteSpecificReducer.toLowerCase() === 'y');
|
||||
let makeAppStateReducer = (appStateReducer.toLowerCase() === 'y');
|
||||
|
||||
let subDir = (subarea) ? area + '/' + subarea : area;
|
||||
let relDir = 'components/' + subDir + '/ft-' + fileName;
|
||||
let dir = 'src/' + relDir;
|
||||
mkdirp.sync(dir);// quick fix incase parent folder doesn't exist.
|
||||
|
||||
this.project.locations.push(this.project[dir] = ProjectItem.directory(dir));
|
||||
this.project[dir].add(
|
||||
ProjectItem.text(`ft-${fileName}.js`, this.generateComponentJsSource(className)),
|
||||
ProjectItem.text(`ft-${fileName}.spec.js`, this.generateComponentTestJsSource(className, fileName, relDir, funcName)),
|
||||
ProjectItem.text(`ft-${fileName}.html`, this.generateComponentHtmlSource(fileName)),
|
||||
ProjectItem.text(`ft-${fileName}.md`, this.generateComponentMdSource('ft-' + fileName))
|
||||
// ProjectItem.text(`_ft-${fileName}.scss`, this.generateComponentSassSource('ft-' + fileName, name))
|
||||
);
|
||||
|
||||
if (makeSiteSpecificReducer) {
|
||||
let reducerDir = dir + '/lib/en-us-retail';
|
||||
mkdirp.sync(reducerDir);// quick fix incase parent folder doesn't exist.
|
||||
this.project.locations.push(this.project[reducerDir] = ProjectItem.directory(reducerDir));
|
||||
this.project[reducerDir].add(
|
||||
ProjectItem.text(`${fileName}.reducer.js`, this.generateReducerJsSource(funcName, fileName)),
|
||||
ProjectItem.text(`${fileName}.spec.js`, this.generateReducerTestJsSource(funcName, fileName))
|
||||
);
|
||||
}
|
||||
|
||||
if (makeAppStateReducer) {
|
||||
let reducerDirAppState = dir + '/lib';
|
||||
mkdirp.sync(reducerDirAppState);// quick fix incase parent folder doesn't exist.
|
||||
this.project.locations.push(this.project[reducerDirAppState] = ProjectItem.directory(reducerDirAppState));
|
||||
this.project[reducerDirAppState].add(
|
||||
ProjectItem.text(`${fileName}.reducer.js`, this.generateAppStateReducerJsSource(funcName, fileName)),
|
||||
ProjectItem.text(`${fileName}.spec.js`, this.generateAppStateReducerTestJsSource(funcName, fileName))
|
||||
);
|
||||
}
|
||||
|
||||
return this.project.commitChanges()
|
||||
.then(() => this.ui.log(`Created ${fileName}.`));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* source for top level component js
|
||||
* @param className
|
||||
* @returns {string}
|
||||
*/
|
||||
generateComponentJsSource(className) {
|
||||
return `import {inject} from 'aurelia-framework';
|
||||
import {ReduxComponentBase} from '../../../../lib/redux-component-base';
|
||||
//import {getFundState} from '../../lib/map-state-utils';
|
||||
|
||||
@inject('Store', 'Beans', Element)
|
||||
export class Ft${className} extends ReduxComponentBase {
|
||||
populated = false;
|
||||
|
||||
constructor(store, beans, element) {
|
||||
// add logging and integration with the data store
|
||||
super(store);
|
||||
this.fundId = element.getAttribute('fund-id');
|
||||
|
||||
// This is a top level component so we need to initiate the population
|
||||
this.dispatch({
|
||||
type: 'POPULATE_CHANGE_ME_STATE',
|
||||
// beans: beans..., // beans set in configuration for site e.g. configuration/en-us-retail/beans.js
|
||||
fundId: this.fundId
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the state changes.
|
||||
*/
|
||||
mapState(newState) {
|
||||
try {
|
||||
this.logger.debug('mapState()');
|
||||
//let fundState = getFundState(newState, this.fundId);
|
||||
// set component properties from state as appropriate
|
||||
//this.label = newState.products.distributions.label;
|
||||
//this.proximity = fundState.distributions.caveats.proximity;
|
||||
|
||||
// if we get to here without erroring, data has been populated successfully
|
||||
this.populated = true;
|
||||
} catch (e) {
|
||||
// state not populated yet
|
||||
this.populated = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for top level component js unit test
|
||||
* @param className
|
||||
* @param fileName
|
||||
* @returns {string}
|
||||
*/
|
||||
generateComponentTestJsSource(className, fileName, relDir, funcName) {
|
||||
return `import {StageComponent} from 'aurelia-testing';
|
||||
import {bootstrap} from 'aurelia-bootstrapper';
|
||||
import {wait} from '../../../../lib/test-utils.js';
|
||||
|
||||
describe('${className}', () => {
|
||||
let delay = 10;
|
||||
let component;
|
||||
let mockStore = {
|
||||
dispatch: function(action) {
|
||||
expect(action.type).toBeDefined();
|
||||
},
|
||||
subscribe: function(callback) {
|
||||
}
|
||||
};
|
||||
let mockBeans = { // see configuration/en-us-retail/beans.js for example
|
||||
component: {
|
||||
${funcName}: []
|
||||
},
|
||||
bean: {
|
||||
}
|
||||
};
|
||||
let mockAttributes;
|
||||
let mockState;
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(mockStore, 'dispatch');
|
||||
mockAttributes = {};
|
||||
mockState = {};
|
||||
component = StageComponent
|
||||
.withResources('${relDir}/ft-${fileName}')
|
||||
.inView(\`<ft-${fileName} id="test1"></ft-${fileName}>\`);
|
||||
component.configure = (aurelia) => {
|
||||
aurelia.container.registerInstance('Store', mockStore);
|
||||
aurelia.container.registerInstance('Beans', mockBeans);
|
||||
aurelia.use.standardConfiguration();
|
||||
};
|
||||
});
|
||||
|
||||
it('should render something', done => {
|
||||
component.boundTo(mockAttributes);
|
||||
component.create(bootstrap)
|
||||
.then(() => {
|
||||
if (component.viewModel.mapState) {
|
||||
component.viewModel.mapState(mockState);
|
||||
}
|
||||
})
|
||||
.then(wait(delay))
|
||||
.then(() => {
|
||||
const testElement = document.getElementById('test1');
|
||||
expect(testElement.innerText.trim()).toBe('ft-${fileName}: replace me');
|
||||
})
|
||||
.then(done);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
component.dispose();
|
||||
});
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for top level component html
|
||||
* @returns {string}
|
||||
*/
|
||||
generateComponentHtmlSource(fileName) {
|
||||
return `<template>
|
||||
<div>ft-${fileName}: replace me</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for reducer
|
||||
* @param funcName, fileName
|
||||
*/
|
||||
generateReducerJsSource(funcName, fileName) {
|
||||
return `/**
|
||||
* Data Reducer for ${funcName}
|
||||
* Takes site specific json data and creates model for components
|
||||
* after applying business and presentation logic and data mapping
|
||||
*/
|
||||
import {LogManager} from 'aurelia-framework';
|
||||
|
||||
const logger = LogManager.getLogger('${fileName}');
|
||||
|
||||
export function ${funcName}(state, action) {
|
||||
switch (action.type) {
|
||||
case 'CHANGE_ME_TO_PROPER_ACTION_NAME_SUCCESS':
|
||||
logger.debug('Reducing: CHANGE_ME_TO_PROPER_ACTION_NAME_SUCCESS');
|
||||
|
||||
return Object.assign({}, state, {
|
||||
${funcName}: action.data
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for reducer unit test
|
||||
* @param funcName
|
||||
*/
|
||||
generateReducerTestJsSource(funcName, fileName) {
|
||||
return `import {${funcName}} from './${fileName}.reducer';
|
||||
|
||||
describe('${funcName}', () => {
|
||||
it('should return unchanged state if action does not apply', done => {
|
||||
let action = {
|
||||
type: 'ANOTHER_ACTION'
|
||||
};
|
||||
let oldState = {};
|
||||
let newState = ${funcName}(oldState, action, {});
|
||||
expect(newState).toBe(oldState);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return some stuff', done => {
|
||||
let action = {
|
||||
type: 'CHANGE_ME_TO_PROPER_ACTION_NAME_SUCCESS',
|
||||
data: {
|
||||
stuff: 'some stuff'
|
||||
}
|
||||
};
|
||||
let newState = ${funcName}({}, action, {});
|
||||
expect(newState.${funcName}.stuff).toBe('some stuff');
|
||||
done();
|
||||
});
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for reducer
|
||||
* @param funcName, fileName
|
||||
*/
|
||||
generateAppStateReducerJsSource(funcName, fileName) {
|
||||
return `/**
|
||||
* App State Reducer for ${funcName}
|
||||
* Takes application state data and creates model for components
|
||||
*/
|
||||
import {LogManager} from 'aurelia-framework';
|
||||
|
||||
const logger = LogManager.getLogger('${fileName}');
|
||||
|
||||
export function ${funcName}(state, action) {
|
||||
switch (action.type) {
|
||||
case 'SOME_ACTION':
|
||||
logger.debug('Reducing: SOME_ACTION');
|
||||
|
||||
return Object.assign({}, state, {
|
||||
${funcName}: action.data
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* source for reducer unit test
|
||||
* @param funcName
|
||||
*/
|
||||
generateAppStateReducerTestJsSource(funcName, fileName) {
|
||||
return `import {${funcName}} from './${fileName}.reducer';
|
||||
|
||||
describe('${funcName}', () => {
|
||||
it('should return unchanged state if action does not apply', done => {
|
||||
let action = {
|
||||
type: 'ANOTHER_ACTION'
|
||||
};
|
||||
let oldState = {};
|
||||
let newState = ${funcName}(oldState, action, {});
|
||||
expect(newState).toBe(oldState);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return some stuff', done => {
|
||||
let action = {
|
||||
type: 'SOME_ACTION',
|
||||
data: {
|
||||
stuff: 'some stuff'
|
||||
}
|
||||
};
|
||||
let newState = ${funcName}({}, action, {});
|
||||
expect(newState.${funcName}.stuff).toBe('some stuff');
|
||||
done();
|
||||
});
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate markdown stub
|
||||
* @param fileName
|
||||
* @returns {string}
|
||||
*/
|
||||
generateComponentMdSource(fileName) {
|
||||
return `# ${ fileName }
|
||||
|
||||
## Usage
|
||||
${'```'}html
|
||||
<${ fileName} fund-id="817" cid="uniqueId"></${ fileName}>
|
||||
${'```'}
|
||||
*The cid is guaranteed to be unique to this page even if multiple instances of the component are added to the same page.*
|
||||
|
||||
## Developer notes
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate sass partial stub
|
||||
* @param fileName
|
||||
* @returns {string}
|
||||
*/
|
||||
// generateComponentSassSource(fileName, name) {
|
||||
// return `
|
||||
// // CSS specific to the ${ fileName } component goes here
|
||||
// [data-fti-component="${ name }"] {
|
||||
|
||||
// }
|
||||
// `;
|
||||
// }
|
||||
}
|
4
aurelia_project/generators/redux-component.json
Normal file
4
aurelia_project/generators/redux-component.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "redux-component",
|
||||
"description": "Creates all the source files, and tests for a redux component."
|
||||
}
|
41
aurelia_project/generators/task.js
Normal file
41
aurelia_project/generators/task.js
Normal file
@ -0,0 +1,41 @@
|
||||
import {inject} from 'aurelia-dependency-injection';
|
||||
import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli';
|
||||
|
||||
@inject(Project, CLIOptions, UI)
|
||||
export default class TaskGenerator {
|
||||
constructor(project, options, ui) {
|
||||
this.project = project;
|
||||
this.options = options;
|
||||
this.ui = ui;
|
||||
}
|
||||
|
||||
execute() {
|
||||
return this.ui
|
||||
.ensureAnswer(this.options.args[0], 'What would you like to call the task?')
|
||||
.then(name => {
|
||||
let fileName = this.project.makeFileName(name);
|
||||
let functionName = this.project.makeFunctionName(name);
|
||||
|
||||
this.project.tasks.add(
|
||||
ProjectItem.text(`${fileName}.js`, this.generateSource(functionName))
|
||||
);
|
||||
|
||||
return this.project.commitChanges()
|
||||
.then(() => this.ui.log(`Created ${fileName}.`));
|
||||
});
|
||||
}
|
||||
|
||||
generateSource(functionName) {
|
||||
return `import gulp from 'gulp';
|
||||
import changed from 'gulp-changed';
|
||||
import project from '../aurelia.json';
|
||||
|
||||
export default function ${functionName}() {
|
||||
return gulp.src(project.paths.???)
|
||||
.pipe(changed(project.paths.output, {extension: '.???'}))
|
||||
.pipe(gulp.dest(project.paths.output));
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
4
aurelia_project/generators/task.json
Normal file
4
aurelia_project/generators/task.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "task",
|
||||
"description": "Creates a task and places it in the project tasks folder."
|
||||
}
|
41
aurelia_project/generators/value-converter.js
Normal file
41
aurelia_project/generators/value-converter.js
Normal file
@ -0,0 +1,41 @@
|
||||
import {inject} from 'aurelia-dependency-injection';
|
||||
import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli';
|
||||
|
||||
@inject(Project, CLIOptions, UI)
|
||||
export default class ValueConverterGenerator {
|
||||
constructor(project, options, ui) {
|
||||
this.project = project;
|
||||
this.options = options;
|
||||
this.ui = ui;
|
||||
}
|
||||
|
||||
execute() {
|
||||
return this.ui
|
||||
.ensureAnswer(this.options.args[0], 'What would you like to call the value converter?')
|
||||
.then(name => {
|
||||
let fileName = this.project.makeFileName(name);
|
||||
let className = this.project.makeClassName(name);
|
||||
|
||||
this.project.valueConverters.add(
|
||||
ProjectItem.text(`${fileName}.js`, this.generateSource(className))
|
||||
);
|
||||
|
||||
return this.project.commitChanges()
|
||||
.then(() => this.ui.log(`Created ${fileName}.`));
|
||||
});
|
||||
}
|
||||
|
||||
generateSource(className) {
|
||||
return `export class ${className}ValueConverter {
|
||||
toView(value) {
|
||||
|
||||
}
|
||||
|
||||
fromView(value) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
4
aurelia_project/generators/value-converter.json
Normal file
4
aurelia_project/generators/value-converter.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "value-converter",
|
||||
"description": "Creates a value converter class and places it in the project resources."
|
||||
}
|
97
aurelia_project/tasks/build.js
Normal file
97
aurelia_project/tasks/build.js
Normal file
@ -0,0 +1,97 @@
|
||||
import gulp from 'gulp';
|
||||
import transpile from './transpile';
|
||||
import processMarkup from './process-markup';
|
||||
import processAssets from './process-assets';
|
||||
import lintJS from './lint-js';
|
||||
import {build, CLIOptions} from 'aurelia-cli';
|
||||
import project from '../aurelia.json';
|
||||
import processDocs from './process-docs';
|
||||
import livesiteJS from './livesite-js';
|
||||
import cleanAssets from './clean';
|
||||
import copyJsFilesToPL from './copy-js';
|
||||
import copyDataToPL from './copy-data';
|
||||
|
||||
export function buildJs(done) {
|
||||
// TODO : review if --dev still required, since au run --watch now works as expected
|
||||
if (CLIOptions.hasFlag('dev')) {
|
||||
return gulp.series(
|
||||
readProjectConfiguration,
|
||||
gulp.parallel(
|
||||
transpile,
|
||||
livesiteJS,
|
||||
processMarkup
|
||||
),
|
||||
writeBundles,
|
||||
copyJsFilesToPL
|
||||
)(done);
|
||||
}
|
||||
return gulp.series(
|
||||
readProjectConfiguration,
|
||||
gulp.parallel(
|
||||
lintJS,
|
||||
transpile,
|
||||
livesiteJS,
|
||||
processMarkup,
|
||||
processAssets
|
||||
),
|
||||
writeBundles,
|
||||
copyJsFilesToPL
|
||||
)(done);
|
||||
}
|
||||
|
||||
export function buildDocs(done) {
|
||||
return gulp.series(
|
||||
readProjectConfiguration,
|
||||
processDocs
|
||||
)(done);
|
||||
}
|
||||
|
||||
export function buildAll(done) {
|
||||
// TODO : review if --dev still required, since au run --watch now works as expected
|
||||
if (CLIOptions.hasFlag('js') || CLIOptions.hasFlag('dev')) {
|
||||
return buildJs(done);
|
||||
} else if (CLIOptions.hasFlag('docs')) {
|
||||
return gulp.series(
|
||||
readProjectConfiguration,
|
||||
gulp.parallel(
|
||||
processDocs,
|
||||
transpile,
|
||||
processMarkup,
|
||||
processAssets
|
||||
),
|
||||
writeBundles
|
||||
)(done);
|
||||
} else if (CLIOptions.hasFlag('data')) {
|
||||
return gulp.series(
|
||||
readProjectConfiguration,
|
||||
copyDataToPL
|
||||
)(done);
|
||||
}
|
||||
return gulp.series(
|
||||
cleanAssets,
|
||||
readProjectConfiguration,
|
||||
gulp.parallel(
|
||||
processDocs,
|
||||
lintJS,
|
||||
transpile,
|
||||
livesiteJS,
|
||||
processMarkup,
|
||||
processAssets
|
||||
),
|
||||
writeBundles,
|
||||
copyJsFilesToPL,
|
||||
copyDataToPL
|
||||
)(done);
|
||||
}
|
||||
|
||||
export default function buildDefault(done) {
|
||||
return buildAll(done);
|
||||
}
|
||||
|
||||
function readProjectConfiguration() {
|
||||
return build.src(project);
|
||||
}
|
||||
|
||||
function writeBundles() {
|
||||
return build.dest();
|
||||
}
|
26
aurelia_project/tasks/build.json
Normal file
26
aurelia_project/tasks/build.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "build",
|
||||
"description": "Builds and processes all application assets.",
|
||||
"flags": [
|
||||
{
|
||||
"name": "env",
|
||||
"description": "Sets the build environment.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "js",
|
||||
"description": "Only build JS assets.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "docs",
|
||||
"description": "Only build documentation.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "dev",
|
||||
"description": "Only transpile JS and process markup. Do not use prior to committing.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
14
aurelia_project/tasks/clean.js
Normal file
14
aurelia_project/tasks/clean.js
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Created by bstjohn on 01/04/2017.
|
||||
*/
|
||||
import gulp from 'gulp';
|
||||
import debug from 'gulp-debug';
|
||||
import project from '../aurelia.json';
|
||||
import clean from 'gulp-clean';
|
||||
|
||||
export default function cleanAssets(done) {
|
||||
let assets = project.assetsProcessor.clean;
|
||||
return gulp.src(['assets/js/*'], {read: false})
|
||||
.pipe(debug({title: `cleaning ${assets}`}))
|
||||
.pipe(clean());
|
||||
}
|
12
aurelia_project/tasks/copy-data.js
Normal file
12
aurelia_project/tasks/copy-data.js
Normal file
@ -0,0 +1,12 @@
|
||||
import gulp from 'gulp';
|
||||
|
||||
function copyDataToPL() {
|
||||
let sourceDataFiles = ['test/data/**'];
|
||||
let destinationData = '../pattern-library/public/data/';
|
||||
return gulp.src(sourceDataFiles)
|
||||
.pipe(gulp.dest(destinationData));
|
||||
}
|
||||
|
||||
export default gulp.series(
|
||||
copyDataToPL
|
||||
);
|
12
aurelia_project/tasks/copy-js.js
Normal file
12
aurelia_project/tasks/copy-js.js
Normal file
@ -0,0 +1,12 @@
|
||||
import gulp from 'gulp';
|
||||
|
||||
function copyJsFilesToPL() {
|
||||
let sourceJsFiles = [ 'assets/js/*.js', 'assets/js/*.map' ];
|
||||
let destinationJs = '../pattern-library/public/assets/js/';
|
||||
return gulp.src(sourceJsFiles)
|
||||
.pipe(gulp.dest(destinationJs));
|
||||
}
|
||||
|
||||
export default gulp.series(
|
||||
copyJsFilesToPL
|
||||
);
|
26
aurelia_project/tasks/get-stub-data.js
Normal file
26
aurelia_project/tasks/get-stub-data.js
Normal file
@ -0,0 +1,26 @@
|
||||
// linting configuration in is .eslintrc.json file in project root folder
|
||||
|
||||
import gulp from 'gulp';
|
||||
//import project from '../aurelia.json';
|
||||
import download from 'gulp-download';
|
||||
import rename from 'gulp-rename';
|
||||
import jsonFormat from 'gulp-json-format';
|
||||
|
||||
export default function getStubData() {
|
||||
//let pageUrl = 'https://www.franklintempleton.com/en-us-retail/advisor/';
|
||||
let pageUrl = 'http://rcovlnx0191:6205/en-us-retail/advisor/';
|
||||
let fundId = '817';
|
||||
let beans = [
|
||||
'us.historical-cumulative-total-returns-labels',
|
||||
'us.historical-after-tax-average-annual-total-returns-labels'
|
||||
];
|
||||
|
||||
beans.forEach(bean => {
|
||||
let url = fundId ? `${pageUrl}?FundID=${fundId}&bid=${bean}` : `${pageUrl}?bid=${bean}`;
|
||||
let path = fundId ? `test/data/${fundId}` : 'test/data';
|
||||
download(url)
|
||||
.pipe(jsonFormat(2))
|
||||
.pipe(rename(`${bean}.json`))
|
||||
.pipe(gulp.dest(path));
|
||||
});
|
||||
}
|
14
aurelia_project/tasks/lint-css.js
Normal file
14
aurelia_project/tasks/lint-css.js
Normal file
@ -0,0 +1,14 @@
|
||||
// linting configuration in is .stylelintrc file in project root folder
|
||||
|
||||
import gulp from 'gulp';
|
||||
import project from '../aurelia.json';
|
||||
import stylelint from 'gulp-stylelint';
|
||||
|
||||
export default function lintCSS() {
|
||||
return gulp.src(project.cssProcessor.source)
|
||||
.pipe(stylelint({
|
||||
reporters: [
|
||||
{formatter: 'string', console: true}
|
||||
]
|
||||
}));
|
||||
}
|
45
aurelia_project/tasks/lint-js.js
Normal file
45
aurelia_project/tasks/lint-js.js
Normal file
@ -0,0 +1,45 @@
|
||||
import gulp from 'gulp';
|
||||
import project from '../aurelia.json';
|
||||
import eslint from 'gulp-eslint';
|
||||
import {CLIOptions} from 'aurelia-cli';
|
||||
|
||||
// linting configuration in is .eslintrc.json file in project root folder
|
||||
|
||||
function lintJsSrc() {
|
||||
if (CLIOptions.hasFlag('watch')) {
|
||||
return gulp.src(project.jsLinter.source)
|
||||
.pipe(eslint())
|
||||
.pipe(eslint.format());
|
||||
}
|
||||
return gulp.src(project.jsLinter.source)
|
||||
.pipe(eslint())
|
||||
.pipe(eslint.format())
|
||||
.pipe(eslint.failAfterError());
|
||||
}
|
||||
|
||||
// linting tests is les strict - console.log and
|
||||
function lintJsTests() {
|
||||
if (CLIOptions.hasFlag('watch')) {
|
||||
return gulp.src(project.jsLinter.testSource)
|
||||
.pipe(eslint({
|
||||
'rules': {
|
||||
'no-console': ['warn'],
|
||||
'no-unused-vars': ['warn'],
|
||||
'quotes': ['off', 'single']
|
||||
}
|
||||
}))
|
||||
.pipe(eslint.format());
|
||||
}
|
||||
return gulp.src(project.jsLinter.testSource)
|
||||
.pipe(eslint({
|
||||
'rules': {
|
||||
'no-console': ['warn'],
|
||||
'no-unused-vars': ['warn'],
|
||||
'quotes': ['off', 'single']
|
||||
}
|
||||
}))
|
||||
.pipe(eslint.format())
|
||||
.pipe(eslint.failAfterError());
|
||||
}
|
||||
|
||||
export default gulp.parallel(lintJsSrc, lintJsTests);
|
23
aurelia_project/tasks/lint-markup.js
Normal file
23
aurelia_project/tasks/lint-markup.js
Normal file
@ -0,0 +1,23 @@
|
||||
// linting configuration in is .eslintrc.json file in project root folder
|
||||
|
||||
import gulp from 'gulp';
|
||||
import project from '../aurelia.json';
|
||||
import lintspaces from 'gulp-lintspaces';
|
||||
|
||||
export default function lintMarkup() {
|
||||
return gulp.src(project.markupProcessor.source)
|
||||
.pipe(lintspaces({
|
||||
'newline': true,
|
||||
'newlineMaximum': 2,
|
||||
'trailingspaces': true,
|
||||
'indentation': 'spaces',
|
||||
'spaces': 4,
|
||||
'ignores': [
|
||||
'html-comments'
|
||||
]
|
||||
}))
|
||||
.pipe(lintspaces.reporter({
|
||||
breakOnWarning: true,
|
||||
prefixLogs: true
|
||||
}));
|
||||
}
|
49
aurelia_project/tasks/livesite-js.js
Normal file
49
aurelia_project/tasks/livesite-js.js
Normal file
@ -0,0 +1,49 @@
|
||||
import gulp from 'gulp';
|
||||
import concat from 'gulp-concat';
|
||||
import sourcemaps from 'gulp-sourcemaps';
|
||||
import { CLIOptions } from 'aurelia-cli';
|
||||
import uglify from 'gulp-uglify';
|
||||
// import rename from 'gulp-rename';
|
||||
import project from '../aurelia.json';
|
||||
import babel from 'gulp-babel';
|
||||
|
||||
/**
|
||||
* Builds LiveSite JS script
|
||||
* @returns
|
||||
*/
|
||||
function buildJavaScriptLS() {
|
||||
let environment = CLIOptions.getEnvironment();
|
||||
if ( environment === 'dev' ) {
|
||||
return gulp.src( project.livesiteJS.source )
|
||||
.pipe( sourcemaps.init() )
|
||||
.pipe( babel( project.livesiteJS.options ) )
|
||||
.pipe( concat( 'livesite-modules.js' ) )
|
||||
.pipe( sourcemaps.write( '.' ) )
|
||||
.pipe( gulp.dest( project.livesiteJS.output ) );
|
||||
} else if ( environment === 'stage' ) {
|
||||
return gulp.src( project.livesiteJS.source )
|
||||
.pipe( sourcemaps.init() )
|
||||
.pipe( babel( project.livesiteJS.options ) )
|
||||
.pipe( concat( 'livesite-modules.js' ) )
|
||||
.pipe( uglify() )
|
||||
// .pipe( rename( {
|
||||
// suffix: '.min'
|
||||
// } ) )
|
||||
.pipe( sourcemaps.write( '.' ) )
|
||||
.pipe( gulp.dest( project.livesiteJS.output ) );
|
||||
} else if ( environment === 'prod' ) {
|
||||
return gulp.src( project.livesiteJS.source )
|
||||
.pipe( sourcemaps.init() )
|
||||
.pipe( babel( project.livesiteJS.options ) )
|
||||
.pipe( concat( 'livesite-modules.js' ) )
|
||||
.pipe( uglify() )
|
||||
// .pipe( rename( {
|
||||
// suffix: '.min'
|
||||
// } ) )
|
||||
.pipe( gulp.dest( project.livesiteJS.output ) );
|
||||
}
|
||||
}
|
||||
|
||||
export default gulp.series(
|
||||
buildJavaScriptLS
|
||||
);
|
9
aurelia_project/tasks/package.js
Normal file
9
aurelia_project/tasks/package.js
Normal file
@ -0,0 +1,9 @@
|
||||
import gulp from 'gulp';
|
||||
import zip from 'gulp-zip';
|
||||
import project from '../aurelia.json';
|
||||
|
||||
export default function() {
|
||||
return gulp.src(project.packager.src, {base: '.'})
|
||||
.pipe(zip(project.packager.zipfile))
|
||||
.pipe(gulp.dest(project.packager.outputDir));
|
||||
}
|
17
aurelia_project/tasks/process-assets.js
Normal file
17
aurelia_project/tasks/process-assets.js
Normal file
@ -0,0 +1,17 @@
|
||||
import gulp from 'gulp';
|
||||
// import changedInPlace from 'gulp-changed-in-place';
|
||||
import project from '../aurelia.json';
|
||||
// import {build} from 'aurelia-cli';
|
||||
import debug from 'gulp-debug';
|
||||
|
||||
export default function processAssets(done) {
|
||||
let subtasks = project.assetsProcessor.assets.map(asset => {
|
||||
return function() {
|
||||
return gulp.src(asset.src)
|
||||
.pipe(debug({title: `copy ${asset.src} >>> ${asset.dest}`}))
|
||||
.pipe(gulp.dest(asset.dest));
|
||||
};
|
||||
});
|
||||
|
||||
return gulp.parallel(subtasks)(done);
|
||||
}
|
32
aurelia_project/tasks/process-css.js
Normal file
32
aurelia_project/tasks/process-css.js
Normal file
@ -0,0 +1,32 @@
|
||||
// changed to SASS+autoprefixer using this blog post: http://ilikekillnerds.com/2016/07/adding-postcssautoprefixer-aurelia-cli/
|
||||
|
||||
import gulp from 'gulp';
|
||||
import sourcemaps from 'gulp-sourcemaps';
|
||||
import project from '../aurelia.json';
|
||||
import sass from 'gulp-sass';
|
||||
import postcss from 'gulp-postcss';
|
||||
import cssnano from 'gulp-cssnano';
|
||||
import autoprefixer from 'autoprefixer';
|
||||
import lintCSS from './lint-css';
|
||||
import rename from 'gulp-rename';
|
||||
|
||||
export default function processCSS() {
|
||||
let processors = [
|
||||
autoprefixer(project.cssProcessor.browsers)
|
||||
];
|
||||
|
||||
return gulp.src(project.cssProcessor.source)
|
||||
.pipe(lintCSS())
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(sass({
|
||||
includePaths: project.cssProcessor.sassIncludePaths
|
||||
}).on('error', sass.logError))
|
||||
.pipe(postcss(processors))
|
||||
.pipe(cssnano())
|
||||
.pipe(sourcemaps.write('.'))
|
||||
.pipe(rename(path => {
|
||||
// this means the generated css files are placed directly in assets/css folder instead of a scss sub-folder
|
||||
path.dirname = path.dirname.replace('scss', '');
|
||||
}))
|
||||
.pipe(gulp.dest(project.cssProcessor.output));
|
||||
}
|
120
aurelia_project/tasks/process-docs.js
Normal file
120
aurelia_project/tasks/process-docs.js
Normal file
@ -0,0 +1,120 @@
|
||||
import gulp from 'gulp';
|
||||
import {CLIOptions} from 'aurelia-cli';
|
||||
import project from '../aurelia.json';
|
||||
import debug from 'gulp-debug';
|
||||
import gutil from 'gulp-util';
|
||||
import through from 'through2';
|
||||
import File from 'vinyl';
|
||||
import marked from 'marked';
|
||||
import hljs from 'highlight.js';
|
||||
|
||||
export default function processDocs(done) {
|
||||
if (CLIOptions.getEnvironment() !== 'prod') {
|
||||
return gulp.src(project.docsProcessor.source)
|
||||
.pipe(debug({title: 'generate documentation:'}))
|
||||
.pipe(mdToJson(project.docsProcessor.jsonFile))
|
||||
.pipe(gulp.dest(project.docsProcessor.outputDir));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// set up document index - matches docs to sections based on regex match on their paths
|
||||
let docs = project.docsProcessor.index;
|
||||
docs.pages = {};
|
||||
let regexes = new Map();
|
||||
|
||||
function getRegexes(section) {
|
||||
if (section.regex !== undefined) {
|
||||
section.pages = [];
|
||||
regexes.set(new RegExp(section.regex), section.pages);
|
||||
}
|
||||
if (section.subs !== undefined) {
|
||||
section.subs.forEach(getRegexes);
|
||||
}
|
||||
}
|
||||
docs.index.forEach(getRegexes);
|
||||
let uncategorizedPages = docs.index.find(section => section.section === 'Uncategorized');
|
||||
uncategorizedPages = uncategorizedPages.pages = [];
|
||||
|
||||
// need a bespoke renderer for marked to put the hljs tag on the code element
|
||||
// might get fixed in subsequent release
|
||||
let myRenderer = new marked.Renderer();
|
||||
if (typeof hljs !== 'undefined') {
|
||||
myRenderer.code = function(code, lang, escaped) {
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
code = hljs.highlight(lang, code).value;
|
||||
} catch (e) {
|
||||
// fail silently
|
||||
}
|
||||
}
|
||||
return '<pre><code'
|
||||
+ (lang
|
||||
? ' class="hljs ' + this.options.langPrefix + lang + '"'
|
||||
: ' class="hljs"')
|
||||
+ '>'
|
||||
+ code
|
||||
+ '\n</code></pre>\n';
|
||||
};
|
||||
}
|
||||
|
||||
marked.setOptions({
|
||||
renderer: myRenderer,
|
||||
highlight: function(code) {
|
||||
return hljs.highlightAuto(code).value;
|
||||
},
|
||||
gfm: true,
|
||||
tables: true,
|
||||
breaks: false,
|
||||
pedantic: false,
|
||||
sanitize: false,
|
||||
smartLists: true,
|
||||
smartypants: false
|
||||
});
|
||||
|
||||
function mdToJson(out) {
|
||||
return through.obj(function(file, enc, cb) {
|
||||
if (file.isNull()) {
|
||||
cb(null, file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (file.isStream()) {
|
||||
cb(new gutil.PluginError('mdToJson', 'Streams not supported'));
|
||||
return;
|
||||
}
|
||||
|
||||
let fileid = file.relative.replace(/\\/g, '/');
|
||||
docs.pages[fileid] = marked(file.contents.toString('utf8'));
|
||||
|
||||
// try and match to correct section
|
||||
let uncategorized = true;
|
||||
for (let [regex, pages] of regexes) {
|
||||
if (regex.test(fileid)) {
|
||||
if (! pages.some( id => id === fileid)) {
|
||||
pages.push(fileid);
|
||||
}
|
||||
uncategorized = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (uncategorized) {
|
||||
if (! uncategorizedPages.some( id => id === fileid)) {
|
||||
uncategorizedPages.push(fileid);
|
||||
}
|
||||
}
|
||||
|
||||
cb();
|
||||
}, function(cb) {
|
||||
let buffer = new Buffer(JSON.stringify(docs, null, ' '));
|
||||
|
||||
let fileListFile = new File({
|
||||
path: out,
|
||||
contents: buffer
|
||||
});
|
||||
|
||||
this.push(fileListFile);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
20
aurelia_project/tasks/process-markup.js
Normal file
20
aurelia_project/tasks/process-markup.js
Normal file
@ -0,0 +1,20 @@
|
||||
import gulp from 'gulp';
|
||||
import htmlmin from 'gulp-htmlmin';
|
||||
import changedInPlace from 'gulp-changed-in-place';
|
||||
import project from '../aurelia.json';
|
||||
import {build} from 'aurelia-cli';
|
||||
import lintMarkup from './lint-markup';
|
||||
|
||||
export default function processMarkup() {
|
||||
return gulp.src(project.markupProcessor.source)
|
||||
.pipe(lintMarkup())
|
||||
.pipe(changedInPlace({firstPass: true}))
|
||||
.pipe(htmlmin({
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
conservativeCollapse: true,
|
||||
minifyCSS: true,
|
||||
minifyJS: true
|
||||
}))
|
||||
.pipe(build.bundle());
|
||||
}
|
184
aurelia_project/tasks/proxy-server.js
Normal file
184
aurelia_project/tasks/proxy-server.js
Normal file
@ -0,0 +1,184 @@
|
||||
import gutil from 'gulp-util';
|
||||
import {CLIOptions} from 'aurelia-cli';
|
||||
|
||||
/**
|
||||
* Example usage
|
||||
* au proxy-server --static-cache --gzip --remove-tracking --override-aurelia-config configuration/etf/main --dev-js-assets-server http://localhost:9000/ --dev-css-assets-server http://pattern-library.corp.frk.com/
|
||||
*/
|
||||
const defaultUrl = CLIOptions.getFlagValue('proxy-target') ? CLIOptions.getFlagValue('proxy-target') : 'https://www.franklintempleton.com/';
|
||||
// --proxy-target http://rcovlnx0188:8202
|
||||
|
||||
|
||||
export function proxyServer(done) {
|
||||
gutil.log('starting proxy server on http://localhost:2000 (proxying = ' + defaultUrl + ')');
|
||||
if (CLIOptions.hasFlag('dev-js-assets-server')) {
|
||||
gutil.log(' replace js assets with ' + CLIOptions.getFlagValue('dev-js-assets-server'));
|
||||
}
|
||||
if (CLIOptions.hasFlag('dev-css-assets-server')) {
|
||||
gutil.log(' replace css assets with ' + CLIOptions.getFlagValue('dev-css-assets-server'));
|
||||
}
|
||||
|
||||
let express = require('express');
|
||||
let proxy = require('express-http-proxy');
|
||||
let cache = require('express-cache-response');
|
||||
let compression = require('compression');
|
||||
|
||||
let app = express();
|
||||
|
||||
if (CLIOptions.hasFlag('static-cache')) {
|
||||
app.use(cache());
|
||||
}
|
||||
if (CLIOptions.hasFlag('gzip')) {
|
||||
app.use(compression());
|
||||
}
|
||||
|
||||
if (CLIOptions.hasFlag('dev-js-assets-server')) {
|
||||
let devAssetsServer = CLIOptions.getFlagValue('dev-js-assets-server').replace(/\/$/, '');
|
||||
app.use('/assets/js/', proxy(devAssetsServer + '/assets/js/', {
|
||||
changeOrigin: true,
|
||||
/**
|
||||
* You can mutate the request options before sending the proxyRequest.
|
||||
* proxyReqOpt represents the options argument passed to the (http|https).request module.
|
||||
*
|
||||
* @param proxyReqOpts
|
||||
* @param srcReq
|
||||
* @returns {*}
|
||||
*/
|
||||
proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
|
||||
proxyReqOpts.headers['Cache-Control'] = 'no-cache';
|
||||
proxyReqOpts.headers['Cache-Control'] = 'no-store';
|
||||
proxyReqOpts.headers['Cache-Control'] = 'no-transform';
|
||||
proxyReqOpts.headers['Cache-Control'] = 'only-if-cached';
|
||||
proxyReqOpts.headers['ETag'] = 'ruin_the_etag' + Math.random();
|
||||
return proxyReqOpts;
|
||||
},
|
||||
/**
|
||||
* Provide a proxyReqPathResolver function if you'd like to operate on the path before issuing the proxy request.
|
||||
* Use a Promise for async operations.
|
||||
* @param req
|
||||
*/
|
||||
proxyReqPathResolver: function(req) {
|
||||
return '/assets/js' + require('url').parse(req.url).path;
|
||||
},
|
||||
/**
|
||||
* You can modify the proxy's response before sending it to the client.
|
||||
* @param proxyRes
|
||||
* @param proxyResData
|
||||
* @param userReq
|
||||
* @param userRes
|
||||
*/
|
||||
userResDecorator: function(proxyRes, proxyResData, userReq, userRes) {
|
||||
let isJS = proxyRes.headers['content-type'] ? proxyRes.headers['content-type'].indexOf('text/javascript') !== -1 : false;
|
||||
isJS = isJS || proxyRes.headers['content-type'] ? proxyRes.headers['content-type'].indexOf('application/javascript') !== -1 : false;
|
||||
isJS = isJS || userReq.originalUrl.endsWith('.js');
|
||||
gutil.log(' > proxying dev js (' + userReq.originalUrl + ') from : ' + devAssetsServer + userReq.originalUrl);
|
||||
proxyRes.headers['etag'] = 'ruin_the_etag' + Math.random();
|
||||
proxyResData = proxyResData.toString('utf8');
|
||||
return proxyResData;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
app.use('/', proxy(defaultUrl, {
|
||||
changeOrigin: true,
|
||||
/**
|
||||
* You can modify the proxy's response before sending it to the client.
|
||||
* @param proxyRes
|
||||
* @param proxyResData
|
||||
* @param userReq
|
||||
* @param userRes
|
||||
*/
|
||||
userResDecorator: function(proxyRes, proxyResData, userReq, userRes) {
|
||||
let isHtml = proxyRes.headers['content-type'] ? proxyRes.headers['content-type'].indexOf('text/html') !== -1 : false;
|
||||
|
||||
|
||||
let isJS = proxyRes.headers['content-type'] ? proxyRes.headers['content-type'].indexOf('text/javascript') !== -1 : false;
|
||||
isJS = isJS || proxyRes.headers['content-type'] ? proxyRes.headers['content-type'].indexOf('application/javascript') !== -1 : false;
|
||||
isJS = isJS || userReq.originalUrl.endsWith('.js');
|
||||
|
||||
if (isHtml) {
|
||||
gutil.log(' > rewriting : ' + userReq.originalUrl);
|
||||
proxyResData = proxyResData.toString('utf8');
|
||||
if (CLIOptions.hasFlag('remove-tracking')) {
|
||||
// remove Google Tag Manager
|
||||
proxyResData = proxyResData.replace(/<!-- Google Tag Manager -->(.|[\r\n])*<!-- End Google Tag Manager -->/gm, function(replace) {
|
||||
gutil.log(' >> removing string : ' + replace);
|
||||
return '';
|
||||
});
|
||||
// remove s7
|
||||
proxyResData = proxyResData.replace(/<script[^>]+src="https:\/\/s7.addthis.com\/.*"[^>]*><\/script>/gm, function(replace) {
|
||||
gutil.log(' >> removing string : ' + replace);
|
||||
return '';
|
||||
});
|
||||
}
|
||||
|
||||
if (CLIOptions.hasFlag('remove-tenant-libs')) {
|
||||
proxyResData = proxyResData.replace(/<script[^>]+src=".*\/((main-home)|(handlebars.*))\.js"[^>]*><\/script>/gm, function(replace) {
|
||||
gutil.log(' >> removing string tenant libraries: ' + replace);
|
||||
return '';
|
||||
});
|
||||
}
|
||||
|
||||
if (CLIOptions.hasFlag('remove-images')) {
|
||||
// kill images by redirecting to favicon
|
||||
proxyResData = proxyResData.replace(/.*\.(jpeg|jpg|png)/gm, function(replace) {
|
||||
gutil.log(' >> removing image: ' + replace);
|
||||
return '/web-resources/ui/default/images/favicon.ico';
|
||||
});
|
||||
}
|
||||
|
||||
if (CLIOptions.hasFlag('dev-css-assets-server')) {
|
||||
let devAssetsServer = CLIOptions.getFlagValue('dev-css-assets-server');
|
||||
// redirect to other host
|
||||
proxyResData = proxyResData.replace(/\/assets\/css\/core(\.min)?\.css/gm, function(replace) {
|
||||
let cssUrl = devAssetsServer + '/assets/css/core.css';
|
||||
gutil.log(' >> replacing ' + replace + ' for link to remote pattern-library (' + cssUrl + ')');
|
||||
return cssUrl;
|
||||
});
|
||||
}
|
||||
|
||||
if (CLIOptions.getFlagValue('override-aurelia-config')) {
|
||||
let aureliaApp = CLIOptions.getFlagValue('override-aurelia-config');
|
||||
proxyResData = proxyResData.replace(/aurelia-app=".*"/gm, function(replace) {
|
||||
gutil.log(' >> replacing aurelia app ' + replace + ' for : ' + aureliaApp);
|
||||
return 'aurelia-app="' + aureliaApp + '"';
|
||||
});
|
||||
}
|
||||
// Inject Timing Code
|
||||
// Use console.timeEnd("from-page-load"); to get time from page load
|
||||
proxyResData = proxyResData.replace(/head>/gm, function(replace) {
|
||||
return 'head><script>console.time("from-page-load");</script>';
|
||||
});
|
||||
}
|
||||
|
||||
if (isJS) {
|
||||
proxyResData = proxyResData.toString('utf8');
|
||||
}
|
||||
return proxyResData;
|
||||
},
|
||||
/**
|
||||
* You can mutate the body content before sending the proxyRequest.
|
||||
* @param bodyContent
|
||||
* @param srcReq
|
||||
* @returns {*}
|
||||
*/
|
||||
proxyReqBodyDecorator: function(bodyContent, srcReq) {
|
||||
return bodyContent;
|
||||
},
|
||||
/**
|
||||
* You can mutate the request options before sending the proxyRequest.
|
||||
* proxyReqOpt represents the options argument passed to the (http|https).request module.
|
||||
*
|
||||
* @param proxyReqOpts
|
||||
* @param srcReq
|
||||
* @returns {*}
|
||||
*/
|
||||
proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
|
||||
return proxyReqOpts;
|
||||
}
|
||||
}));
|
||||
app.listen(2000);
|
||||
}
|
||||
export default function proxyDefault(done) {
|
||||
proxyServer(done);
|
||||
}
|
53
aurelia_project/tasks/proxy-server.json
Normal file
53
aurelia_project/tasks/proxy-server.json
Normal file
@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "proxy-server",
|
||||
"description": "Proxies main site with dev application assets.",
|
||||
"flags": [
|
||||
{
|
||||
"name": "override-aurelia-config",
|
||||
"description": "eg configuration/etf/main",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "proxy-target",
|
||||
"description": "server to proxy eg http://rcovlnx0188:8202",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "dev-js-assets-server",
|
||||
"description": "Use hosted JS files on another server eg http://localhost:9000",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "dev-css-assets-server",
|
||||
"description": "Use hosted JS files on another server eg http://localhost:9000 (will default to unmin-ed version)",
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "remove-tracking",
|
||||
"description": "Remove all google and misc tracking code",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "remove-images",
|
||||
"description": "Remove all images, replace them with 1 pixel equivilients",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "remove-tenant-libs",
|
||||
"description": "Remove tenant libs",
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "gzip",
|
||||
"description": "gzip asset",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "static-cache",
|
||||
"description": "cache asset, dumb cache never expires",
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
}
|
189
aurelia_project/tasks/run.js
Normal file
189
aurelia_project/tasks/run.js
Normal file
@ -0,0 +1,189 @@
|
||||
import gulp from 'gulp';
|
||||
import gutil from 'gulp-util';
|
||||
import browserSync from 'browser-sync';
|
||||
import historyApiFallback from 'connect-history-api-fallback/lib';
|
||||
import project from '../aurelia.json';
|
||||
import {buildAll, buildJs, buildDocs} from './build';
|
||||
import {CLIOptions} from 'aurelia-cli';
|
||||
import request from 'request';
|
||||
|
||||
function onChange(path) {
|
||||
gutil.log(`File Changed: ${path}`);
|
||||
}
|
||||
|
||||
function reload(done) {
|
||||
browserSync.reload();
|
||||
done();
|
||||
}
|
||||
|
||||
let serve = gulp.series(
|
||||
buildAll,
|
||||
done => {
|
||||
browserSync({
|
||||
online: false,
|
||||
open: false,
|
||||
port: 9000,
|
||||
logLevel: 'info',
|
||||
server: {
|
||||
baseDir: ['.'],
|
||||
middleware: [
|
||||
relaxAllowOrigin,
|
||||
proxyFixtures,
|
||||
historyApiFallback()
|
||||
]
|
||||
}
|
||||
}, function(err, bs) {
|
||||
let urls = bs.options.get('urls').toJS();
|
||||
gutil.log(`Application Available At: ${urls.local}`);
|
||||
gutil.log(`BrowserSync Available At: ${urls.ui}`);
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
let relaxAllowOrigin = function(req, res, next) {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
next();
|
||||
};
|
||||
|
||||
let proxyFixtures = function(req, res, next) {
|
||||
// rest api rewrites
|
||||
let isLocalMode = !CLIOptions.hasFlag('use-test-server');
|
||||
if (isLocalMode) {
|
||||
proxyLocalFixtures(req, res, next);
|
||||
} else {
|
||||
proxyRemoteFixtures(req, res, next);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* proxies data feed into server
|
||||
* eg
|
||||
* http://localhost:9000/etf-gb/investor/data/21412/etf.fund-details
|
||||
* proxied to
|
||||
* http://rcovlnx0192:8322/etf-gb/investor/data/21412/etf.fund-details
|
||||
*
|
||||
* @param req
|
||||
* @param res
|
||||
* @param next
|
||||
*/
|
||||
let proxyRemoteFixtures = function(req, res, next) {
|
||||
let testFundId = CLIOptions.getFlagValue('test-server-fund-id') || '21412';
|
||||
let testServer = CLIOptions.getFlagValue('test-server') || 'http://rcovlnx0192:8322';
|
||||
let testSite = CLIOptions.getFlagValue('test-site') || false;
|
||||
|
||||
let proxyUrl;
|
||||
let matches = req.url.match(/^\/([^/]+)\/([^/]+)\/data\/(\d+)\/(.*)/);
|
||||
if (matches !== null) {
|
||||
// gutil.log(`site=${matches[1]}, segment=${matches[2]}, fundId=${matches[3]}, beanId=${matches[4]}`);
|
||||
let site = testSite ? testSite : matches[1];
|
||||
proxyUrl = `${testServer}/${site}/${matches[2]}/data/${testFundId}/${matches[4]}`;
|
||||
} else {
|
||||
matches = req.url.match(/^\/([^/]+)\/([^/]+)\/data\/(.*)/);
|
||||
if (matches !== null) {
|
||||
// gutil.log(`site=${matches[1]}, segment=${matches[2]}, beanId=${matches[3]}`);
|
||||
let site = testSite ? testSite : matches[1];
|
||||
proxyUrl = `${testServer}/${site}/${matches[2]}/data/${matches[3]}`;
|
||||
}
|
||||
}
|
||||
if (proxyUrl) {
|
||||
// any small bean changes add here
|
||||
// eg
|
||||
// proxyUrl = proxyUrl.replace('etf.fund-details', 'etf.fund-details');
|
||||
// proxyUrl = proxyUrl.replace('etf.distribution-history', 'etf.distribution-history');
|
||||
|
||||
gutil.log(`${req.url} -> ${proxyUrl}`);
|
||||
request.get(
|
||||
proxyUrl, {},
|
||||
function(error, response, contents) {
|
||||
// gutil.log(error, response, body);
|
||||
if (!error && response.statusCode === 200) {
|
||||
try {
|
||||
if (!contents.match(/^( |[\r\n])*$/)) {
|
||||
let json = JSON.parse(contents);
|
||||
json.__debug = {
|
||||
injectedByNode: true,
|
||||
sourceUrl: proxyUrl
|
||||
};
|
||||
contents = JSON.stringify(json, null, 2);
|
||||
}
|
||||
} catch (e) {
|
||||
gutil.log(e);
|
||||
}
|
||||
res.end(contents);
|
||||
} else {
|
||||
gutil.log(error);
|
||||
}
|
||||
next();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
gutil.log(req.url);
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param req
|
||||
* @param res
|
||||
* @param next
|
||||
*/
|
||||
let proxyLocalFixtures = function(req, res, next) {
|
||||
let matches = req.url.match(/^\/([^/]+)\/([^/]+)\/data\/(\d+)\/(.*)/);
|
||||
if (matches !== null) {
|
||||
// gutil.log(`site=${matches[1]}, segment=${matches[2]}, fundId=${matches[3]}, beanId=${matches[4]}`);
|
||||
let fixtureFile = `/test/data/${matches[1]}/${matches[3]}/${matches[4]}.json`;
|
||||
gutil.log(`${req.url} -> ${fixtureFile}`);
|
||||
req.url = fixtureFile;
|
||||
} else {
|
||||
matches = req.url.match(/^\/([^/]+)\/([^/]+)\/data\/(.*)/);
|
||||
if (matches !== null) {
|
||||
// gutil.log(`site=${matches[1]}, segment=${matches[2]}, beanId=${matches[3]}`);
|
||||
let fixtureFile = `/test/data/${matches[1]}/${matches[3]}.json`;
|
||||
gutil.log(`${req.url} -> ${fixtureFile}`);
|
||||
req.url = fixtureFile;
|
||||
} else {
|
||||
gutil.log(req.url);
|
||||
}
|
||||
}
|
||||
next();
|
||||
};
|
||||
|
||||
let refresh = gulp.series(
|
||||
buildAll,
|
||||
reload
|
||||
);
|
||||
|
||||
let refreshJs = gulp.series(
|
||||
buildJs,
|
||||
reload
|
||||
);
|
||||
|
||||
let refreshDocs = gulp.series(
|
||||
buildDocs,
|
||||
reload
|
||||
);
|
||||
|
||||
let watch = function() {
|
||||
// aurelia bundles
|
||||
gulp.watch(project.transpiler.source, refreshJs).on('change', onChange);
|
||||
gulp.watch(project.markupProcessor.source, refreshJs).on('change', onChange);
|
||||
|
||||
// markdown pages
|
||||
gulp.watch(project.docsProcessor.source, refreshDocs).on('change', onChange);
|
||||
|
||||
gulp.watch(project.cssProcessor.source, refresh).on('change', onChange);
|
||||
};
|
||||
|
||||
let run;
|
||||
|
||||
if (CLIOptions.hasFlag('watch')) {
|
||||
run = gulp.series(
|
||||
serve,
|
||||
watch
|
||||
);
|
||||
} else {
|
||||
run = serve;
|
||||
}
|
||||
|
||||
export default run;
|
36
aurelia_project/tasks/run.json
Normal file
36
aurelia_project/tasks/run.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "run",
|
||||
"description": "Builds the application and serves up the assets via a local web server, watching files for changes as you work.",
|
||||
"flags": [
|
||||
{
|
||||
"name": "env",
|
||||
"description": "Sets the build environment.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "watch",
|
||||
"description": "Watches source files for changes and refreshes the app automatically.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "use-test-server",
|
||||
"description": "Get Data from test server, default fund id 21412, default server http://rcovlnx0192:8322.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "test-server",
|
||||
"description": "Set Data from test server, requires --use-test-server.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "test-server-fund-id",
|
||||
"description": "Set Test Server to use, requires --use-test-server.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "test-site",
|
||||
"description": "Set Test Site to use eg etf-en or etf-us, requires --use-test-server.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
41
aurelia_project/tasks/sonar.js
Normal file
41
aurelia_project/tasks/sonar.js
Normal file
@ -0,0 +1,41 @@
|
||||
import gulp from 'gulp';
|
||||
import project from '../aurelia.json';
|
||||
import sonar from 'gulp-sonar';
|
||||
|
||||
export default function sonarTest( done ) {
|
||||
let version = '0.1.0';
|
||||
let projectKey = 'sonar:' + project.name + ':' + version;
|
||||
let options = {
|
||||
sonar: {
|
||||
host: {
|
||||
url: project.sonar.sonarURL
|
||||
},
|
||||
jdbc: {
|
||||
url: project.sonar.sonarDB,
|
||||
username: project.sonar.sonarUser,
|
||||
password: project.sonar.sonarPasswd
|
||||
},
|
||||
projectKey: projectKey,
|
||||
projectName: project.name,
|
||||
projectVersion: version,
|
||||
// comma-delimited string of source directories
|
||||
sources: project.sonar.sources,
|
||||
exclusions: project.sonar.exclusions,
|
||||
language: 'js',
|
||||
sourceEncoding: 'UTF-8',
|
||||
javascript: {
|
||||
lcov: {
|
||||
reportPath: project.sonar.reportPath
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
// All these properties will be send to the child_process.exec method (see: https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback )
|
||||
// Increase the amount of data allowed on stdout or stderr (if this value is exceeded then the child process is killed, and the gulp-sonar will fail).
|
||||
maxBuffer: 1024 * 1024
|
||||
}
|
||||
}
|
||||
};
|
||||
// gulp source doesn't matter, all files are referenced in options object above
|
||||
return gulp.src( 'src/**/*.js', { read: false } )
|
||||
.pipe( sonar( options ) );
|
||||
}
|
45
aurelia_project/tasks/test.js
Normal file
45
aurelia_project/tasks/test.js
Normal file
@ -0,0 +1,45 @@
|
||||
import gulp from 'gulp';
|
||||
import {Server as Karma} from 'karma';
|
||||
import {CLIOptions} from 'aurelia-cli';
|
||||
import jest from 'gulp-jest';
|
||||
|
||||
// TODO: add coverage options
|
||||
|
||||
function testUI(done) {
|
||||
let karamConfig = {
|
||||
configFile: __dirname + '/../../karma.conf.js'
|
||||
};
|
||||
if (CLIOptions.hasFlag('watch')) {
|
||||
karamConfig.singleRun = false;
|
||||
karamConfig.specReporter = {
|
||||
showSpecTiming: true,
|
||||
suppressSkipped: true,
|
||||
suppressErrorSummary: false
|
||||
};
|
||||
}
|
||||
new Karma(karamConfig, done).start();
|
||||
}
|
||||
|
||||
function testBusinessLogic() {
|
||||
return gulp.src('src').pipe(jest({
|
||||
config: {
|
||||
'verbose': true,
|
||||
'testRegex': '(util|lib|value-converters).*.spec.js$',
|
||||
'collectCoverage': true,
|
||||
'coverageDirectory': '../coverage',
|
||||
'coverageReporters': ['html', 'clover']
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
export default function test(done) {
|
||||
if (CLIOptions.hasFlag('bl')) {
|
||||
return testBusinessLogic();
|
||||
} else if (CLIOptions.hasFlag('ui')) {
|
||||
return testUI(done);
|
||||
}
|
||||
return gulp.series(
|
||||
testBusinessLogic,
|
||||
testUI
|
||||
)();
|
||||
}
|
26
aurelia_project/tasks/test.json
Normal file
26
aurelia_project/tasks/test.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "test",
|
||||
"description": "Runs all unit tests and reports the results.",
|
||||
"flags": [
|
||||
{
|
||||
"name": "env",
|
||||
"description": "Sets the build environment.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "watch",
|
||||
"description": "Watches test files for changes and re-runs the tests automatically.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "bl",
|
||||
"description": "Test only the Business Logic (non-UI e.g. reducers) code via Jest.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "ui",
|
||||
"description": "Test only the UI components via Karma.",
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
}
|
35
aurelia_project/tasks/transpile.js
Normal file
35
aurelia_project/tasks/transpile.js
Normal file
@ -0,0 +1,35 @@
|
||||
import gulp from 'gulp';
|
||||
import changedInPlace from 'gulp-changed-in-place';
|
||||
import plumber from 'gulp-plumber';
|
||||
import babel from 'gulp-babel';
|
||||
import sourcemaps from 'gulp-sourcemaps';
|
||||
import notify from 'gulp-notify';
|
||||
import rename from 'gulp-rename';
|
||||
import project from '../aurelia.json';
|
||||
import {CLIOptions, build} from 'aurelia-cli';
|
||||
// import debug from 'gulp-debug';
|
||||
|
||||
function configureEnvironment() {
|
||||
let env = CLIOptions.getEnvironment();
|
||||
|
||||
return gulp.src(`aurelia_project/environments/${env}.js`)
|
||||
.pipe(changedInPlace({firstPass: true}))
|
||||
.pipe(rename('environment.js'))
|
||||
.pipe(gulp.dest(project.paths.root));
|
||||
}
|
||||
|
||||
function buildJavaScript() {
|
||||
// TODO: should lintJS run here instead of in the build task?
|
||||
return gulp.src(project.transpiler.source)
|
||||
// .pipe(debug({title: 'start transpile:'}))
|
||||
.pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
|
||||
.pipe(changedInPlace({firstPass: true}))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(babel(project.transpiler.options))
|
||||
.pipe(build.bundle());
|
||||
}
|
||||
|
||||
export default gulp.series(
|
||||
configureEnvironment,
|
||||
buildJavaScript
|
||||
);
|
29
docs.html
Normal file
29
docs.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Site Configuration</title>
|
||||
<link rel="stylesheet" href="http://pattern-library.corp.frk.com/assets/css/core.css" type="text/css"/> <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/styles/kimbie.dark.min.css">
|
||||
<style>
|
||||
code {
|
||||
text-transform: none;
|
||||
}
|
||||
a {
|
||||
cursor: pointer;
|
||||
}
|
||||
p code {
|
||||
color: #a0a0a0;
|
||||
padding: 1px;
|
||||
}
|
||||
li code {
|
||||
color: #a0a0a0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body aurelia-app="components/test/docs/main">
|
||||
|
||||
<script src="/assets/js/web-platform.js" data-main="aurelia-bootstrapper"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
6434
geocities.css
Normal file
6434
geocities.css
Normal file
File diff suppressed because it is too large
Load Diff
109
index.html
Normal file
109
index.html
Normal file
@ -0,0 +1,109 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Web Platform Local Development Environment</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/muicss/0.9.12/css/mui.min.css" type="text/css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="mui-container">
|
||||
<h1 class="rainbow">Web Platform Local Development Environment</h1>
|
||||
|
||||
<div class="mui-panel">
|
||||
<h2>Documentation</h2>
|
||||
<a href="/docs.html">Docs</a>
|
||||
</div>
|
||||
|
||||
<div class="mui-panel">
|
||||
<h2>Unit test coverage</h2>
|
||||
<a href="/coverage/index.html">Reducers</a>
|
||||
<br>
|
||||
<a href="/coverage/components/index.html">Components</a>
|
||||
</div>
|
||||
|
||||
<div class="mui-panel">
|
||||
<h2>UK ETF</h2>
|
||||
<a href="/test/pages/etf-gb/fund-explorer.html">ETF Fund Explorer</a>
|
||||
<br>
|
||||
<a href="/test/pages/etf-gb/overview.html">ETF Overview</a>
|
||||
<br/>
|
||||
<a href="/test/pages/etf-gb/fund-trading-characteristics.html">ETF Fund Trading Characteristics</a>
|
||||
<br/>
|
||||
<a href="/test/pages/etf-gb/portfolio.html">ETF Portfolio</a>
|
||||
<br/>
|
||||
<a href="/test/pages/etf-gb/portfolio-21412.html">ETF Portfolio 21412</a>
|
||||
|
||||
<br>
|
||||
<a href="/test/pages/etf-gb/performance.html">ETF Performance</a>
|
||||
<br>
|
||||
<a href="/test/pages/etf-gb/performance-annualised.html">ETF Performance Annualised</a>
|
||||
<br>
|
||||
<a href="/test/pages/etf-gb/calendar-year.html">ETF Performance Calendar</a>
|
||||
<br>
|
||||
<a href="/test/pages/etf-gb/backtested-performance.html">ETF Backtested Performances</a>
|
||||
<br>
|
||||
<a href="/test/pages/etf-gb/pricing-distribution.html">ETF Pricing & Distribution</a>
|
||||
</div>
|
||||
|
||||
<div class="mui-panel">
|
||||
<h2>UK Test Pages</h2>
|
||||
<a href="/test/pages/en-gb/carousel.html">Carousels</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-gb/grid-filter.html">Grid Filter</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-gb/performance.html">Performance</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-gb/portfolio.html">Portfolio</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-gb/ppss.html">PPSS</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-gb/pricing-distribution.html">Pricing & Distribution</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-gb/video-switch.html">Video Switch</a>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<a href="/test/pages/en-gb/marketing.html">Document Archives</a>
|
||||
<br/>
|
||||
<a href="/test/pages/en-gb/doclister.html">Document Lister</a>
|
||||
<br/>
|
||||
<a href="/test/pages/en-gb/stickytabs.html">Sticky Tabs</a>
|
||||
<br/>
|
||||
<a href="/test/pages/en-gb/overview.html">Overview</a>
|
||||
</div>
|
||||
|
||||
<div class="mui-panel">
|
||||
<h2>US Test Pages</h2>
|
||||
<a href="/test/pages/en-us-retail/portfolio4.html">Portfolio <sup><strong>NEWEST</strong></sup></a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/performance2.html">Performance</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/pricing2.html">Pricing</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/product-landing-page.html">Product Landing</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/tax-information2.html">Tax Information</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/ppss.html">PPSS</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/historical-average-annual-total-returns-placeholder.html">Historical AATR Modal Placeholder</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/historical-cumulative-total-returns-placeholder.html">Historical CTR Modal Placeholder</a>
|
||||
<h2>US Broken Test Pages</h2>
|
||||
<a href="/test/pages/en-us-retail/distributions2.html">US Distributions</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/overview2.html">Overview</a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/portfolio2.html">Portfolio <sup>NEW</sup></a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/portfolio3.html">Portfolio <sup><strong>NEWER</strong></sup></a>
|
||||
<br>
|
||||
<a href="/test/pages/en-us-retail/documents.html">Documents</a>
|
||||
<br>
|
||||
<a href="/test/reference/gateway/gatewayPage.html">Gateway</a>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
5
jest-portfolio-reducers.json
Normal file
5
jest-portfolio-reducers.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"verbose": true,
|
||||
"rootDir": "src/components/products/portfolio",
|
||||
"testRegex": "(util|lib|value-converters).*.spec.js$"
|
||||
}
|
5
jest-ppss-reducers.json
Normal file
5
jest-ppss-reducers.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"verbose": true,
|
||||
"rootDir": "src/components/products/ppss/ft-ppss",
|
||||
"testRegex": "(util|lib|value-converters).*.spec.js$"
|
||||
}
|
5
jest-reducers.json
Normal file
5
jest-reducers.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"verbose": true,
|
||||
"rootDir": "src",
|
||||
"testRegex": "(util|lib|value-converters).*.spec.js$"
|
||||
}
|
12
jsconfig.json
Normal file
12
jsconfig.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES6"
|
||||
},
|
||||
"exclude": [
|
||||
"assets",
|
||||
"coverage",
|
||||
"node_modules",
|
||||
"ui-toolkit"
|
||||
]
|
||||
}
|
68
karma.conf.js
Normal file
68
karma.conf.js
Normal file
@ -0,0 +1,68 @@
|
||||
'use strict';
|
||||
const path = require('path');
|
||||
const project = require('./aurelia_project/aurelia.json');
|
||||
|
||||
let testSrc = [
|
||||
{ pattern: project.unitTestRunner.source, included: false },
|
||||
{ pattern: 'test/unit/setup.js', included: false },
|
||||
{ pattern: 'src/**/*.fixture.json', included: false },
|
||||
'test/aurelia-karma.js'
|
||||
];
|
||||
|
||||
let output = project.platform.output;
|
||||
let appSrc = project.build.bundles.map(x => path.join(output, x.name));
|
||||
let entryIndex = appSrc.indexOf(path.join(output, project.build.loader.configTarget));
|
||||
let entryBundle = appSrc.splice(entryIndex, 1)[0];
|
||||
let files = [entryBundle].concat(testSrc).concat(appSrc);
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: [project.testFramework.id],
|
||||
files: files,
|
||||
exclude: [
|
||||
'src/**/lib/**/*.spec.js',
|
||||
'src/**/util/**/*.spec.js',
|
||||
'src/**/value-converters/**/*.spec.js'
|
||||
],
|
||||
preprocessors: {
|
||||
[project.unitTestRunner.source]: [project.transpiler.id],
|
||||
['test/unit/setup.js']: [project.transpiler.id],
|
||||
'src/**/!(*.spec)+(.js)': ['coverage']
|
||||
},
|
||||
'babelPreprocessor': { options: project.transpiler.options },
|
||||
reporters: ['coverage', 'spec'],
|
||||
coverageReporter: {
|
||||
type: 'html',
|
||||
dir: 'coverage/',
|
||||
subdir: 'components',
|
||||
includeAllSources: true
|
||||
},
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
// browsers: ['PhantomJS'],
|
||||
browsers: ['Chrome'],
|
||||
// browsers: ['ChromeNoSandboxHeadless'], // headless Chrome should work from v59+
|
||||
customLaunchers: {
|
||||
ChromeNoSandboxHeadless: {
|
||||
base: 'Chrome',
|
||||
flags: [
|
||||
'--no-sandbox',
|
||||
// See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
|
||||
// https://www.chromestatus.com/features/5678767817097216
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
// Without a remote debugging port, Google Chrome exits immediately.
|
||||
' --remote-debugging-port=9222'
|
||||
]
|
||||
}
|
||||
},
|
||||
singleRun: true,
|
||||
phantomjsLauncher: {
|
||||
// Have phantomjs exit if a ResourceError is encountered (useful if karma exits without killing phantom)
|
||||
exitOnResourceError: true
|
||||
}
|
||||
});
|
||||
};
|
1
labels-array.json
Normal file
1
labels-array.json
Normal file
@ -0,0 +1 @@
|
||||
["1-yr","10-Hypo-text-Bottom","10-Hypo-text-Top","10-yr","10yr","15-yr","1yr","250k-499k","3-yr","3yr","5-yr","500k-999k","50k-99k","52-week-range-heading","5yr","7-day-current-yield","7-day-effective-yield","actual-allocation","actual-allocation-type","add-to-factsheet-to-cart","add-to-favourite.add","additional-tax-information","advantage-hypo-para","after-shares-sold","all","all-fund-distribution-message","allocation","amount","AS_OF_DATE","as-of","asset-class-exposure-calculation-type","assetclass","at-nav","ataatr-info-text","aum","before-shares-sold","below-investment-grade","calendar-year-1yr","calendar-year-2yr","calendar-year-3yr","calendar-year-4yr","calendar-year-5yr","calendar-year-6yr","capital-gain-distributions","cash-and-cash-equv","category","chart","chart-alternate","close","compare-selected-funds","component-heading","component-sub-heading","component-subheading","component-subheading-sector-exposure","contact-us-info","cumulative-performance-heading","currency","daily-fund-prices","date-selector-info","direct-usgovt-obligations","discrete-1yr","discrete-2yr","discrete-3yr","discrete-4yr","discrete-5yr","distribution-date","distribution-rate-and-breakpoints","distributions","distributions-estimates","dividend-distributions","dividends","dividends-per-share","dividends-received-deduction","domicile","download","download-all-holdings","etf","ex-date","ex-dividend-date","expenses-collapse","expenses-collapse.cdsc","expenses-collapse.gross","expenses-collapse.max","expenses-collapse.net","expenses-collapse.ratio","expenses-collapse.sales-charges","factsheet","fav","favouriteonly","federal-id-number","find-a-fund","flag.hard-closure","flag.soft-closure","for-tax-year","foreign-tax-credit-information-label","fund-identifiers","fund-information","fund-name","fund-number","fund-with-sales-charge","fund-without-sales-charge","fundname-shareclass-seperator","funds-selected","further-information","geographic-exposure-calculation-type","gross-exposure-calculation-type","gross-exposure-coloum","heading","highest-lowest-nav","highest-nav","historical-data-link-text","holdings","hypothetical-chart-title","important-fund-info","inception","inception-date","income-use","info-collapse-content","info-modal-content","info-modal-content-2","info-modal-content-3","investment","investment-grade","isin","issuers","less-than-50k","life","long-term-cap-gains-label","lowest-nav","manager-allocation-calc-type","market-value","mdash","millions-indicator","money-funds","month","month-end","morningstar-category","morningstar-rating","morningstar.not-rated","morningstar.rating-too-low","name","nav","NAV","NAV-as-of-post","NAV-as-of-pre","nav-change","NAV-change","NAV-high","NAV-low","NAV-sub","nav-total-return","nb-funds-in-category","net-exposure-calculation-type","net-exposure-coloum","next","no-data-msg","no-distribution-paid-message","no-distributions","no-managers-message","no-results-message","non-tax-free-income-fund-para","non-taxable-return-of-capital-label","not-applicable-message","not-rated","notional-value","of","off","on","ongoing-charges","ordinary-dividends-info-text","ordinary-dividends-label","other","overall","pay-date-label","payable-date","performance-annualised-heading","performance-tab","POP","POP-sales-charge-heading","POP-sub","positions-heading","positions-not-available","previous","qualified-dividend-income-info-text","qualified-dividend-income-label","quarter-end","ratings-tab","read-important","record-date","record-date-label","refunded","reinvestment-date","reinvestment-price","reset-to-current","sales-charge","salescharges","schedules","search-fields","sector","security-name","share-class","share-prices-heading","show-performance","showing","specified-private-activity-bond-interest","statistics-heading","subheading","symbol","table","table-heading","target-allocation","target-allocation-type","tax-exempt-income-jurisdiction-label","tax-exempt-income-label","tax-year","ter","ticker","total-distributions-label","total-label","updated-daily","updated-monthly","value","view-historical-data","weight","year","year-end-message","year-to-date-distributions-per-share","yield-tab","yield.w-waiver","yield.wo-waiver","ytd","ytd-total-ret"]
|
340
labels-object.json
Normal file
340
labels-object.json
Normal file
@ -0,0 +1,340 @@
|
||||
{
|
||||
"1-yr": [
|
||||
"1 Yr",
|
||||
"1 YR"
|
||||
],
|
||||
"10-Hypo-text-Bottom": [],
|
||||
"10-Hypo-text-Top": [],
|
||||
"10-yr": [
|
||||
"10 Yr",
|
||||
"10 YR"
|
||||
],
|
||||
"10yr": "10 YR",
|
||||
"15-yr": [],
|
||||
"1yr": "1 YR",
|
||||
"250k-499k": [],
|
||||
"3-yr": [
|
||||
"3 Yr",
|
||||
"3 YR"
|
||||
],
|
||||
"3yr": "3 YR",
|
||||
"5-yr": [
|
||||
"5 Yr",
|
||||
"5 YR"
|
||||
],
|
||||
"500k-999k": [],
|
||||
"50k-99k": [],
|
||||
"52-week-range-heading": "52-week Range ($)",
|
||||
"5yr": "5 YR",
|
||||
"7-day-current-yield": "7 Day Current Yield",
|
||||
"7-day-effective-yield": "7 Day Effective Yield",
|
||||
"actual-allocation": "Actual Allocation",
|
||||
"actual-allocation-type": [],
|
||||
"add-to-factsheet-to-cart": "Add Fact Sheet to My Cart",
|
||||
"add-to-favourite.add": "Add to my Favorites",
|
||||
"additional-tax-information": "Additional Tax Information",
|
||||
"advantage-hypo-para": "Create a client-use report of the fund's performance, tailored for a specific client.",
|
||||
"after-shares-sold": "After Shares Sold",
|
||||
"all": "All",
|
||||
"all-fund-distribution-message": "All fund distributions will vary depending on current market conditions, and past distributions are not indicative of future trends.",
|
||||
"allocation": [],
|
||||
"amount": [],
|
||||
"AS_OF_DATE": [],
|
||||
"as-of": [
|
||||
"As of",
|
||||
"As of "
|
||||
],
|
||||
"asset-class-exposure-calculation-type": "% of Total asset exposure calculation-type",
|
||||
"assetclass": "Asset Class",
|
||||
"at-nav": "at NAV",
|
||||
"ataatr-info-text": [],
|
||||
"aum": [],
|
||||
"before-shares-sold": "Before Shares Sold",
|
||||
"below-investment-grade": "Below Investment Grade",
|
||||
"calendar-year-1yr": "Year 1",
|
||||
"calendar-year-2yr": "Year 2",
|
||||
"calendar-year-3yr": "Year 3",
|
||||
"calendar-year-4yr": "Year 4",
|
||||
"calendar-year-5yr": "Year 5",
|
||||
"calendar-year-6yr": "Year 6",
|
||||
"capital-gain-distributions": [],
|
||||
"cash-and-cash-equv": "Cash & Cash Equivalents",
|
||||
"category": [],
|
||||
"chart": "Chart",
|
||||
"chart-alternate": "No chart available for this data.",
|
||||
"close": [
|
||||
"Close",
|
||||
"close"
|
||||
],
|
||||
"compare-selected-funds": "Compare Selected Funds",
|
||||
"component-heading": [
|
||||
"Average Annual Total Returns",
|
||||
"Cumulative Total Returns",
|
||||
"HISTORICAL DATA - After-Tax Average Annual Total Returns",
|
||||
"HISTORICAL DATA - Average Annual Total Returns",
|
||||
"HISTORICAL DATA - Cumulative Total Returns",
|
||||
"Geographic Allocation",
|
||||
"Market Capitalisation",
|
||||
"Sector Allocation",
|
||||
"Geographic Breakdown",
|
||||
"Portfolio",
|
||||
"Asset Class Exposure",
|
||||
"Asset Allocation",
|
||||
"Commodities Sector Breakdown",
|
||||
"Coupon Rate",
|
||||
"credit quality exposure",
|
||||
"CURRENCY DISTRIBUTION",
|
||||
"Daily Fund Prices and Breakpoints",
|
||||
"Fixed Income Sector Breakdown",
|
||||
"Geographic Exposure",
|
||||
"Manager Roster",
|
||||
"Maturity Breakdown",
|
||||
"Pricing at",
|
||||
"Quality Breakdown",
|
||||
"sector breakdown",
|
||||
"sector exposure",
|
||||
"Strategy Breakdown",
|
||||
"Tax Information",
|
||||
"Top Five Holdings",
|
||||
"TOP TEN HOLDINGS"
|
||||
],
|
||||
"component-sub-heading": [
|
||||
"AFTER-TAX AVERAGE ANNUAL TOTAL RETURNS",
|
||||
"Average Annual Total Returns",
|
||||
"Cumulative Total Returns"
|
||||
],
|
||||
"component-subheading": [],
|
||||
"component-subheading-sector-exposure": "sub heading",
|
||||
"contact-us-info": "For information on tax years prior to 2008, please contact us.",
|
||||
"cumulative-performance-heading": [],
|
||||
"currency": "Currency",
|
||||
"daily-fund-prices": [],
|
||||
"date-selector-info": "Choose a month and year from the drop-menus above to show historical performance data.",
|
||||
"direct-usgovt-obligations": "Direct U.S.Gov't Obligations %",
|
||||
"discrete-1yr": "Dec-15 / Dec-16",
|
||||
"discrete-2yr": "Dec-14 / Dec-15",
|
||||
"discrete-3yr": "Dec-13 / Dec-14",
|
||||
"discrete-4yr": "Dec-12 / Dec-13",
|
||||
"discrete-5yr": "Dec-11 / Dec-12",
|
||||
"distribution-date": [],
|
||||
"distribution-rate-and-breakpoints": [],
|
||||
"distributions": [
|
||||
"Distributions",
|
||||
"DISTRIBUTIONS (PER SHARE)"
|
||||
],
|
||||
"distributions-estimates": [],
|
||||
"dividend-distributions": [],
|
||||
"dividends": [],
|
||||
"dividends-per-share": [],
|
||||
"dividends-received-deduction": "Dividends-Received Deduction %",
|
||||
"domicile": [],
|
||||
"download": [],
|
||||
"download-all-holdings": "Download all holdings (xls)",
|
||||
"etf": [],
|
||||
"ex-date": [],
|
||||
"ex-dividend-date": [],
|
||||
"expenses-collapse": "Expenses & Sales Charge",
|
||||
"expenses-collapse.cdsc": "CDSC",
|
||||
"expenses-collapse.gross": "Gross",
|
||||
"expenses-collapse.max": "Max",
|
||||
"expenses-collapse.net": "Net",
|
||||
"expenses-collapse.ratio": "Expense Ratio",
|
||||
"expenses-collapse.sales-charges": "Sales Charges",
|
||||
"factsheet": [],
|
||||
"fav": "FAV",
|
||||
"favouriteonly": "My Favorites Only",
|
||||
"federal-id-number": "Federal ID Number",
|
||||
"find-a-fund": [],
|
||||
"flag.hard-closure": "Closed to all investments",
|
||||
"flag.soft-closure": "This share class is closed to new investors",
|
||||
"for-tax-year": "for Tax Year",
|
||||
"foreign-tax-credit-information-label": "Foreign Tax Credit Information",
|
||||
"fund-identifiers": "Fund Identifiers",
|
||||
"fund-information": [],
|
||||
"fund-name": "Fund Name",
|
||||
"fund-number": "Fund Number",
|
||||
"fund-with-sales-charge": "Fund with Sales Charge (%) (POP)",
|
||||
"fund-without-sales-charge": "Fund without Sales Charge (%) (NAV)",
|
||||
"fundname-shareclass-seperator": "-",
|
||||
"funds-selected": "Funds Selected",
|
||||
"further-information": "Further-Information",
|
||||
"geographic-exposure-calculation-type": "% of Total geographic exposure calculation-type default 010 fund is not added",
|
||||
"gross-exposure-calculation-type": "% of Total gross-exposure for 998",
|
||||
"gross-exposure-coloum": "Gross Exposure",
|
||||
"heading": [],
|
||||
"highest-lowest-nav": [],
|
||||
"highest-nav": [],
|
||||
"historical-data-link-text": [
|
||||
"View Historical Data",
|
||||
"VIEW HISTORICAL DATA FOR LIQUID ASSETS"
|
||||
],
|
||||
"holdings": "Holdings",
|
||||
"hypothetical-chart-title": "HYPOTHETICAL $10K INVESTMENT",
|
||||
"important-fund-info": [],
|
||||
"inception": [
|
||||
"Inception",
|
||||
"since",
|
||||
"Since Inception"
|
||||
],
|
||||
"inception-date": "Inception Date",
|
||||
"income-use": [],
|
||||
"info-collapse-content": [
|
||||
"Test Content for Further Information",
|
||||
"<22>"
|
||||
],
|
||||
"info-modal-content": [
|
||||
"<p>Average annual total return shows the investment's average annual change in value over the indicated periods. It is not the same as a year-by-year annual return. Figures reflect reinvestment of dividends and capital gains.</p>",
|
||||
"<p>Cumulative total return shows the change in the investment's value over the time period indicated. Figures reflect reinvestment of dividends and capital gains.</p>",
|
||||
"<p>Net Asset Value (NAV) is the value of one share of the fund on a given day.</p>\n<p>NAV change is the change from the last quoted price.</p>\n<p>The Public Offering Price (POP) is the purchase price for each share of the fund on a given day. It includes the maximum initial sales charge.</p>",
|
||||
"<p><b>Alpha</b> <br />The difference between a fund's actual returns versus its expected performance, given its level of market risk as measured by beta. A positive alpha indicates the fund performed better than its beta would predict while a negative alpha indicates the fund's under performance based on the expectations indicated by the fund's beta. <br /> <br /><b>Beta</b> <br />A measure of a fund's volatility in relation to the stock market, as measured by a stated index. By definition, the beta of the stated index is 1; a fund with a higher beta has been more volatile than the index, and a fund with a lower beta has been less volatile than the index. <br /> <br /><b>Sharpe Ratio</b> <br />The Sharpe ratio, developed by Nobel Prize winner William Sharpe, provides a measure of a fund's historical risk-adjusted performance. A higher number indicates better historical risk-adjusted performance. <br /> <br /><b>Correlation</b><br />The linear relationship between two return series. Correlation shows the strength of the relationship between two return series. The higher the relationship, the more similar the returns. <br /> <br /><b>R-Squared</b> <br />This number indicates what percentage of a fund's performance fluctuation can be explained by movements in the benchmark index. R-squared (correlation) ranges from 0 to 100. An R-squared of 100 would mean that the fund is tracking its benchmark exactly. A low R-squared indicates that very few of the fund's movements are explained by movements of its benchmark. R-squared can help determine the significance of the fund's beta. A higher R-squared generally indicates a more useful beta. Lower R-squared means the fund's beta is less relevant to its performance. <br /> <br /><b>Standard Deviation</b> <br />This figure provides a statistical measure of the range of a fund's returns. A high standard deviation indicates a wide range of returns and thus greater volatility.</p>",
|
||||
"<p><b>Direct U.S. Government Obligations</b></p>\n<p>To determine the amount of income derived from these obligations, multiply the total ordinary dividends you received from the fund during the calendar year, as reported on Form 1099-DIV, box 1a by the percentage shown. The percentage of direct U.S. government obligation interest available for tax-exempt treatment may be limited in states that require the fund to meet certain minimum thresholds. Please contact your tax advisor to determine the availability of exemptions in your state.</p>\n<p><b>Specified Private Activity Bond Interest</b></p>\n<p>This percentage represents the amount of Tax-Exempt Interest Dividends paid by a fund that are subject to the alternative minimum tax (AMT). The dollar amount of AMT reportable specified private activity bond interest paid to an individual shareholder is reported on Form 1099-DIV, box 11. Other shareholders can determine the AMT reportable specified private activity bond interest by multiplying the percentage shown by the total Tax-Exempt Income Dividends received during the year as reported on their annual Year-End Asset Summary Statement.</p>\n<p><b>Dividends-Received Deduction</b></p>\n<p>This percentage represents the amount of ordinary dividends paid (including short-term capital gains distributions) during the fund's fiscal year, as income qualifying for the dividends-received deduction.</p>"
|
||||
],
|
||||
"info-modal-content-2": "<p><b>Foreign Tax Credit Information</b><br />These amounts represent the foreign taxes paid and foreign source income as designated by the fund that is allocated to shareholders of record on the date(s) noted below. Foreign tax paid allocated to shareholders is reported on Form 1099-DIV, box 6 and is also included in box 1a, Total Ordinary Dividends. Form 1099-DIV also reports foreign source income paid to shareholders.</p>",
|
||||
"info-modal-content-3": "<p><b>Tax-Exempt Income by Jurisdiction</b><br />This table lists the percentage of your tax-exempt income dividends that may qualify for exemption in your state. (Please contact your tax advisor to determine the taxability of this income in your state.) To determine the amount of income derived from each jurisdiction, multiply the total tax-exempt interest you received from the fund during the calendar year, as reported on Form 1099-DIV, box 10 by the percentage shown.</p>",
|
||||
"investment": "Investment",
|
||||
"investment-grade": "Investment Grade",
|
||||
"isin": "ISIN",
|
||||
"issuers": "Number of Issuers",
|
||||
"less-than-50k": "Less than $50,000",
|
||||
"life": [
|
||||
"Since Inception",
|
||||
"Since inception"
|
||||
],
|
||||
"long-term-cap-gains-label": "Long-Term <br/>Cap Gains ($)",
|
||||
"lowest-nav": [],
|
||||
"manager-allocation-calc-type": [],
|
||||
"market-value": "Market Value",
|
||||
"mdash": "—",
|
||||
"millions-indicator": "(M)",
|
||||
"money-funds": "Money Funds",
|
||||
"month": [],
|
||||
"month-end": [
|
||||
"Month End",
|
||||
"MONTH END",
|
||||
"Month end"
|
||||
],
|
||||
"morningstar-category": "Morningstar Category",
|
||||
"morningstar-rating": "Morningstar Rating",
|
||||
"morningstar.not-rated": "This fund is not yet rated.",
|
||||
"morningstar.rating-too-low": "We do not publish a Morningstar Rating for this fund.",
|
||||
"name": [
|
||||
"",
|
||||
"Name"
|
||||
],
|
||||
"nav": "NAV",
|
||||
"NAV": "NAV",
|
||||
"NAV-as-of-post": " ",
|
||||
"NAV-as-of-pre": "on",
|
||||
"nav-change": "Nav change",
|
||||
"NAV-change": "NAV Change",
|
||||
"NAV-high": "NAV High",
|
||||
"NAV-low": "NAV Low",
|
||||
"NAV-sub": "(Net Asset Value)",
|
||||
"nav-total-return": "Average Annual Total Return at",
|
||||
"nb-funds-in-category": "Number of Funds in Category",
|
||||
"net-exposure-calculation-type": [
|
||||
"% of Total for default",
|
||||
"net-exposure-calculation-type for 948,894, funds"
|
||||
],
|
||||
"net-exposure-coloum": "Net Exposure",
|
||||
"next": "Next",
|
||||
"no-data-msg": [],
|
||||
"no-distribution-paid-message": "No Distributions Paid.",
|
||||
"no-distributions": [],
|
||||
"no-managers-message": [],
|
||||
"no-results-message": "No results match your search criteria",
|
||||
"non-tax-free-income-fund-para": "These amounts represent current year cash distributions paid by the fund and foreign taxes passed through (if any). These amounts are reported to shareholders on Form 1099-DIV.",
|
||||
"non-taxable-return-of-capital-label": "Non-Taxable <br/>Return of Capital ($)",
|
||||
"not-applicable-message": "Not applicable to this fund.",
|
||||
"not-rated": "Not Rated",
|
||||
"notional-value": "Notional Value",
|
||||
"of": "of",
|
||||
"off": "Off",
|
||||
"on": [
|
||||
"On",
|
||||
"on"
|
||||
],
|
||||
"ongoing-charges": [],
|
||||
"ordinary-dividends-info-text": "<p>Ordinary Dividends represent dividends paid by a fund that are derived from interest, dividends, net short-term capital gains and other types of ordinary income earned by the fund. For a fund that elects to pass through its foreign taxes paid (a non-cash item), a shareholders allotted share of foreign taxes has been added to the Ordinary Dividend cash distributions received by the shareholder. Ordinary Dividends equals the amount reported to shareholders on Form 1099-DIV, box 1a.</p>",
|
||||
"ordinary-dividends-label": "Ordinary <br/>Dividends ($)",
|
||||
"other": "Other",
|
||||
"overall": "Overall",
|
||||
"pay-date-label": "Pay <br/>Date",
|
||||
"payable-date": [],
|
||||
"performance-annualised-heading": [],
|
||||
"performance-tab": "Performance",
|
||||
"POP": "POP",
|
||||
"POP-sales-charge-heading": "Pop and Sales Charge at Breakpoints",
|
||||
"POP-sub": "(Public Offering Price)",
|
||||
"positions-heading": "Positions",
|
||||
"positions-not-available": "Not Available.",
|
||||
"previous": "Previous",
|
||||
"qualified-dividend-income-info-text": "<p>This amount reflects the portion of a fund's distribution of Ordinary Dividends reported on Form 1099-DIV, box 1a that may be eligible for the 15% tax rate for individuals (0% for lower tax bracket taxpayers). This amount represents both cash distributions and non-cash amounts, such as foreign taxes paid, that have been allocated to shareholders. Qualified Dividend Income equals the amount reported to shareholders on Form 1099-DIV, box 1b.</p>",
|
||||
"qualified-dividend-income-label": "Qualified <br />Dividend Income ($)",
|
||||
"quarter-end": [
|
||||
"Quarter End",
|
||||
"QUARTER END",
|
||||
"Quarter end"
|
||||
],
|
||||
"ratings-tab": "Ratings",
|
||||
"read-important": [
|
||||
"Read important information about results and other investment disclosures",
|
||||
"<b>\n Read important information about performance results and other disclosures\n</b>"
|
||||
],
|
||||
"record-date": [],
|
||||
"record-date-label": "Record <br/>Date",
|
||||
"refunded": "Refunded",
|
||||
"reinvestment-date": [],
|
||||
"reinvestment-price": [],
|
||||
"reset-to-current": "Reset to Current",
|
||||
"sales-charge": "Sales Charge",
|
||||
"salescharges": "Sales Charges",
|
||||
"schedules": [],
|
||||
"search-fields": [
|
||||
"Filter by keyword",
|
||||
"Filter by Keyword"
|
||||
],
|
||||
"sector": "Sector",
|
||||
"security-name": "Security Name",
|
||||
"share-class": "Class",
|
||||
"share-prices-heading": "Share Prices ($)",
|
||||
"show-performance": "Show Performance",
|
||||
"showing": "Showing",
|
||||
"specified-private-activity-bond-interest": "Specified Private Activity Bond Interest %",
|
||||
"statistics-heading": "Statistics",
|
||||
"subheading": [],
|
||||
"symbol": "TICKER",
|
||||
"table": "Table",
|
||||
"table-heading": "% of Total (Exposure)",
|
||||
"target-allocation": "Target Allocation",
|
||||
"target-allocation-type": [],
|
||||
"tax-exempt-income-jurisdiction-label": "Tax-Exempt Income Jurisdiction",
|
||||
"tax-exempt-income-label": "Tax-Exempt <br/>Income ($)",
|
||||
"tax-year": "Tax year:",
|
||||
"ter": [],
|
||||
"ticker": "Ticker",
|
||||
"total-distributions-label": "Total <br/>Distributions ($)",
|
||||
"total-label": "Total",
|
||||
"updated-daily": "(updated daily)",
|
||||
"updated-monthly": "(updated monthly)",
|
||||
"value": [
|
||||
"",
|
||||
"Value"
|
||||
],
|
||||
"view-historical-data": [],
|
||||
"weight": "Weight (%)",
|
||||
"year": [],
|
||||
"year-end-message": "Tax information will be posted by mid-February.",
|
||||
"year-to-date-distributions-per-share": [],
|
||||
"yield-tab": "Yield",
|
||||
"yield.w-waiver": "w/ waiver",
|
||||
"yield.wo-waiver": "w/o waiver",
|
||||
"ytd": [
|
||||
"YTD",
|
||||
"ytd"
|
||||
],
|
||||
"ytd-total-ret": [
|
||||
"YTD Total return at Nav",
|
||||
"<abbr title=\"Year to Date\">YTD</abbr> Total return at Nav"
|
||||
]
|
||||
}
|
BIN
microfab.gif
Normal file
BIN
microfab.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
2
nbproject/private/private.properties
Normal file
2
nbproject/private/private.properties
Normal file
@ -0,0 +1,2 @@
|
||||
auxiliary.org-netbeans-modules-javascript-karma.config=karma.conf.js
|
||||
browser=Chrome.INTEGRATED
|
7
nbproject/private/private.xml
Normal file
7
nbproject/private/private.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<_0:editor-bookmarks xmlns:_0="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||
<group/>
|
||||
</open-files>
|
||||
</project-private>
|
22
nbproject/project.properties
Normal file
22
nbproject/project.properties
Normal file
@ -0,0 +1,22 @@
|
||||
auxiliary.org-netbeans-modules-css-prep.less_2e_compiler_2e_options=
|
||||
auxiliary.org-netbeans-modules-css-prep.less_2e_enabled=false
|
||||
auxiliary.org-netbeans-modules-css-prep.less_2e_mappings=/less:/css
|
||||
auxiliary.org-netbeans-modules-css-prep.sass_2e_compiler_2e_options=
|
||||
auxiliary.org-netbeans-modules-css-prep.sass_2e_configured=true
|
||||
auxiliary.org-netbeans-modules-css-prep.sass_2e_enabled=false
|
||||
auxiliary.org-netbeans-modules-css-prep.sass_2e_mappings=/scss:/css
|
||||
auxiliary.org-netbeans-modules-javascript-nodejs.enabled=false
|
||||
auxiliary.org-netbeans-modules-javascript-nodejs.node_2e_default=true
|
||||
auxiliary.org-netbeans-modules-javascript-nodejs.run_2e_enabled=false
|
||||
auxiliary.org-netbeans-modules-javascript-nodejs.sync_2e_enabled=true
|
||||
auxiliary.org-netbeans-modules-javascript2-json.json_2e_comments=true
|
||||
auxiliary.org-netbeans-modules-javascript2-requirejs.enabled=true
|
||||
auxiliary.org-netbeans-modules-web-clientproject-api.js_2e_libs_2e_folder=js/libs
|
||||
browser.run=true
|
||||
file.reference.frontend-projects-web-platform=.
|
||||
file.reference.web-platform-src=src
|
||||
files.encoding=UTF-8
|
||||
site.root.folder=${file.reference.frontend-projects-web-platform}
|
||||
source.folder=${file.reference.web-platform-src}
|
||||
start.file=index.html
|
||||
web.context.root=/
|
9
nbproject/project.xml
Normal file
9
nbproject/project.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.web.clientproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/clientside-project/1">
|
||||
<name>ft-web-platform</name>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
127
package.json
Normal file
127
package.json
Normal file
@ -0,0 +1,127 @@
|
||||
{
|
||||
"name": "ft-web-platform",
|
||||
"description": "Platform functionality for retail web sites",
|
||||
"version": "0.1.0",
|
||||
"license": "Franklin Templeton Investments",
|
||||
"repository": {
|
||||
"type": "svn",
|
||||
"url": "https://sourcemgmtsvn.noam.corp.frk.com:18080/svn/globalweb/branches/GW-Maintenance/frontend-projects/web-platform"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"test-reducers": "jest --config jest-reducers.json --coverage",
|
||||
"test-portfolio-reducers": "jest --config jest-portfolio-reducers.json --coverage --watch",
|
||||
"test-ppss-reducers": "jest --config jest-ppss-reducers.json --coverage --watch",
|
||||
"coverage": "jest --coverage",
|
||||
"au-build": "au build",
|
||||
"au-build-dev": "au build --dev",
|
||||
"au-build-js": "au build --js",
|
||||
"au-build-css": "au build --alan",
|
||||
"au-lint-css": "au lint-css",
|
||||
"au-lint-js": "au lint-js",
|
||||
"au-process-assets": "au process-assets",
|
||||
"au-process-css": "au process-css",
|
||||
"au-process-markup": "au process-markup",
|
||||
"au-test": "au test --bl",
|
||||
"au-run": "au run --watch",
|
||||
"au-run-dev": "au run --watch --dev"
|
||||
},
|
||||
"jest": {
|
||||
"verbose": true,
|
||||
"rootDir": "src"
|
||||
},
|
||||
"dependencies": {
|
||||
"aurelia-animator-css": "^1.0.1",
|
||||
"aurelia-bootstrapper": "^2.1.1",
|
||||
"aurelia-fetch-client": "^1.1.2",
|
||||
"aurelia-framework": "^1.1.0",
|
||||
"aurelia-pal-browser": "^1.2.0",
|
||||
"bluebird": "^3.5.0",
|
||||
"highcharts": "^5.0.9",
|
||||
"lodash": "^4.17.4",
|
||||
"moment": "^2.18.1",
|
||||
"moment-parseformat": "^2.1.4",
|
||||
"redux": "^3.6.0",
|
||||
"requirejs": "^2.3.3",
|
||||
"requirejs-text": "^2.0.15",
|
||||
"responsive-toolkit": "^2.6.3",
|
||||
"whatwg-fetch": "^2.0.3"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"devDependencies": {
|
||||
"attrchange": "^1.0.1",
|
||||
"aurelia-cli": "^0.29.0",
|
||||
"aurelia-testing": "^1.0.0-beta.2.0.1",
|
||||
"aurelia-tools": "^1.0.0",
|
||||
"autoprefixer": "^6.7.7",
|
||||
"babel-eslint": "^6.0.4",
|
||||
"babel-plugin-syntax-flow": "^6.8.0",
|
||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||
"babel-plugin-transform-es2015-modules-amd": "^6.8.0",
|
||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.10.3",
|
||||
"babel-plugin-transform-flow-strip-types": "^6.8.0",
|
||||
"babel-polyfill": "^6.9.1",
|
||||
"babel-preset-es2015": "^6.9.0",
|
||||
"babel-preset-stage-1": "^6.5.0",
|
||||
"babel-register": "^6.9.0",
|
||||
"bootstrap": "^3.3.7",
|
||||
"bootstrap-sass": "^3.3.7",
|
||||
"browser-sync": "^2.13.0",
|
||||
"compression": "^1.6.2",
|
||||
"connect-history-api-fallback": "^1.2.0",
|
||||
"express": "^4.15.3",
|
||||
"express-cache-response": "^1.0.2",
|
||||
"express-http-proxy": "^1.0.3",
|
||||
"glob": "^7.1.1",
|
||||
"gulp": "github:gulpjs/gulp#4.0",
|
||||
"gulp-babel": "^6.1.2",
|
||||
"gulp-changed-in-place": "^2.0.3",
|
||||
"gulp-clean": "^0.3.2",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-cssnano": "^2.1.2",
|
||||
"gulp-debug": "^3.0.0",
|
||||
"gulp-download": "0.0.1",
|
||||
"gulp-eslint": "^2.1.0",
|
||||
"gulp-htmlmin": "^3.0.0",
|
||||
"gulp-jest": "^1.0.0",
|
||||
"gulp-json-format": "^1.0.0",
|
||||
"gulp-lintspaces": "^0.5.0",
|
||||
"gulp-notify": "^2.2.0",
|
||||
"gulp-plumber": "^1.1.0",
|
||||
"gulp-postcss": "^6.2.0",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-sass": "^3.0.0",
|
||||
"gulp-sonar": "^3.0.1",
|
||||
"gulp-sourcemaps": "^2.0.0-alpha",
|
||||
"gulp-stylelint": "^3.6.1",
|
||||
"gulp-uglify": "^2.1.2",
|
||||
"gulp-util": "^3.0.8",
|
||||
"gulp-zip": "^3.2.0",
|
||||
"highlight.js": "^9.9.0",
|
||||
"http-proxy-middleware": "^0.17.4",
|
||||
"jasmine-core": "^2.4.1",
|
||||
"jest": "^18.0.0",
|
||||
"jest-cli": "^18.1.0",
|
||||
"jquery": "^3.1.1",
|
||||
"jquery-ui": "^1.12.1",
|
||||
"jsonfile": "^3.0.0",
|
||||
"karma": "^0.13.22",
|
||||
"karma-babel-preprocessor": "^6.0.1",
|
||||
"karma-chrome-launcher": "^1.0.1",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-jasmine": "^1.0.2",
|
||||
"karma-spec-reporter": "0.0.26",
|
||||
"marked": "^0.3.6",
|
||||
"minimatch": "^3.0.2",
|
||||
"mockdate": "^2.0.1",
|
||||
"owl.carousel": "^2.2.0",
|
||||
"pretty-hrtime": "^1.0.3",
|
||||
"request": "^2.81.0",
|
||||
"stylelint-config-standard": "^15.0.0",
|
||||
"through2": "^2.0.1",
|
||||
"uglify-js": "^2.6.3",
|
||||
"vinyl": "^2.0.1",
|
||||
"vinyl-map2": "^1.2.1"
|
||||
}
|
||||
}
|
231
scripts/getLabels.js
Normal file
231
scripts/getLabels.js
Normal file
@ -0,0 +1,231 @@
|
||||
/**
|
||||
* Created by mdonnel on 11/05/2017.
|
||||
*/
|
||||
|
||||
const meow = require('meow');
|
||||
const util = require('util');
|
||||
const jsonfile = require('jsonfile');
|
||||
const fs = require('fs');
|
||||
const glob = require('glob');
|
||||
const chalk = require('chalk');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
|
||||
const cli = meow({
|
||||
help: `
|
||||
Usage
|
||||
node getLabels.js -p <path> <options>
|
||||
|
||||
Path
|
||||
Where to check for html files. Only looks at .html files.
|
||||
|
||||
Outputs
|
||||
Outputs a labels.json file
|
||||
|
||||
Options
|
||||
-p, --path Path to search for HTMl files
|
||||
-r, --replace Replace label['id'] with getLabel('id')
|
||||
-l, --label Path to search for JSON files
|
||||
|
||||
Examples
|
||||
# Check all the html files in a given folder
|
||||
|
||||
node getLabels.js -p C:\\dev\\web-platform\\src\\components\\products
|
||||
|
||||
# Check all the html files in a given folder then replace all old label
|
||||
references with the new method
|
||||
|
||||
node getLabels.js -p C:\\dev\\web-platform\\src\\components\\products --replace
|
||||
`},
|
||||
{
|
||||
alias: {
|
||||
p: 'path',
|
||||
l: 'labels',
|
||||
r: 'replace'
|
||||
},
|
||||
default: {
|
||||
path: null,
|
||||
labels: null,
|
||||
replace: false
|
||||
},
|
||||
boolean: [ 'replace'],
|
||||
string: ['path', 'labels']
|
||||
});
|
||||
|
||||
|
||||
const globOptions = {};
|
||||
const options = {
|
||||
path: cli.flags.path,
|
||||
replace: cli.flags.replace,
|
||||
labels: cli.flags.labels
|
||||
};
|
||||
|
||||
const labelsPattern = /label\[\s?\'(\S+)\'\s?\]/g;
|
||||
const getLabelsPattern = /getLabel\(\s?\'(\S+)\'\s?\)/g;
|
||||
const fileArray = './labels-array.json';
|
||||
const fileObject = './labels-object.json';
|
||||
|
||||
const log = function() {
|
||||
process.stdout.write(util.format.apply(this, arguments) + '\n');
|
||||
};
|
||||
|
||||
function consolidateLabels(a) {
|
||||
const [labelList, labelObj] = a;
|
||||
const newLabels = {};
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (typeof labelObj === 'undefined') {
|
||||
return resolve();
|
||||
}
|
||||
log('Consolidating labels...');
|
||||
|
||||
for (const listItem of labelList) {
|
||||
const newEntry = [];
|
||||
labelObj.forEach((obj) => {
|
||||
if (Object.keys(obj).indexOf(listItem) !== -1) {
|
||||
const tempStr = obj[listItem];
|
||||
if (newEntry.indexOf(tempStr) === -1) {
|
||||
newEntry.push(tempStr);
|
||||
}
|
||||
}
|
||||
newLabels[listItem] = (newEntry.length === 1) ? newEntry[0] : newEntry;
|
||||
});
|
||||
}
|
||||
return resolve(newLabels);
|
||||
});
|
||||
}
|
||||
|
||||
function getLabels(rawLabels) {
|
||||
const newLabels = {};
|
||||
const lSource = _.get(rawLabels, 'provider.labels.label');
|
||||
|
||||
|
||||
if (typeof lSource !== 'undefined') {
|
||||
for (const item of lSource) {
|
||||
const key = _.get(item, 'key');
|
||||
newLabels[`${key.toString()}`] = _.get(item, 'value');
|
||||
}
|
||||
}
|
||||
|
||||
return newLabels;
|
||||
}
|
||||
function getAllLabels(labelPath, d) {
|
||||
const searchPath = `${labelPath}\\**\\*.json`;
|
||||
const found = [];
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (labelPath === null) {
|
||||
return resolve [d];
|
||||
}
|
||||
log(`Looking for label files: ${labelPath}`);
|
||||
glob(searchPath, globOptions, function(er, files) {
|
||||
files.forEach(function(element) {
|
||||
if (path.parse(element).name.indexOf('label') !== -1) {
|
||||
log(element);
|
||||
const labelfile = jsonfile.readFileSync(element);
|
||||
const labeldata = getLabels(labelfile);
|
||||
found.push(labeldata);
|
||||
}
|
||||
});
|
||||
|
||||
return resolve([d, found]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function processFiles(srcPath, doReplace = false) {
|
||||
const searchPath = `${srcPath}\\**\\*.html`;
|
||||
|
||||
log(`Searching: ${searchPath}`);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
let found = [];
|
||||
glob(searchPath, globOptions, function(er, files) {
|
||||
files.forEach(function(element) {
|
||||
try {
|
||||
const openedFile = fs.readFileSync(element, 'utf8');
|
||||
let matched;
|
||||
|
||||
// find plain labels
|
||||
matched = labelsPattern.exec(openedFile);
|
||||
while (matched) {
|
||||
const str = matched[1];
|
||||
if (found.indexOf(str) === -1) {
|
||||
found.push(str);
|
||||
}
|
||||
matched = labelsPattern.exec(openedFile);
|
||||
}
|
||||
|
||||
// find new getLabels
|
||||
matched = getLabelsPattern.exec(openedFile);
|
||||
while (matched) {
|
||||
const str = matched[1];
|
||||
if (found.indexOf(str) === -1) {
|
||||
found.push(str);
|
||||
}
|
||||
matched = getLabelsPattern.exec(openedFile);
|
||||
}
|
||||
|
||||
if (doReplace && labelsPattern.test(openedFile)) {
|
||||
log(`Updating: ${chalk.cyan(truncatePath(element, 4))}`);
|
||||
const newFile = openedFile.replace(labelsPattern, 'getLabel(\'$1\')');
|
||||
fs.writeFile(element, newFile);
|
||||
}
|
||||
} catch (e) {
|
||||
return reject(e);
|
||||
}
|
||||
});
|
||||
|
||||
found = found.sort(function(a, b) {
|
||||
return a.toLowerCase().localeCompare(b.toLowerCase());
|
||||
});
|
||||
return resolve(found);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function truncatePath(pathStr, parts) {
|
||||
const oldBits = pathStr.split('/');
|
||||
return ['...'].concat(oldBits.slice(oldBits.length - (parts - 1))).join('/');
|
||||
}
|
||||
function saveJSON(data) {
|
||||
log(chalk.yellow('Saving...'));
|
||||
jsonfile.writeFileSync(fileArray, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
function saveJSONObject(data) {
|
||||
log(chalk.yellow('Saving...'));
|
||||
jsonfile.writeFileSync(fileObject, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
function processLabels(opt) {
|
||||
log('GetLabels');
|
||||
if (opt.path !== null) {
|
||||
log(chalk.magenta('Working...'));
|
||||
processFiles(opt.path, opt.replace)
|
||||
.then((f) => {
|
||||
return saveJSON(f);
|
||||
})
|
||||
.then(function(d) {
|
||||
return getAllLabels(opt.labels, d);
|
||||
})
|
||||
.then((d) => {
|
||||
return consolidateLabels(d);
|
||||
})
|
||||
.then((f) => {
|
||||
return saveJSONObject(f);
|
||||
})
|
||||
.then(() => {
|
||||
log(chalk.green('Done.'));
|
||||
}).catch((e) => {
|
||||
log(chalk.red(e));
|
||||
});
|
||||
} else {
|
||||
log('Nothing to do. Try adding a path. Or use --help for help.');
|
||||
}
|
||||
}
|
||||
|
||||
processLabels(options);
|
||||
|
1
scripts/labels-array.json
Normal file
1
scripts/labels-array.json
Normal file
File diff suppressed because one or more lines are too long
340
scripts/labels-object.json
Normal file
340
scripts/labels-object.json
Normal file
@ -0,0 +1,340 @@
|
||||
{
|
||||
"1-yr": [
|
||||
"1 Yr",
|
||||
"1 YR"
|
||||
],
|
||||
"10-Hypo-text-Bottom": [],
|
||||
"10-Hypo-text-Top": [],
|
||||
"10-yr": [
|
||||
"10 Yr",
|
||||
"10 YR"
|
||||
],
|
||||
"10yr": "10 YR",
|
||||
"15-yr": [],
|
||||
"1yr": "1 YR",
|
||||
"250k-499k": [],
|
||||
"3-yr": [
|
||||
"3 Yr",
|
||||
"3 YR"
|
||||
],
|
||||
"3yr": "3 YR",
|
||||
"5-yr": [
|
||||
"5 Yr",
|
||||
"5 YR"
|
||||
],
|
||||
"500k-999k": [],
|
||||
"50k-99k": [],
|
||||
"52-week-range-heading": "52-week Range ($)",
|
||||
"5yr": "5 YR",
|
||||
"7-day-current-yield": "7 Day Current Yield",
|
||||
"7-day-effective-yield": "7 Day Effective Yield",
|
||||
"actual-allocation": "Actual Allocation",
|
||||
"actual-allocation-type": [],
|
||||
"add-to-factsheet-to-cart": "Add Fact Sheet to My Cart",
|
||||
"add-to-favourite.add": "Add to my Favorites",
|
||||
"additional-tax-information": "Additional Tax Information",
|
||||
"advantage-hypo-para": "Create a client-use report of the fund's performance, tailored for a specific client.",
|
||||
"after-shares-sold": "After Shares Sold",
|
||||
"all": "All",
|
||||
"all-fund-distribution-message": "All fund distributions will vary depending on current market conditions, and past distributions are not indicative of future trends.",
|
||||
"allocation": [],
|
||||
"amount": [],
|
||||
"AS_OF_DATE": [],
|
||||
"as-of": [
|
||||
"As of",
|
||||
"As of "
|
||||
],
|
||||
"asset-class-exposure-calculation-type": "% of Total asset exposure calculation-type",
|
||||
"assetclass": "Asset Class",
|
||||
"at-nav": "at NAV",
|
||||
"ataatr-info-text": [],
|
||||
"aum": [],
|
||||
"before-shares-sold": "Before Shares Sold",
|
||||
"below-investment-grade": "Below Investment Grade",
|
||||
"calendar-year-1yr": "Year 1",
|
||||
"calendar-year-2yr": "Year 2",
|
||||
"calendar-year-3yr": "Year 3",
|
||||
"calendar-year-4yr": "Year 4",
|
||||
"calendar-year-5yr": "Year 5",
|
||||
"calendar-year-6yr": "Year 6",
|
||||
"capital-gain-distributions": [],
|
||||
"cash-and-cash-equv": "Cash & Cash Equivalents",
|
||||
"category": [],
|
||||
"chart": "Chart",
|
||||
"chart-alternate": "No chart available for this data.",
|
||||
"close": [
|
||||
"Close",
|
||||
"close"
|
||||
],
|
||||
"compare-selected-funds": "Compare Selected Funds",
|
||||
"component-heading": [
|
||||
"Average Annual Total Returns",
|
||||
"Cumulative Total Returns",
|
||||
"HISTORICAL DATA - After-Tax Average Annual Total Returns",
|
||||
"HISTORICAL DATA - Average Annual Total Returns",
|
||||
"HISTORICAL DATA - Cumulative Total Returns",
|
||||
"Geographic Allocation",
|
||||
"Market Capitalisation",
|
||||
"Sector Allocation",
|
||||
"Geographic Breakdown",
|
||||
"Portfolio",
|
||||
"Asset Class Exposure",
|
||||
"Asset Allocation",
|
||||
"Commodities Sector Breakdown",
|
||||
"Coupon Rate",
|
||||
"credit quality exposure",
|
||||
"CURRENCY DISTRIBUTION",
|
||||
"Daily Fund Prices and Breakpoints",
|
||||
"Fixed Income Sector Breakdown",
|
||||
"Geographic Exposure",
|
||||
"Manager Roster",
|
||||
"Maturity Breakdown",
|
||||
"Pricing at",
|
||||
"Quality Breakdown",
|
||||
"sector breakdown",
|
||||
"sector exposure",
|
||||
"Strategy Breakdown",
|
||||
"Tax Information",
|
||||
"Top Five Holdings",
|
||||
"TOP TEN HOLDINGS"
|
||||
],
|
||||
"component-sub-heading": [
|
||||
"AFTER-TAX AVERAGE ANNUAL TOTAL RETURNS",
|
||||
"Average Annual Total Returns",
|
||||
"Cumulative Total Returns"
|
||||
],
|
||||
"component-subheading": [],
|
||||
"component-subheading-sector-exposure": "sub heading",
|
||||
"contact-us-info": "For information on tax years prior to 2008, please contact us.",
|
||||
"cumulative-performance-heading": [],
|
||||
"currency": "Currency",
|
||||
"daily-fund-prices": [],
|
||||
"date-selector-info": "Choose a month and year from the drop-menus above to show historical performance data.",
|
||||
"direct-usgovt-obligations": "Direct U.S.Gov't Obligations %",
|
||||
"discrete-1yr": "Dec-15 / Dec-16",
|
||||
"discrete-2yr": "Dec-14 / Dec-15",
|
||||
"discrete-3yr": "Dec-13 / Dec-14",
|
||||
"discrete-4yr": "Dec-12 / Dec-13",
|
||||
"discrete-5yr": "Dec-11 / Dec-12",
|
||||
"distribution-date": [],
|
||||
"distribution-rate-and-breakpoints": [],
|
||||
"distributions": [
|
||||
"Distributions",
|
||||
"DISTRIBUTIONS (PER SHARE)"
|
||||
],
|
||||
"distributions-estimates": [],
|
||||
"dividend-distributions": [],
|
||||
"dividends": [],
|
||||
"dividends-per-share": [],
|
||||
"dividends-received-deduction": "Dividends-Received Deduction %",
|
||||
"domicile": [],
|
||||
"download": [],
|
||||
"download-all-holdings": "Download all holdings (xls)",
|
||||
"etf": [],
|
||||
"ex-date": [],
|
||||
"ex-dividend-date": [],
|
||||
"expenses-collapse": "Expenses & Sales Charge",
|
||||
"expenses-collapse.cdsc": "CDSC",
|
||||
"expenses-collapse.gross": "Gross",
|
||||
"expenses-collapse.max": "Max",
|
||||
"expenses-collapse.net": "Net",
|
||||
"expenses-collapse.ratio": "Expense Ratio",
|
||||
"expenses-collapse.sales-charges": "Sales Charges",
|
||||
"factsheet": [],
|
||||
"fav": "FAV",
|
||||
"favouriteonly": "My Favorites Only",
|
||||
"federal-id-number": "Federal ID Number",
|
||||
"find-a-fund": [],
|
||||
"flag.hard-closure": "Closed to all investments",
|
||||
"flag.soft-closure": "This share class is closed to new investors",
|
||||
"for-tax-year": "for Tax Year",
|
||||
"foreign-tax-credit-information-label": "Foreign Tax Credit Information",
|
||||
"fund-identifiers": "Fund Identifiers",
|
||||
"fund-information": [],
|
||||
"fund-name": "Fund Name",
|
||||
"fund-number": "Fund Number",
|
||||
"fund-with-sales-charge": "Fund with Sales Charge (%) (POP)",
|
||||
"fund-without-sales-charge": "Fund without Sales Charge (%) (NAV)",
|
||||
"fundname-shareclass-seperator": "-",
|
||||
"funds-selected": "Funds Selected",
|
||||
"further-information": "Further-Information",
|
||||
"geographic-exposure-calculation-type": "% of Total geographic exposure calculation-type default 010 fund is not added",
|
||||
"gross-exposure-calculation-type": "% of Total gross-exposure for 998",
|
||||
"gross-exposure-coloum": "Gross Exposure",
|
||||
"heading": [],
|
||||
"highest-lowest-nav": [],
|
||||
"highest-nav": [],
|
||||
"historical-data-link-text": [
|
||||
"View Historical Data",
|
||||
"VIEW HISTORICAL DATA FOR LIQUID ASSETS"
|
||||
],
|
||||
"holdings": "Holdings",
|
||||
"hypothetical-chart-title": "HYPOTHETICAL $10K INVESTMENT",
|
||||
"important-fund-info": [],
|
||||
"inception": [
|
||||
"Inception",
|
||||
"since",
|
||||
"Since Inception"
|
||||
],
|
||||
"inception-date": "Inception Date",
|
||||
"income-use": [],
|
||||
"info-collapse-content": [
|
||||
"Test Content for Further Information",
|
||||
"<22>"
|
||||
],
|
||||
"info-modal-content": [
|
||||
"<p>Average annual total return shows the investment's average annual change in value over the indicated periods. It is not the same as a year-by-year annual return. Figures reflect reinvestment of dividends and capital gains.</p>",
|
||||
"<p>Cumulative total return shows the change in the investment's value over the time period indicated. Figures reflect reinvestment of dividends and capital gains.</p>",
|
||||
"<p>Net Asset Value (NAV) is the value of one share of the fund on a given day.</p>\n<p>NAV change is the change from the last quoted price.</p>\n<p>The Public Offering Price (POP) is the purchase price for each share of the fund on a given day. It includes the maximum initial sales charge.</p>",
|
||||
"<p><b>Alpha</b> <br />The difference between a fund's actual returns versus its expected performance, given its level of market risk as measured by beta. A positive alpha indicates the fund performed better than its beta would predict while a negative alpha indicates the fund's under performance based on the expectations indicated by the fund's beta. <br /> <br /><b>Beta</b> <br />A measure of a fund's volatility in relation to the stock market, as measured by a stated index. By definition, the beta of the stated index is 1; a fund with a higher beta has been more volatile than the index, and a fund with a lower beta has been less volatile than the index. <br /> <br /><b>Sharpe Ratio</b> <br />The Sharpe ratio, developed by Nobel Prize winner William Sharpe, provides a measure of a fund's historical risk-adjusted performance. A higher number indicates better historical risk-adjusted performance. <br /> <br /><b>Correlation</b><br />The linear relationship between two return series. Correlation shows the strength of the relationship between two return series. The higher the relationship, the more similar the returns. <br /> <br /><b>R-Squared</b> <br />This number indicates what percentage of a fund's performance fluctuation can be explained by movements in the benchmark index. R-squared (correlation) ranges from 0 to 100. An R-squared of 100 would mean that the fund is tracking its benchmark exactly. A low R-squared indicates that very few of the fund's movements are explained by movements of its benchmark. R-squared can help determine the significance of the fund's beta. A higher R-squared generally indicates a more useful beta. Lower R-squared means the fund's beta is less relevant to its performance. <br /> <br /><b>Standard Deviation</b> <br />This figure provides a statistical measure of the range of a fund's returns. A high standard deviation indicates a wide range of returns and thus greater volatility.</p>",
|
||||
"<p><b>Direct U.S. Government Obligations</b></p>\n<p>To determine the amount of income derived from these obligations, multiply the total ordinary dividends you received from the fund during the calendar year, as reported on Form 1099-DIV, box 1a by the percentage shown. The percentage of direct U.S. government obligation interest available for tax-exempt treatment may be limited in states that require the fund to meet certain minimum thresholds. Please contact your tax advisor to determine the availability of exemptions in your state.</p>\n<p><b>Specified Private Activity Bond Interest</b></p>\n<p>This percentage represents the amount of Tax-Exempt Interest Dividends paid by a fund that are subject to the alternative minimum tax (AMT). The dollar amount of AMT reportable specified private activity bond interest paid to an individual shareholder is reported on Form 1099-DIV, box 11. Other shareholders can determine the AMT reportable specified private activity bond interest by multiplying the percentage shown by the total Tax-Exempt Income Dividends received during the year as reported on their annual Year-End Asset Summary Statement.</p>\n<p><b>Dividends-Received Deduction</b></p>\n<p>This percentage represents the amount of ordinary dividends paid (including short-term capital gains distributions) during the fund's fiscal year, as income qualifying for the dividends-received deduction.</p>"
|
||||
],
|
||||
"info-modal-content-2": "<p><b>Foreign Tax Credit Information</b><br />These amounts represent the foreign taxes paid and foreign source income as designated by the fund that is allocated to shareholders of record on the date(s) noted below. Foreign tax paid allocated to shareholders is reported on Form 1099-DIV, box 6 and is also included in box 1a, Total Ordinary Dividends. Form 1099-DIV also reports foreign source income paid to shareholders.</p>",
|
||||
"info-modal-content-3": "<p><b>Tax-Exempt Income by Jurisdiction</b><br />This table lists the percentage of your tax-exempt income dividends that may qualify for exemption in your state. (Please contact your tax advisor to determine the taxability of this income in your state.) To determine the amount of income derived from each jurisdiction, multiply the total tax-exempt interest you received from the fund during the calendar year, as reported on Form 1099-DIV, box 10 by the percentage shown.</p>",
|
||||
"investment": "Investment",
|
||||
"investment-grade": "Investment Grade",
|
||||
"isin": "ISIN",
|
||||
"issuers": "Number of Issuers",
|
||||
"less-than-50k": "Less than $50,000",
|
||||
"life": [
|
||||
"Since Inception",
|
||||
"Since inception"
|
||||
],
|
||||
"long-term-cap-gains-label": "Long-Term <br/>Cap Gains ($)",
|
||||
"lowest-nav": [],
|
||||
"manager-allocation-calc-type": [],
|
||||
"market-value": "Market Value",
|
||||
"mdash": "—",
|
||||
"millions-indicator": "(M)",
|
||||
"money-funds": "Money Funds",
|
||||
"month": [],
|
||||
"month-end": [
|
||||
"Month End",
|
||||
"MONTH END",
|
||||
"Month end"
|
||||
],
|
||||
"morningstar-category": "Morningstar Category",
|
||||
"morningstar-rating": "Morningstar Rating",
|
||||
"morningstar.not-rated": "This fund is not yet rated.",
|
||||
"morningstar.rating-too-low": "We do not publish a Morningstar Rating for this fund.",
|
||||
"name": [
|
||||
"",
|
||||
"Name"
|
||||
],
|
||||
"nav": "NAV",
|
||||
"NAV": "NAV",
|
||||
"NAV-as-of-post": " ",
|
||||
"NAV-as-of-pre": "on",
|
||||
"nav-change": "Nav change",
|
||||
"NAV-change": "NAV Change",
|
||||
"NAV-high": "NAV High",
|
||||
"NAV-low": "NAV Low",
|
||||
"NAV-sub": "(Net Asset Value)",
|
||||
"nav-total-return": "Average Annual Total Return at",
|
||||
"nb-funds-in-category": "Number of Funds in Category",
|
||||
"net-exposure-calculation-type": [
|
||||
"% of Total for default",
|
||||
"net-exposure-calculation-type for 948,894, funds"
|
||||
],
|
||||
"net-exposure-coloum": "Net Exposure",
|
||||
"next": "Next",
|
||||
"no-data-msg": [],
|
||||
"no-distribution-paid-message": "No Distributions Paid.",
|
||||
"no-distributions": [],
|
||||
"no-managers-message": [],
|
||||
"no-results-message": "No results match your search criteria",
|
||||
"non-tax-free-income-fund-para": "These amounts represent current year cash distributions paid by the fund and foreign taxes passed through (if any). These amounts are reported to shareholders on Form 1099-DIV.",
|
||||
"non-taxable-return-of-capital-label": "Non-Taxable <br/>Return of Capital ($)",
|
||||
"not-applicable-message": "Not applicable to this fund.",
|
||||
"not-rated": "Not Rated",
|
||||
"notional-value": "Notional Value",
|
||||
"of": "of",
|
||||
"off": "Off",
|
||||
"on": [
|
||||
"On",
|
||||
"on"
|
||||
],
|
||||
"ongoing-charges": [],
|
||||
"ordinary-dividends-info-text": "<p>Ordinary Dividends represent dividends paid by a fund that are derived from interest, dividends, net short-term capital gains and other types of ordinary income earned by the fund. For a fund that elects to pass through its foreign taxes paid (a non-cash item), a shareholders allotted share of foreign taxes has been added to the Ordinary Dividend cash distributions received by the shareholder. Ordinary Dividends equals the amount reported to shareholders on Form 1099-DIV, box 1a.</p>",
|
||||
"ordinary-dividends-label": "Ordinary <br/>Dividends ($)",
|
||||
"other": "Other",
|
||||
"overall": "Overall",
|
||||
"pay-date-label": "Pay <br/>Date",
|
||||
"payable-date": [],
|
||||
"performance-annualised-heading": [],
|
||||
"performance-tab": "Performance",
|
||||
"POP": "POP",
|
||||
"POP-sales-charge-heading": "Pop and Sales Charge at Breakpoints",
|
||||
"POP-sub": "(Public Offering Price)",
|
||||
"positions-heading": "Positions",
|
||||
"positions-not-available": "Not Available.",
|
||||
"previous": "Previous",
|
||||
"qualified-dividend-income-info-text": "<p>This amount reflects the portion of a fund's distribution of Ordinary Dividends reported on Form 1099-DIV, box 1a that may be eligible for the 15% tax rate for individuals (0% for lower tax bracket taxpayers). This amount represents both cash distributions and non-cash amounts, such as foreign taxes paid, that have been allocated to shareholders. Qualified Dividend Income equals the amount reported to shareholders on Form 1099-DIV, box 1b.</p>",
|
||||
"qualified-dividend-income-label": "Qualified <br />Dividend Income ($)",
|
||||
"quarter-end": [
|
||||
"Quarter End",
|
||||
"QUARTER END",
|
||||
"Quarter end"
|
||||
],
|
||||
"ratings-tab": "Ratings",
|
||||
"read-important": [
|
||||
"Read important information about results and other investment disclosures",
|
||||
"<b>\n Read important information about performance results and other disclosures\n</b>"
|
||||
],
|
||||
"record-date": [],
|
||||
"record-date-label": "Record <br/>Date",
|
||||
"refunded": "Refunded",
|
||||
"reinvestment-date": [],
|
||||
"reinvestment-price": [],
|
||||
"reset-to-current": "Reset to Current",
|
||||
"sales-charge": "Sales Charge",
|
||||
"salescharges": "Sales Charges",
|
||||
"schedules": [],
|
||||
"search-fields": [
|
||||
"Filter by keyword",
|
||||
"Filter by Keyword"
|
||||
],
|
||||
"sector": "Sector",
|
||||
"security-name": "Security Name",
|
||||
"share-class": "Class",
|
||||
"share-prices-heading": "Share Prices ($)",
|
||||
"show-performance": "Show Performance",
|
||||
"showing": "Showing",
|
||||
"specified-private-activity-bond-interest": "Specified Private Activity Bond Interest %",
|
||||
"statistics-heading": "Statistics",
|
||||
"subheading": [],
|
||||
"symbol": "TICKER",
|
||||
"table": "Table",
|
||||
"table-heading": "% of Total (Exposure)",
|
||||
"target-allocation": "Target Allocation",
|
||||
"target-allocation-type": [],
|
||||
"tax-exempt-income-jurisdiction-label": "Tax-Exempt Income Jurisdiction",
|
||||
"tax-exempt-income-label": "Tax-Exempt <br/>Income ($)",
|
||||
"tax-year": "Tax year:",
|
||||
"ter": [],
|
||||
"ticker": "Ticker",
|
||||
"total-distributions-label": "Total <br/>Distributions ($)",
|
||||
"total-label": "Total",
|
||||
"updated-daily": "(updated daily)",
|
||||
"updated-monthly": "(updated monthly)",
|
||||
"value": [
|
||||
"",
|
||||
"Value"
|
||||
],
|
||||
"view-historical-data": [],
|
||||
"weight": "Weight (%)",
|
||||
"year": [],
|
||||
"year-end-message": "Tax information will be posted by mid-February.",
|
||||
"year-to-date-distributions-per-share": [],
|
||||
"yield-tab": "Yield",
|
||||
"yield.w-waiver": "w/ waiver",
|
||||
"yield.wo-waiver": "w/o waiver",
|
||||
"ytd": [
|
||||
"YTD",
|
||||
"ytd"
|
||||
],
|
||||
"ytd-total-ret": [
|
||||
"YTD Total return at Nav",
|
||||
"<abbr title=\"Year to Date\">YTD</abbr> Total return at Nav"
|
||||
]
|
||||
}
|
1
scripts/labels.json
Normal file
1
scripts/labels.json
Normal file
@ -0,0 +1 @@
|
||||
["1-yr","10-Hypo-text-Bottom","10-Hypo-text-Top","10-yr","10yr","15-yr","1yr","250k-499k","3-yr","3yr","5-yr","500k-999k","50k-99k","52-week-range-heading","5yr","7-day-current-yield","7-day-effective-yield","actual-allocation","actual-allocation-type","add-to-factsheet-to-cart","add-to-favourite.add","additional-tax-information","advantage-hypo-para","after-shares-sold","all","all-fund-distribution-message","allocation","amount","AS_OF_DATE","as-of","asset-class-exposure-calculation-type","assetclass","at-nav","ataatr-info-text","aum","before-shares-sold","below-investment-grade","calendar-year-1yr","calendar-year-2yr","calendar-year-3yr","calendar-year-4yr","calendar-year-5yr","calendar-year-6yr","capital-gain-distributions","cash-and-cash-equv","category","chart","chart-alternate","close","compare-selected-funds","component-heading","component-sub-heading","component-subheading","component-subheading-sector-exposure","contact-us-info","cumulative-performance-heading","currency","daily-fund-prices","date-selector-info","direct-usgovt-obligations","discrete-1yr","discrete-2yr","discrete-3yr","discrete-4yr","discrete-5yr","distribution-date","distribution-rate-and-breakpoints","distributions","distributions-estimates","dividend-distributions","dividends","dividends-per-share","dividends-received-deduction","domicile","download","download-all-holdings","etf","ex-date","ex-dividend-date","expenses-collapse","expenses-collapse.cdsc","expenses-collapse.gross","expenses-collapse.max","expenses-collapse.net","expenses-collapse.ratio","expenses-collapse.sales-charges","factsheet","fav","favouriteonly","federal-id-number","find-a-fund","flag.hard-closure","flag.soft-closure","for-tax-year","foreign-tax-credit-information-label","fund-identifiers","fund-information","fund-name","fund-number","fund-with-sales-charge","fund-without-sales-charge","fundname-shareclass-seperator","funds-selected","further-information","geographic-exposure-calculation-type","gross-exposure-calculation-type","gross-exposure-coloum","heading","highest-lowest-nav","highest-nav","historical-data-link-text","holdings","hypothetical-chart-title","important-fund-info","inception","inception-date","income-use","info-collapse-content","info-modal-content","info-modal-content-2","info-modal-content-3","investment","investment-grade","isin","issuers","less-than-50k","life","long-term-cap-gains-label","lowest-nav","manager-allocation-calc-type","market-value","mdash","millions-indicator","money-funds","month","month-end","morningstar-category","morningstar-rating","morningstar.not-rated","morningstar.rating-too-low","name","nav","NAV","NAV-as-of-post","NAV-as-of-pre","nav-change","NAV-change","NAV-high","NAV-low","NAV-sub","nav-total-return","nb-funds-in-category","net-exposure-calculation-type","net-exposure-coloum","next","no-data-msg","no-distribution-paid-message","no-distributions","no-managers-message","no-results-message","non-tax-free-income-fund-para","non-taxable-return-of-capital-label","not-applicable-message","not-rated","notional-value","of","off","on","ongoing-charges","ordinary-dividends-info-text","ordinary-dividends-label","other","overall","pay-date-label","payable-date","performance-annualised-heading","performance-tab","POP","POP-sales-charge-heading","POP-sub","positions-heading","positions-not-available","previous","qualified-dividend-income-info-text","qualified-dividend-income-label","quarter-end","ratings-tab","read-important","record-date","record-date-label","refunded","reinvestment-date","reinvestment-price","reset-to-current","sales-charge","salescharges","schedules","search-fields","sector","security-name","share-class","share-prices-heading","show-performance","showing","specified-private-activity-bond-interest","statistics-heading","subheading","symbol","table","table-heading","target-allocation","target-allocation-type","tax-exempt-income-jurisdiction-label","tax-exempt-income-label","tax-year","ter","ticker","total-distributions-label","total-label","updated-daily","updated-monthly","value","view-historical-data","weight","year","year-end-message","year-to-date-distributions-per-share","yield-tab","yield.w-waiver","yield.wo-waiver","ytd","ytd-total-ret"]
|
@ -0,0 +1,53 @@
|
||||
import {inject/*, LogManager*/} from 'aurelia-framework';
|
||||
// const logger = LogManager.getLogger('performance-annualised');
|
||||
|
||||
@inject('Store', Element)
|
||||
export class shareClassLinkListenerCustomAttribute {
|
||||
constructor(store, element) {
|
||||
this.element = element;
|
||||
store.subscribe(() => this.mapState(store.getState()));
|
||||
}
|
||||
|
||||
queryStringToJSON(href) {
|
||||
let params = href.slice(1).split('&');
|
||||
let result = {};
|
||||
|
||||
for (let param of params) {
|
||||
param = param.split('=');
|
||||
result[param[0]] = decodeURIComponent(param[1] || '');
|
||||
}
|
||||
|
||||
return JSON.parse(JSON.stringify(result));
|
||||
}
|
||||
|
||||
mapState(newState) {
|
||||
try {
|
||||
let currentPath = this.element.pathname;
|
||||
let currentQueryObject = this.queryStringToJSON(this.element.search);
|
||||
|
||||
let storeFundId = newState.products.app.currentFundId;
|
||||
let storeShareClass = newState.products.app.currentShareClass;
|
||||
|
||||
let newFundId;
|
||||
let newShareClass;
|
||||
|
||||
if (storeFundId !== 0) {
|
||||
newFundId = (storeFundId === currentQueryObject['FundID']) ? currentQueryObject['FundID'] : storeFundId;
|
||||
} else {
|
||||
newFundId = currentQueryObject['FundID'];
|
||||
}
|
||||
|
||||
if (storeShareClass !== '') {
|
||||
newShareClass = (storeShareClass === currentQueryObject['ShareClass']) ? currentQueryObject['ShareClass'] : storeShareClass;
|
||||
} else {
|
||||
newShareClass = currentQueryObject['ShareClass'];
|
||||
}
|
||||
|
||||
let newHref = currentPath + '?' + 'FundID=' + newFundId + '&ShareClass=' + newShareClass;
|
||||
this.element.href = newHref;
|
||||
} catch (e) {
|
||||
//logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
**Share class link listener**
|
||||
|
||||
This is a custom attribute which listens for changes made to the href attributes of anchor tags which have the
|
||||
*share-class-link-listener* attribute. These changes to the href are made from selecting a different class in the *ft-share-class-filter*
|
||||
custom element, present on individual Fund pages.
|
||||
|
||||
Upon a state change, it compares the current href query string parameters against those in the store, and if the current
|
||||
ones differ from the store, it runs a routine to update the params accordingly.
|
5
src/components/common/elements/_ft-chart.scss
Normal file
5
src/components/common/elements/_ft-chart.scss
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
.ft-chart {
|
||||
display: block;
|
||||
min-height: 500px;
|
||||
}
|
101
src/components/common/elements/ft-bar-chart.js
Normal file
101
src/components/common/elements/ft-bar-chart.js
Normal file
@ -0,0 +1,101 @@
|
||||
import {bindable, useView, computedFrom} from 'aurelia-framework';
|
||||
import {FtChart} from './ft-chart';
|
||||
|
||||
@useView('./ft-chart.html')
|
||||
export class FtBarChart extends FtChart {
|
||||
// @bindable options;
|
||||
|
||||
@bindable data = [];
|
||||
@bindable suffix = '';
|
||||
@bindable prefix = '';
|
||||
@bindable type = '';
|
||||
|
||||
@computedFrom('data', 'suffix', 'prefix', 'type')
|
||||
get series() {
|
||||
return this.data;
|
||||
}
|
||||
get options() {
|
||||
let suffix = this.suffix;
|
||||
let prefix = this.prefix;
|
||||
let type = this.type;
|
||||
let _self = this;
|
||||
|
||||
return {
|
||||
chart: {
|
||||
colorByPoint: true,
|
||||
type: type
|
||||
},
|
||||
colors: [
|
||||
'#005598', '#4e9d2d', '#00a0dc', '#333333', '#ed7700',
|
||||
'#8a1811', '#163758', '#81bb00', '#5fc0eb', '#767676',
|
||||
'#f7bb00', '#cb0000', '#bad583', '#a5d7f5', '#a7a7a7',
|
||||
'#f5db8b', '#d3e3b0', '#DBEFFB', '#c9c9c9', '#e8e8e8'
|
||||
],
|
||||
tooltip: {
|
||||
formatter: function() {
|
||||
if (_self.data.length > 1) {
|
||||
return `${this.point.name}<br /><span style="font-size:14px;color:${this.point.series.color}">${this.point.series.name}</span>${prefix}${Highcharts.numberFormat(this.point.y, 2)}${suffix}`;
|
||||
}
|
||||
return `${this.point.name}<br />${prefix}${Highcharts.numberFormat(this.point.y, 2)}${suffix}`;
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
labels: {
|
||||
enabled: (this.data.length > 1)
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
enabled: false
|
||||
},
|
||||
labels: {
|
||||
useHTML: true,
|
||||
formatter: function() {
|
||||
return `${prefix}${Highcharts.numberFormat(this.value, 1)}${suffix}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
enabled: (this.data.length > 1),
|
||||
align: 'left',
|
||||
verticalAlign: 'top',
|
||||
layout: 'horizontal',
|
||||
x: 0,
|
||||
symbolRadius: 0,
|
||||
itemHoverStyle: {
|
||||
cursor: 'default'
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
series: {
|
||||
events: {
|
||||
legendItemClick: function() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: !(this.data.length > 1),
|
||||
align: 'left',
|
||||
inside: true,
|
||||
formatter: function() {
|
||||
return this.point.name;
|
||||
},
|
||||
style: {
|
||||
color: '#000',
|
||||
fontWeight: 'normal',
|
||||
textTransform: 'uppercase',
|
||||
opacity: '1',
|
||||
textOutline: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
dataChanged() {
|
||||
this.updateChart();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<a class="${direction}"
|
||||
href="javascript:void(0)"
|
||||
role="button"
|
||||
data-slide="${slide}"
|
||||
data-target="#${carousel.carouselNode.id}">
|
||||
<span>${linkTextBefore}</span>
|
||||
<img src="${image}" alt="${linkText}"/>
|
||||
<span>${linkTextAfter}</span>
|
||||
</a>
|
||||
</template>
|
@ -0,0 +1,33 @@
|
||||
import {bindable, inject} from 'aurelia-framework';
|
||||
import {FtCarousel} from './ft-carousel';
|
||||
import environment from '../../../../environment';
|
||||
//import {LogManager} from 'aurelia-framework';
|
||||
//const logger = LogManager.getLogger('ft-carousel');
|
||||
|
||||
@inject(FtCarousel)
|
||||
export class FtCarouselNavigation {
|
||||
@bindable direction;
|
||||
@bindable linkText;
|
||||
leftLinkText;
|
||||
rightLinkText;
|
||||
image;
|
||||
|
||||
constructor(carousel) {
|
||||
this.carousel = carousel;
|
||||
//logger.debug(carousel);
|
||||
this.leftLinkText = carousel.leftLinkText;
|
||||
this.rightLinkText = carousel.rightLinkText;
|
||||
}
|
||||
|
||||
attached() {
|
||||
if (this.direction === 'left') {
|
||||
this.image = `${environment.cssRoot}/assets/img/carousel-navb-l.png`;
|
||||
this.linkTextAfter = this.leftLinkText;
|
||||
this.slide = 'prev';
|
||||
} else {
|
||||
this.image = `${environment.cssRoot}/assets/img/carousel-navb-r.png`;
|
||||
this.linkTextBefore = this.rightLinkText;
|
||||
this.slide = 'next';
|
||||
}
|
||||
}
|
||||
}
|
41
src/components/common/elements/ft-carousel/ft-carousel.html
Normal file
41
src/components/common/elements/ft-carousel/ft-carousel.html
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<!--<require from="./ft-carousel-navigation"></require>-->
|
||||
<div class="col-sm-12" data-fti-component="carousel">
|
||||
<div id="ft-carousel-header" class="carousel-header">
|
||||
${currentSlideTitle}
|
||||
</div>
|
||||
<!-- Left and right controls -->
|
||||
<div class="nav-carousel">
|
||||
<!--<ft-carousel-navigation direction="left" link-text.bind="leftLinkText"></ft-carousel-navigation>-->
|
||||
<!--<ft-carousel-navigation direction="right" link-text.bind="rightLinkText"></ft-carousel-navigation>-->
|
||||
<a class="left"
|
||||
href="javascript:void(0)"
|
||||
role="button"
|
||||
data-slide="prev"
|
||||
data-target="#${carouselNode.id}">
|
||||
<img src="${imageL}" alt="${leftLinkText}"/>
|
||||
<span>${leftLinkText}</span>
|
||||
</a>
|
||||
<a class="right"
|
||||
href="javascript:void(0)"
|
||||
role="button"
|
||||
data-slide="next"
|
||||
data-target="#${carouselNode.id}">
|
||||
<span>${rightLinkText}</span>
|
||||
<img src="${imageR}" alt="${rightLinkText}"/>
|
||||
</a>
|
||||
</div>
|
||||
<div ref="carouselNode" class="carousel slide" data-ride="carousel" data-interval="false">
|
||||
<!-- slide content added through tranclusion -->
|
||||
<slot></slot>
|
||||
<!-- Indicators -->
|
||||
<ol class="carousel-indicators ft-carousel-indicator">
|
||||
<li repeat.for="1 of numberOfSlides"
|
||||
data-target="#${carouselNode.id}"
|
||||
data-slide-to="${$index}"
|
||||
class="${($index === 0) ? 'active' : 'inactive'}"></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
100
src/components/common/elements/ft-carousel/ft-carousel.js
Normal file
100
src/components/common/elements/ft-carousel/ft-carousel.js
Normal file
@ -0,0 +1,100 @@
|
||||
import {bindable} from 'aurelia-framework';
|
||||
import environment from '../../../../environment';
|
||||
//import {LogManager} from 'aurelia-framework';
|
||||
//const logger = LogManager.getLogger('ft-carousel');
|
||||
|
||||
let index = 0;
|
||||
|
||||
/**
|
||||
* Returns array with slides titles
|
||||
* @param {Object} carousel
|
||||
* @returns {Array}
|
||||
*/
|
||||
function getSlidesTitle(carousel) {
|
||||
let carouselTitlesArr = [];
|
||||
let carouselTitles = carousel.find('.item');
|
||||
for (let i = 0; i < carouselTitles.length; i++) {
|
||||
carouselTitlesArr.push(carouselTitles[i].getAttribute('slide-title'));
|
||||
}
|
||||
return carouselTitlesArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current slide position in array returned by getSlidesTitle
|
||||
* @param {Array} carouselTitlesArr
|
||||
* @param {String} currentSlideTitle
|
||||
* @returns {Number}
|
||||
*/
|
||||
function getNextSlideNumber(carouselTitlesArr, currentSlideTitle) {
|
||||
let slideNr = 0;
|
||||
for (let carouselTitle of carouselTitlesArr) {
|
||||
if (carouselTitle === currentSlideTitle) {
|
||||
return slideNr;
|
||||
}
|
||||
slideNr++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Next Slide Title
|
||||
* @param {Array} carouselTitlesArr
|
||||
* @param {int} slideNR
|
||||
* @returns {Array}
|
||||
*/
|
||||
function getNextSlide(carouselTitlesArr, slideNR) {
|
||||
let nrOfSlides = carouselTitlesArr.length;
|
||||
let nextSlideNR = parseInt(slideNR, 10) + 1;
|
||||
if (nextSlideNR > nrOfSlides - 1) nextSlideNR = 0;
|
||||
return carouselTitlesArr[nextSlideNR];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Previous Slide Title
|
||||
* @param {Array} carouselTitlesArr
|
||||
* @param {int} slideNR
|
||||
* @returns {Array}
|
||||
*/
|
||||
function getPrevSlide(carouselTitlesArr, slideNR) {
|
||||
let nrOfSlides = carouselTitlesArr.length;
|
||||
let prevSlideNR = parseInt(slideNR, 10) - 1;
|
||||
if (prevSlideNR < 0) prevSlideNR = nrOfSlides - 1;
|
||||
return carouselTitlesArr[prevSlideNR];
|
||||
}
|
||||
|
||||
export class FtCarousel {
|
||||
@bindable leftLinkText;
|
||||
@bindable rightLinkText;
|
||||
currentSlideTitle = '';
|
||||
numberOfSlides = 0;
|
||||
|
||||
attached() {
|
||||
this.carouselNode.id = `carousel-${++index}`;
|
||||
let carousel = $(this.carouselNode);
|
||||
let carouselTitles = getSlidesTitle(carousel);
|
||||
//logger.debug(carouselTitles);
|
||||
carousel.bind('slid.bs.carousel', (e) => {
|
||||
let currentSlideTitle = e.relatedTarget.getAttribute('slide-title');
|
||||
let slideNR = getNextSlideNumber(carouselTitles, currentSlideTitle);
|
||||
let nextSlide = getNextSlide(carouselTitles, slideNR);
|
||||
let prevSlide = getPrevSlide(carouselTitles, slideNR);
|
||||
this.currentSlideTitle = currentSlideTitle;
|
||||
this.leftLinkText = prevSlide;
|
||||
this.rightLinkText = nextSlide;
|
||||
//logger.debug('Previous Slide: ' + prevSlide + '; Next Slide: ' + nextSlide);
|
||||
});
|
||||
let slides = carousel.find('.item');
|
||||
let currentSlideTitle = slides[0].getAttribute('slide-title');
|
||||
let slideNR = getNextSlideNumber(carouselTitles, currentSlideTitle);
|
||||
let nextSlide = getNextSlide(carouselTitles, slideNR);
|
||||
let prevSlide = getPrevSlide(carouselTitles, slideNR);
|
||||
this.numberOfSlides = slides.length;
|
||||
this.currentSlideTitle = currentSlideTitle;
|
||||
this.leftLinkText = prevSlide;
|
||||
this.rightLinkText = nextSlide;
|
||||
this.imageL = `${environment.cssRoot}/assets/img/carousel-navb-l.png`;
|
||||
this.imageR = `${environment.cssRoot}/assets/img/carousel-navb-r.png`;
|
||||
//logger.debug('currentSlideTitle: ' + this.currentSlideTitle);
|
||||
//logger.debug('Previous Slide: ' + prevSlide + '; Next Slide: ' + nextSlide);
|
||||
carousel.carousel();
|
||||
}
|
||||
}
|
15
src/components/common/elements/ft-carousel/ft-carousel.md
Normal file
15
src/components/common/elements/ft-carousel/ft-carousel.md
Normal file
@ -0,0 +1,15 @@
|
||||
# ft-carousel
|
||||
|
||||
This uses the bootstrap carousel. The carousel is created in the attached() method (where jquery is available.
|
||||
|
||||
A unique id is created using a timestamp and passed to the data-target attributes of the navigation elements.
|
||||
The element that we are going to create the carousel on is passed to the component using ```ref```.
|
||||
The actual content of each slide is passed in using *transclusion* ie a slot. It is assumed that each slide will be
|
||||
enclosed in a div with a ```item``` class and a ```slide-title``` attribute.
|
||||
|
||||
The next and previous buttons are added through sub-elements ```ft-carousel-navigation```. These elements gain a
|
||||
reference to the parent through dependency injection, but initialisation parameters for labels and whether left or right
|
||||
are passed through bindings.
|
||||
|
||||
|
||||
|
1
src/components/common/elements/ft-chart.html
Normal file
1
src/components/common/elements/ft-chart.html
Normal file
@ -0,0 +1 @@
|
||||
<template class="ft-chart chart"></template>
|
117
src/components/common/elements/ft-chart.js
Normal file
117
src/components/common/elements/ft-chart.js
Normal file
@ -0,0 +1,117 @@
|
||||
import {
|
||||
bindable,
|
||||
inject
|
||||
} from 'aurelia-framework';
|
||||
import merge from 'lodash/merge';
|
||||
import isArray from 'lodash/isArray';
|
||||
import isObjectLike from 'lodash/isObjectLike';
|
||||
// import {LogManager} from 'aurelia-framework';
|
||||
// const logger = LogManager.getLogger( 'ft-chart' );
|
||||
|
||||
@inject( Element )
|
||||
export class FtChart {
|
||||
@bindable options;
|
||||
@bindable series = [];
|
||||
|
||||
chart;
|
||||
newChartOnUpdate = false; // determines which update animation method to use - depends on data which method looks best
|
||||
|
||||
defaultOptions = {
|
||||
credits: {
|
||||
enabled: false
|
||||
},
|
||||
exporting: {
|
||||
enabled: false
|
||||
},
|
||||
legend: {
|
||||
enabled: false
|
||||
},
|
||||
title: {
|
||||
text: ''
|
||||
}
|
||||
};
|
||||
|
||||
constructor( element ) {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
attached() {
|
||||
let newOpts = this.mergeOptions();
|
||||
newOpts.series = this._getSeriesAsArray();
|
||||
this.chart = Highcharts.chart( this.element, newOpts );
|
||||
|
||||
$( '.tab-pane' ).attrchange( {
|
||||
trackValues: true,
|
||||
callback: e => {
|
||||
// logger.debug( this.chart );
|
||||
this.updateChart();
|
||||
// this.chart.reflow();
|
||||
return;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
mergeOptions() {
|
||||
// this can be overriden in sub-classes
|
||||
let newOpts = merge( {}, this.defaultOptions, this.options );
|
||||
return newOpts;
|
||||
}
|
||||
|
||||
updateChart() {
|
||||
if ( this.chart ) {
|
||||
/*
|
||||
Update Options.
|
||||
Do this before updating the series, so it doesn't block the animation
|
||||
*/
|
||||
let newOpts = this.mergeOptions();
|
||||
let newSeriesArr = this._getSeriesAsArray();
|
||||
|
||||
if ( this.newChartOnUpdate ) {
|
||||
// this animation update method destroys the old one and draws a new chart from scratch
|
||||
if ( this.chart ) {
|
||||
newOpts.series = newSeriesArr;
|
||||
this.chart.destroy();
|
||||
this.chart = Highcharts.chart( this.element, newOpts );
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
Merge in new series.
|
||||
Rather than delete data, and start again, update existing series data, so that chart re-animates
|
||||
*/
|
||||
this.chart.update( newOpts );
|
||||
if ( this.chart && this.chart.series ) {
|
||||
this.chart.series.forEach( s => {
|
||||
if ( newSeriesArr.length ) {
|
||||
s.setData( newSeriesArr.shift().data );
|
||||
} else {
|
||||
s.remove();
|
||||
}
|
||||
} );
|
||||
if ( newSeriesArr.length ) {
|
||||
newSeriesArr.forEach( s => {
|
||||
this.chart.addSeries( s );
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
optionsChanged() {
|
||||
this.updateChart();
|
||||
}
|
||||
|
||||
seriesChanged() {
|
||||
this.updateChart();
|
||||
}
|
||||
|
||||
// accomodate single series i.e. {} in addition to []
|
||||
_getSeriesAsArray() {
|
||||
if ( isArray( this.series ) ) {
|
||||
return this.series.slice(); // take a copy of series, so we're safe to make changes
|
||||
} else if ( isObjectLike( this.series ) ) {
|
||||
return [ Object.assign( {}, this.series ) ];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
103
src/components/common/elements/ft-column-chart.js
Normal file
103
src/components/common/elements/ft-column-chart.js
Normal file
@ -0,0 +1,103 @@
|
||||
import {
|
||||
bindable,
|
||||
useView,
|
||||
computedFrom
|
||||
} from 'aurelia-framework';
|
||||
import {FtChart} from './ft-chart';
|
||||
// import {LogManager} from 'aurelia-framework';
|
||||
// const logger = LogManager.getLogger('ft-chart');
|
||||
|
||||
@useView( './ft-chart.html' )
|
||||
export class FtColumnChart extends FtChart {
|
||||
// @bindable options;
|
||||
|
||||
@bindable data = [];
|
||||
@bindable suffix = '';
|
||||
@bindable prefix = '';
|
||||
@bindable type = '';
|
||||
@bindable categories = '';
|
||||
@bindable ytitle = '';
|
||||
|
||||
@computedFrom( 'data', 'suffix', 'prefix', 'type', 'categories', 'ytitle' )
|
||||
get series() {
|
||||
return this.data;
|
||||
}
|
||||
newChartOnUpdate = true;
|
||||
get options() {
|
||||
let suffix = this.suffix;
|
||||
let prefix = this.prefix;
|
||||
let type = this.type;
|
||||
let categories = this.categories;
|
||||
let ytitle = this.ytitle;
|
||||
let ytitleEnabled = ( ytitle !== '' ) ? true : false;
|
||||
let _self = this;
|
||||
|
||||
return {
|
||||
chart: {
|
||||
colorByPoint: true,
|
||||
type: type
|
||||
// width: $('.tab-pane.active').width()
|
||||
},
|
||||
colors: [
|
||||
'#005598', '#4e9d2d', '#00a0dc', '#333333', '#ed7700',
|
||||
'#8a1811', '#163758', '#81bb00', '#5fc0eb', '#767676',
|
||||
'#f7bb00', '#cb0000', '#bad583', '#a5d7f5', '#a7a7a7',
|
||||
'#f5db8b', '#d3e3b0', '#DBEFFB', '#c9c9c9', '#e8e8e8'
|
||||
],
|
||||
tooltip: {
|
||||
formatter: function() {
|
||||
if ( _self.data.length > 1 ) {
|
||||
return `${this.point.name}<br />${prefix}${Highcharts.numberFormat(this.point.y, 2)}${suffix}`;
|
||||
}
|
||||
return `${this.point.name}<br />${prefix}${Highcharts.numberFormat(this.point.y, 2)}${suffix}`;
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
categories: categories
|
||||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
enabled: ytitleEnabled,
|
||||
text: ytitle
|
||||
},
|
||||
labels: {
|
||||
useHTML: true,
|
||||
formatter: function() {
|
||||
return `${prefix}${Highcharts.numberFormat(this.value, 1)}${suffix}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
enabled: false,
|
||||
align: 'left',
|
||||
verticalAlign: 'top',
|
||||
layout: 'horizontal',
|
||||
x: 0,
|
||||
symbolRadius: 0,
|
||||
itemHoverStyle: {
|
||||
cursor: 'default'
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
series: {
|
||||
events: {
|
||||
legendItemClick: function() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
duration: 2000,
|
||||
easing: 'easeIn'
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
dataChanged() {
|
||||
this.updateChart();
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<template bindable="data">
|
||||
<table class="table table-text" if.bind="!data.empty">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
|
||||
<i class="chart-key chart-color-${data.index}"></i>
|
||||
</th>
|
||||
<th>
|
||||
<strong innerHTML.bind="data.label"></strong>
|
||||
</th>
|
||||
<th class="text-right">
|
||||
<ft-label label.bind="data.total | ftWithPercentOrDash"></ft-label>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody if.bind="!data.hideRows">
|
||||
<tr repeat.for="row of data.items">
|
||||
<td >${row.name}</td>
|
||||
<td >${row.val | ftWithPercentOrDash}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="row">
|
||||
<div class="date-selector form-inline clearfix">
|
||||
<div class="date-picker date-dropdown input-group hasDatepicker" id="dp1490008761101">
|
||||
<div class="ui-datepicker-inline ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all" style="display: block;">
|
||||
<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix ui-corner-all">
|
||||
<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click" title="Prev"><span class="ui-icon ui-icon-circle-triangle-w">Prev</span></a><a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="Next"><span class="ui-icon ui-icon-circle-triangle-e">Next</span></a>
|
||||
<div class="ui-datepicker-title">
|
||||
<select class="ui-datepicker-month" if.bind="dateFormat==='M-Y'" value.bind="selectedMnth">
|
||||
<option value.bind="availableMonths" repeat.for="month of availableMonths" value="${ month.key }">${ month.value }</option>
|
||||
<select>
|
||||
<select class="ui-datepicker-year" change.delegate="yearChange()" value.bind="selectedYr">
|
||||
<option repeat.for="year of availableYears" value="${ year.year }">${ year.year }</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-show" if.bind="submitType==='buttons'" click.delegate="yearChange('button')">Show Data</button>
|
||||
<button class="btn btn-default btn-disabled" if.bind="submitType==='buttons'" click.delegate="resetToCurrent()">Reset to Current</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user