├── .gitignore ├── .jshintrc ├── .vscode ├── launch.json ├── settings.json ├── symbols.json └── tasks.json ├── LICENSE ├── README.md ├── app ├── App_Resources │ ├── Android │ │ ├── AndroidManifest.xml │ │ ├── drawable-hdpi │ │ │ └── icon.png │ │ ├── drawable-ldpi │ │ │ └── icon.png │ │ ├── drawable-mdpi │ │ │ └── icon.png │ │ └── drawable-nodpi │ │ │ └── splashscreen.9.png │ └── iOS │ │ ├── Default-568h@2x.png │ │ ├── Default-667h@2x.png │ │ ├── Default-736h@3x.png │ │ ├── Default-Landscape-568h@2x.png │ │ ├── Default-Landscape-667h@2x.png │ │ ├── Default-Landscape.png │ │ ├── Default-Landscape@2x.png │ │ ├── Default-Landscape@3x.png │ │ ├── Default-Portrait.png │ │ ├── Default-Portrait@2x.png │ │ ├── Default.png │ │ ├── Default@2x.png │ │ ├── Icon-Small-50.png │ │ ├── Icon-Small-50@2x.png │ │ ├── Icon-Small.png │ │ ├── Icon-Small@2x.png │ │ ├── icon-40.png │ │ ├── icon-40@2x.png │ │ ├── icon-60.png │ │ ├── icon-60@2x.png │ │ ├── icon-72.png │ │ ├── icon-72@2x.png │ │ ├── icon-76.png │ │ ├── icon-76@2x.png │ │ ├── icon.png │ │ └── icon@2x.png ├── app.component.ts ├── app.css ├── app.module.ts ├── app.routing.ts ├── app.scss ├── content │ └── logos │ │ ├── bucs-logo.jpg │ │ ├── bucs-logo.png │ │ ├── ntl-Logo-300x286.jpg │ │ └── sutl.jpg ├── context │ └── router.context.ts ├── controls │ ├── card │ │ └── card.control.ts │ ├── content │ │ └── content.control.ts │ ├── controls.ref.ts │ ├── drawer │ │ ├── drawer.common.css │ │ ├── drawer.common.scss │ │ └── drawer.ts │ ├── fab │ │ ├── fab.common.css │ │ ├── fab.common.scss │ │ ├── fab.component.ts │ │ └── fakeFab.component.ts │ ├── icons │ │ ├── ion-icon.css │ │ ├── ion-icon.ts │ │ ├── material-icon.ts │ │ ├── nx-icon.css │ │ ├── nx-icon.scss │ │ └── nx-icon.ts │ ├── list │ │ ├── header.ts │ │ ├── list-item.ts │ │ ├── list.common.css │ │ ├── list.common.scss │ │ └── list.ts │ ├── nav │ │ ├── nav-back.ts │ │ ├── nav-title.ts │ │ ├── nav.common.css │ │ ├── nav.common.scss │ │ └── nav.ts │ ├── parallax │ │ └── parallax.ts │ ├── pullToRefresh │ │ └── pullToRefresh.control.ts │ └── searchList │ │ ├── searchList.css │ │ ├── searchList.html │ │ └── searchList.ts ├── decorators │ └── log.ts ├── directives │ └── primary.ts ├── fonts │ ├── MaterialIcons-Regular.ttf │ └── ionicons.ttf ├── main.ts ├── models │ └── models.ts ├── package.json ├── pages │ ├── competition │ │ ├── club │ │ │ └── club.page.ts │ │ ├── clubList │ │ │ └── club.list.page.ts │ │ ├── competition.page.html │ │ ├── competition.page.ts │ │ ├── findCompetitor │ │ │ └── find.competitor.page.ts │ │ ├── grade │ │ │ ├── competitors │ │ │ │ └── grade.competitors.page.ts │ │ │ └── grade.page.ts │ │ ├── gradeList │ │ │ └── grade.list.page.ts │ │ ├── information │ │ │ └── information.page.ts │ │ ├── startList │ │ │ ├── competitors │ │ │ │ └── competitors.page.ts │ │ │ ├── obsolete.html │ │ │ ├── start.list.items.control.ts │ │ │ └── start.list.page.ts │ │ └── stats │ │ │ ├── stats.page.html │ │ │ └── stats.page.ts │ ├── mapPage │ │ ├── mapPage.html │ │ └── mapPage.ts │ ├── menus.ref.ts │ ├── nav │ │ ├── competition.nav.html │ │ ├── competition.nav.ts │ │ ├── start.nav.control.html │ │ └── start.nav.control.ts │ ├── pages.ref.ts │ ├── region │ │ ├── region.page.html │ │ └── region.page.ts │ ├── regions │ │ ├── regions.page.html │ │ └── regions.page.ts │ ├── start │ │ ├── start.list.search.control.ts │ │ ├── start.page.html │ │ ├── start.page.ts │ │ └── stat.list.start.control.ts │ ├── templates.ref.ts │ └── templates │ │ ├── competitor.result.score.row.ts │ │ ├── competitor.results.css │ │ └── competitor.results.ts ├── pipes │ ├── dates │ │ └── dates.ts │ ├── orderBy │ │ └── orderBy.ts │ ├── pipes.ref.ts │ ├── score │ │ └── score.ts │ ├── startGroup │ │ └── startGroup.ts │ └── title │ │ └── title.ts ├── providers │ ├── leagues │ │ ├── clubCache.ts │ │ ├── clubService.ts │ │ ├── competitionCache.ts │ │ ├── competitionService.ts │ │ ├── competitorService.ts │ │ ├── displayService.ts │ │ ├── gradeCache.ts │ │ ├── gradeService.ts │ │ ├── regionCache.ts │ │ └── regionService.ts │ ├── logger.ts │ ├── navHelper.ts │ ├── providers.ref.ts │ └── routes │ │ └── routes.ts ├── references.d.ts ├── router │ └── remember-location-strategy.ts ├── theme │ ├── _app-common.scss │ ├── _app-variables.scss │ ├── _components.scss │ ├── app.android.css │ ├── app.android.scss │ ├── app.ios.css │ ├── app.ios.scss │ ├── button.css │ ├── button.scss │ ├── colors.css │ ├── components │ │ ├── icons.css │ │ ├── icons.scss │ │ ├── list.css │ │ ├── list.scss │ │ ├── nav.css │ │ └── nav.scss │ ├── fonts.css │ ├── fonts.scss │ └── padding.css ├── vendor-platform.android.ts ├── vendor-platform.ios.ts └── vendor.ts ├── gruntfile.js ├── hooks ├── after-prepare │ └── nativescript-dev-sass.js ├── before-livesync │ └── nativescript-angular-sync.js ├── before-prepare │ ├── nativescript-dev-sass.js │ └── nativescript-dev-typescript.js └── before-watch │ ├── nativescript-dev-sass.js │ └── nativescript-dev-typescript.js ├── package.json ├── package.json.bak ├── references.d.ts ├── screenshots ├── CompetitionList.png ├── RegionsPage-drawer.png ├── RegionsPage.png ├── StartPage.png ├── animation │ ├── load-page.gif │ ├── refresh-page.gif │ └── refresh-pointless-page.gif ├── card+refresh view.png ├── competitionPage.png ├── controls │ └── sidebar.gif ├── pages │ ├── club-list.gif │ ├── grade.page.competitor.results(minus ordering).png │ └── regions.gif ├── pipes │ └── groupBy+orderBy.gif └── style-bug │ ├── after-nav.png │ └── before-nav_20160314015641.png ├── tsconfig.aot.json ├── tsconfig.json ├── tsconfig.json.bak ├── typings.json ├── typings ├── dummy.ios.d.ts └── main.d.ts └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 12 | .grunt 13 | 14 | # node-waf configuration 15 | .lock-wscript 16 | 17 | # Compiled binary addons (http://nodejs.org/api/addons.html) 18 | build/Release 19 | 20 | # Dependency directory 21 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 22 | node_modules 23 | app/**/*.js 24 | app/**/*.map 25 | platforms 26 | 27 | # Optional npm cache directory 28 | .npm 29 | 30 | # Optional REPL history 31 | .node_repl_history 32 | *.tgz -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "undef": true, 3 | "nonew": true, 4 | "curly": false, 5 | "noarg": true, 6 | "forin": true, 7 | "noempty": false, 8 | "eqeqeq": false, 9 | "strict": false, 10 | "bitwise": true, 11 | "newcap": false, 12 | "camelcase": true, 13 | "browser": true, 14 | "node": true, 15 | "devel": true, 16 | "shadow": true, 17 | "eqnull": true, 18 | "mocha": true, 19 | "jasmine": true, 20 | "qunit": true, 21 | "predef": [ "android", "__extends", "java", "javax", "Promise" ] 22 | 23 | } 24 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch on iOS Device", 6 | "type": "nativescript", 7 | "platform": "ios", 8 | "request": "launch", 9 | "appRoot": "${workspaceRoot}", 10 | "sourceMaps": true, 11 | "diagnosticLogging": false, 12 | "emulator": false 13 | }, 14 | { 15 | "name": "Attach on iOS Device", 16 | "type": "nativescript", 17 | "platform": "ios", 18 | "request": "attach", 19 | "appRoot": "${workspaceRoot}", 20 | "sourceMaps": true, 21 | "diagnosticLogging": false, 22 | "emulator": false 23 | }, 24 | { 25 | "name": "Launch on iOS Emulator", 26 | "type": "nativescript", 27 | "platform": "ios", 28 | "request": "launch", 29 | "appRoot": "${workspaceRoot}", 30 | "sourceMaps": true, 31 | "diagnosticLogging": false, 32 | "emulator": true 33 | }, 34 | { 35 | "name": "Attach on iOS Emulator", 36 | "type": "nativescript", 37 | "platform": "ios", 38 | "request": "attach", 39 | "appRoot": "${workspaceRoot}", 40 | "sourceMaps": true, 41 | "diagnosticLogging": false, 42 | "emulator": true 43 | }, 44 | { 45 | "name": "Launch on Android Device", 46 | "type": "nativescript", 47 | "platform": "android", 48 | "request": "launch", 49 | "appRoot": "${workspaceRoot}", 50 | "sourceMaps": true, 51 | "diagnosticLogging": false, 52 | "emulator": false 53 | }, 54 | { 55 | "name": "Launch on Android Emulator", 56 | "type": "nativescript", 57 | "platform": "android", 58 | "request": "launch", 59 | "appRoot": "${workspaceRoot}", 60 | "sourceMaps": true, 61 | "diagnosticLogging": false, 62 | "emulator": true 63 | }, 64 | { 65 | "name": "Attach on Android Device", 66 | "type": "nativescript", 67 | "platform": "android", 68 | "request": "attach", 69 | "appRoot": "${workspaceRoot}", 70 | "sourceMaps": false, 71 | "diagnosticLogging": false, 72 | "emulator": false 73 | }, 74 | { 75 | "name": "Attach on Android Emulator", 76 | "type": "nativescript", 77 | "platform": "android", 78 | "request": "attach", 79 | "appRoot": "${workspaceRoot}", 80 | "sourceMaps": false, 81 | "diagnosticLogging": false, 82 | "emulator": true 83 | } 84 | ] 85 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.check.workspaceVersion": false 3 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "tsc", 4 | "isShellCommand": true, 5 | // Show the output window only if unrecognized errors occur. 6 | "showOutput": "silent", 7 | "args": ["-p", "."], 8 | //"isWatching": true, 9 | // use the standard tsc problem matcher to find compile problems 10 | // in the output. 11 | "problemMatcher": "$tsc" 12 | } 13 | // { 14 | // "version": "0.1.0", 15 | // "command": "lessc", 16 | // "isShellCommand": true, 17 | // "args": ["app/app.less", "app/app.css"] 18 | // } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 matt4446 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![start-page](https://github.com/matt4446/WhatsMyScore2-NativeScript/blob/master/screenshots/StartPage.png) 2 | ![regions-page](https://github.com/matt4446/WhatsMyScore2-NativeScript/blob/master/screenshots/RegionsPage.png) 3 | ![regions-page-drawer](https://github.com/matt4446/WhatsMyScore2-NativeScript/blob/master/screenshots/RegionsPage-drawer.png) 4 | 5 | # WhatsMyScore2 - NativeScript 6 | What's My Score App built with NativeScript + Angular 2 + TypeScript 7 | 8 | ## Getting Started 9 | Make sure you have all the tools to run [NativeScript](http://docs.nativescript.org/start/getting-started) 10 | 11 | 1. npm install 12 | 2. tns run android 13 | 14 | ## To-do: 15 | - Start page - *complete* - must remove the test page some point 16 | - Regions page - *complete* 17 | - Region page - *complete* 18 | - Region competitions page - *complete* 19 | - Competition page - *complete* 20 | - Information - *to-do* 21 | - Start list - *complete* - with groupBy and orderBy pipes 22 | - Grade start list *to-do* 23 | - Grade list - *to-do: add search* with groupBy and orderBy pipes 24 | - Grade results - *to-do* 25 | - Club list - *to-do: add search* with groupBy and orderBy pipes 26 | - Club results - *to-do* 27 | - Stats page - *to-do* 28 | 29 | 30 | 3. Angular2 NativeScript components 31 | - List control: [nx-list](https://github.com/matt4446/WhatsMyScore2-NativeScript/app/pages/startPage/startPage.html) - *complete* 32 | - List item control: [nx-list-item](https://github.com/matt4446/WhatsMyScore2-NativeScript/blob/master/app/controls/list/list-item.ts) - *mostly done - I may come back and add more animation cues.* 33 | - Nav - work in progress - may switch to the angular-nativescript actionbar - undecided. 34 | - Side bar 35 | 4. Styling - *ongoing* 36 | 37 | ### Fonts 38 | fonts have been added: 39 | 40 | - Ionicons: [ion-icon for nativescript](https://github.com/matt4446/WhatsMyScore2-NativeScript/blob/master/app/controls/icons/ion-icon.ts) 41 | - FontAwesome: not in use currently -------------------------------------------------------------------------------- /app/App_Resources/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/App_Resources/Android/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/Android/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /app/App_Resources/Android/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/Android/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /app/App_Resources/Android/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/Android/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /app/App_Resources/Android/drawable-nodpi/splashscreen.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/Android/drawable-nodpi/splashscreen.9.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-568h@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-667h@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-736h@3x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-Landscape-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-Landscape-568h@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-Landscape-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-Landscape-667h@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-Landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-Landscape.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-Landscape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-Landscape@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-Landscape@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-Landscape@3x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-Portrait.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default-Portrait@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Default@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Icon-Small-50.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Icon-Small.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/Icon-Small@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon-40.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon-40@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon-60.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon-60@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon-72.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon-72@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon-76.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon-76@2x.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon.png -------------------------------------------------------------------------------- /app/App_Resources/iOS/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/App_Resources/iOS/icon@2x.png -------------------------------------------------------------------------------- /app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {AppRoutingService} from './context/router.context'; 2 | import { Component } from "@angular/core"; 3 | import {Logger} from './providers/logger'; 4 | import { PageRoute } from 'nativescript-angular'; 5 | 6 | @Component({ 7 | selector: "my-app", 8 | template: ` 9 | 10 | `, 11 | styleUrls: [] 12 | }) 13 | export class AppComponent { 14 | // Your TypeScript logic goes here 15 | 16 | public constructor(private logger: Logger) 17 | { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/app.css: -------------------------------------------------------------------------------- 1 | .material-icons{font-family:"Material Icons", "MaterialIcons-Regular";font-style:normal;font-weight:400}.icon-layer-back{background-color:#fff;border-style:solid;border-width:1;border-color:#e6e6e6;border-radius:15;height:29;width:29}.icon-layer-front{background-color:#fafafa;border-style:solid;border-width:1;border-color:#ccc;border-radius:15;text-align:center;horizontal-align:center;vertical-align:center;height:28;width:28;padding-top:2}.icon-wrapper{text-align:center;horizontal-align:center;vertical-align:center;height:28;width:28;padding-top:2}.icon-wrapper .icon-text{color:#b3b3b3;font-size:18}.nx-nav-row{height:40;padding:0}.nx-nav-row .title{color:#fff;font-weight:bold;text-align:center}.nx-nav-row .nx-nav-col{padding-left:14;vertical-align:center}.nx-nav-row .nx-nav-col2{text-align:center;horizontal-align:center}.nx-nav-row .nx-nav-col2 label{vertical-align:center}.nx-nav-row .nx-nav-col3{padding-right:14}.nx-nav-wrapper{border-bottom-color:#015da5;border-bottom-width:1;border-bottom-style:solid}.row1{border-bottom-color:#015aa0;border-bottom-width:1;border-bottom-style:solid}.row1 .nx-nav-row{background-color:#01579b}.row2{border-bottom-color:#015da5;border-bottom-width:1;border-bottom-style:solid}.row2 .nx-nav-row{background-color:#0165b4}.nx-nav .icon-layer-front{background-color:#0168b9;border-color:#0162af}.nx-nav .icon-layer-back{background-color:#016ec4;border-color:#015da5}.nx-nav .icon-wrapper .icon-text{color:#fff}.nx-header{padding:14;border-radius:4;background-color:#01579b;color:#fff}.nx-header .title{font-weight:bold}.nx-header-ext{background-color:#01579b;border-color:#01579b}.nx-list{margin-bottom:14;border-width:1;border-radius:4;border-color:#eee;background-color:#fff}.nx-item{border-bottom-width:1;border-color:#c8c7cc;border-style:solid}.nx-item-top-border{height:1;border-radius:0;border-width:1;border-color:#c8c7cc}.nx-item-column{vertical-align:center}.inset{padding:14}.inset-sides{padding-left:14;padding-right:14}.inset-top{padding-top:14}.inset-bottom{padding-bottom:14}.inset{padding:14}.md-6{font-size:6;height:6}.md-18{font-size:18;height:18}.md-24{font-size:24;height:24}.md-36{font-size:36;height:36}.md-48{font-size:48;height:48}.md-dark{color:rgba(0,0,0,0.54)}.md-light{color:#fff}.title{color:#fff}.nx-item{color:#1a1a1a;font-size:14}.nx-item .title{color:#1a1a1a;font-size:14}.nx-item .note{color:#333;font-size:10} 2 | -------------------------------------------------------------------------------- /app/app.module.ts: -------------------------------------------------------------------------------- 1 | import * as AppRoutes from "./app.routing"; 2 | import * as Controls from "./controls/controls.ref"; 3 | import * as Nav from "./pages/menus.ref"; 4 | import * as Pages from "./pages/pages.ref"; 5 | import * as Pipes from "./pipes/pipes.ref"; 6 | import * as Providers from "./providers/providers.ref"; 7 | import * as Templates from "./pages/templates.ref"; 8 | 9 | import { NO_ERRORS_SCHEMA, NgModule } from "@angular/core"; 10 | 11 | import { AppComponent } from "./app.component"; 12 | import { MomentModule } from "angular2-moment"; 13 | import { NativeScriptHttpModule } from "nativescript-angular/http"; 14 | import { NativeScriptModule } from "nativescript-angular/nativescript.module"; 15 | import { NativeScriptRouterModule } from "nativescript-angular/router"; 16 | import { NativeScriptUISideDrawerModule } from "nativescript-telerik-ui/sidedrawer/angular"; 17 | import { NgPipesModule } from "ngx-pipes"; 18 | 19 | @NgModule({ 20 | bootstrap: [AppComponent], 21 | imports: [ 22 | NativeScriptModule, 23 | NativeScriptHttpModule, 24 | NativeScriptRouterModule, 25 | NativeScriptRouterModule.forRoot(AppRoutes.appRoutes), 26 | NativeScriptUISideDrawerModule, 27 | NgPipesModule, 28 | MomentModule 29 | ], 30 | declarations: [ 31 | AppComponent, 32 | Pages.StartPage, 33 | Pages.StartListControl, 34 | Pages.StartListSearchControl, 35 | 36 | Pages.InformationPage, 37 | Pages.RegionsPage, 38 | Pages.RegionPage, 39 | Pages.FindCompetitorPage, 40 | 41 | Pages.CompetitionPage, 42 | Pages.StartListPage, 43 | Pages.StartListGradePage, 44 | Pages.ClubListPage, 45 | Pages.ClubPage, 46 | Pages.GradeListPage, 47 | Pages.GradeCompetitorsPage, 48 | Pages.StatsPage, 49 | 50 | Templates.CompetitorResult, 51 | Templates.CompetitorResultRow, 52 | Templates.CompetitorResultRowHeader, 53 | Templates.ResultsDetailRow, 54 | 55 | Nav.StartNav, 56 | Nav.CompetitionNav, 57 | 58 | Controls.AlignLeft, 59 | Controls.AlignRight, 60 | Controls.IonIcon, 61 | Controls.MaterialFab, 62 | Controls.MaterialIcon, 63 | Controls.NavIcon, 64 | Controls.NxCard, 65 | Controls.NxContent, 66 | Controls.NxDrawer, 67 | Controls.NxFakeFab, 68 | Controls.NxHeader, 69 | Controls.NxList, 70 | Controls.NxListItem, 71 | Controls.NxIcon, 72 | Controls.NxNav, 73 | Controls.NxNavRow, 74 | Controls.NxNavBack, 75 | Controls.NxPullToRefresh, 76 | Controls.NxPullToRefreshView, 77 | Controls.NxPullToRefreshAnimateElement, 78 | 79 | Controls.NxTitle, 80 | Controls.Paralax, 81 | Controls.ParallaxCollapsableItem, 82 | Controls.ParallaxExpandableItem, 83 | 84 | Pipes.DisplayDate, 85 | Pipes.FormScoreFormatter, 86 | // Pipes.OrderByPipe, 87 | // Pipes.GroupByPipe, 88 | Pipes.ScoreFormatter, 89 | Pipes.TitleTransform 90 | ], 91 | providers: [ 92 | Providers.Logger, 93 | 94 | Providers.RegionCache, 95 | Providers.RegionService, 96 | Providers.GradeCache, 97 | Providers.GradeService, 98 | Providers.ClubCache, 99 | Providers.ClubService, 100 | Providers.CompetitionCache, 101 | Providers.CompetitionService, 102 | Providers.CompetitorService, 103 | Providers.AppRoutingService 104 | // { 105 | // provide: Providers.AppRoutingService, 106 | // useFactory: Providers.AppRoutingServiceFactory, 107 | // deps: [PageRoute] 108 | // } 109 | ], 110 | schemas: [NO_ERRORS_SCHEMA] 111 | }) 112 | export class AppModule { 113 | constructor(private logger:Providers.Logger) { 114 | this.logger.Notify("Main Page Starting"); 115 | } 116 | } 117 | 118 | -------------------------------------------------------------------------------- /app/app.routing.ts: -------------------------------------------------------------------------------- 1 | import * as Pages from "./pages/pages.ref"; 2 | 3 | import { RouterModule, Routes } from "@angular/router"; 4 | 5 | export const appRoutes: Routes = [ 6 | { path: "", component: Pages.StartPage }, 7 | { path: "regions", component: Pages.RegionsPage }, 8 | { path: "regions/:regionId", component: Pages.RegionPage }, 9 | { path: "regions/:regionId/competition/:competitionId", component: Pages.CompetitionPage }, 10 | { path: "regions/:regionId/competition/:competitionId/information", component: Pages.InformationPage }, 11 | { path: "regions/:regionId/competition/:competitionId/startList", component: Pages.StartListPage }, 12 | { path: "regions/:regionId/competition/:competitionId/startList/:gradeId", component: Pages.StartListGradePage }, 13 | { path: "regions/:regionId/competition/:competitionId/clubList", component: Pages.ClubListPage }, 14 | { path: "regions/:regionId/competition/:competitionId/clubList/:clubId", component: Pages.ClubPage }, 15 | { path: "regions/:regionId/competition/:competitionId/gradeList", component: Pages.GradeListPage }, 16 | { path: "regions/:regionId/competition/:competitionId/gradeList/:gradeId", component: Pages.GradeCompetitorsPage }, 17 | { path: "regions/:regionId/competition/:competitionId/findCompetitor", component: Pages.FindCompetitorPage }, 18 | { path: "regions/:regionId/competition/:competitionId/stats", component: Pages.StatsPage } 19 | ]; 20 | -------------------------------------------------------------------------------- /app/app.scss: -------------------------------------------------------------------------------- 1 | @import './theme/_app-variables.scss'; 2 | @import './theme/fonts.scss'; 3 | @import './theme/_components.scss'; 4 | 5 | 6 | .inset { 7 | padding: $primary-content-padding; 8 | } 9 | 10 | .md-6 { font-size: 6; height: 6} 11 | .md-18 { font-size: 18; height: 18; } 12 | .md-24 { font-size: 24; height: 24; } 13 | .md-36 { font-size: 36; height: 36; } 14 | .md-48 { font-size: 48; height: 48; } 15 | 16 | /* Rules for using icons as black on a light background. */ 17 | .md-dark { color: rgba(0, 0, 0, 0.54); } 18 | 19 | /* Rules for using icons as white on a dark background. */ 20 | .md-light { color: rgba(255, 255, 255, 1); } 21 | 22 | .title { 23 | color: $font-primary-title-color; 24 | } 25 | 26 | .nx-item { 27 | color: $font-primary-color1; 28 | font-size: 14; 29 | } 30 | .nx-item .title { 31 | color: $font-primary-color1; 32 | font-size: 14; 33 | } 34 | .nx-item .note { 35 | color: $font-primary-color3; 36 | font-size: 10; 37 | } -------------------------------------------------------------------------------- /app/content/logos/bucs-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/content/logos/bucs-logo.jpg -------------------------------------------------------------------------------- /app/content/logos/bucs-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/content/logos/bucs-logo.png -------------------------------------------------------------------------------- /app/content/logos/ntl-Logo-300x286.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/content/logos/ntl-Logo-300x286.jpg -------------------------------------------------------------------------------- /app/content/logos/sutl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/content/logos/sutl.jpg -------------------------------------------------------------------------------- /app/context/router.context.ts: -------------------------------------------------------------------------------- 1 | import { ActivatedRoute, NavigationEnd, Router } from "@angular/router"; 2 | import {BehaviorSubject, Subject} from "rxjs/Rx"; 3 | import {ICompetition, IRegion} from "../models/models"; 4 | 5 | import {Injectable} from "@angular/core"; 6 | import {Logger} from "../providers/logger"; 7 | import {PageRoute} from "nativescript-angular"; 8 | 9 | export interface IRegionRoute { 10 | RegionId : any; 11 | } 12 | export interface ICompetitionRoute { 13 | CompetitionId: any; 14 | } 15 | export interface IGradeRoute { 16 | GradeId : any; 17 | } 18 | export interface IClubRoute { 19 | ClubId : any; 20 | } 21 | 22 | @Injectable() 23 | export class AppRoutingService implements IRegionRoute, ICompetitionRoute, IGradeRoute, IClubRoute { 24 | 25 | public RegionIdChanging: Subject = new BehaviorSubject(undefined); 26 | public CompetitionIdChanging: Subject = new BehaviorSubject(undefined); 27 | public GradeIdChanging: Subject = new BehaviorSubject(undefined); 28 | public ClubIdChanging: Subject = new BehaviorSubject(undefined); 29 | 30 | private regionId : number; 31 | public get RegionId(): number { 32 | return this.regionId; 33 | } 34 | public set RegionId(value: number){ 35 | this.logger.Notify(`AppRoutingService: set regionId: ${value}`); 36 | if(this.regionId === value) { 37 | return; 38 | } 39 | 40 | this.RegionIdChanging.next(value); 41 | this.regionId = value; 42 | } 43 | 44 | private competitionId: number; 45 | public get CompetitionId(): number { 46 | return this.competitionId; 47 | } 48 | public set CompetitionId(value: number) { 49 | if(this.competitionId === value) { 50 | return; 51 | } 52 | 53 | this.CompetitionIdChanging.next(value); 54 | this.competitionId = value; 55 | } 56 | 57 | private gradeId : number; 58 | public get GradeId(): number { 59 | return this.gradeId; 60 | } 61 | public set GradeId(value: number) { 62 | this.GradeIdChanging.next(value); 63 | this.gradeId = value; 64 | } 65 | 66 | private clubId : number; 67 | public get ClubId(): number { 68 | return this.clubId; 69 | } 70 | public set ClubId(value: number){ 71 | this.ClubIdChanging.next(value); 72 | this.clubId = value; 73 | } 74 | 75 | constructor( 76 | private router: Router, 77 | private logger: Logger) { 78 | logger.Notify("AppRoutingService created"); 79 | 80 | router.events.subscribe((e) => { 81 | this.logger.Notify(`router nav ${e}`); 82 | }); 83 | router.events.filter(e=> e instanceof NavigationEnd); 84 | 85 | this.RegionIdChanging 86 | .filter(e=> e !== undefined) 87 | .subscribe(e=> { 88 | this.logger.Notify(`Region should be reloaded as: ${e}`); 89 | }); 90 | } 91 | 92 | public UpdateFromParams(data : { [key: string]: number }): void { 93 | this.logger.Notify(`Update Params: ${data}`); 94 | this.logger.NotifyObject(data); 95 | 96 | this.RegionId = data["regionId"]; 97 | this.CompetitionId = data["competitionId"]; 98 | this.GradeId = data["gradeId"]; 99 | this.ClubId = data["clubId"]; 100 | 101 | if(this.RegionId) { 102 | this.logger.Notify("RegionId: " + this.RegionId); 103 | } 104 | if(this.ClubId) { 105 | this.logger.Notify("ClubId:" + this.ClubId); 106 | } 107 | if(this.GradeId) { 108 | this.logger.Notify("regionId:" + this.RegionId); 109 | } 110 | if(this.CompetitionId) { 111 | this.logger.Notify("competitionId:" + this.CompetitionId); 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /app/controls/card/card.control.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, ViewChild } from "@angular/core"; 2 | import { Observable, Subject, Subscription } from "rxjs/Rx"; 3 | 4 | import { CardView } from "nativescript-cardview"; 5 | import { Logger } from "../../providers/logger"; 6 | import { registerElement } from "nativescript-angular/element-registry"; 7 | 8 | registerElement("CardView", () => { 9 | console.log("Adding CardView"); 10 | return require("nativescript-cardview").CardView; 11 | }); 12 | @Component({ 13 | selector: "nx-card", 14 | template:` 15 | 16 | 17 | 18 | 19 | 20 | 21 | ` 22 | }) 23 | export class NxCard { 24 | @ViewChild("item") 25 | set _listItems(item: ElementRef){ 26 | let cardView: any = item.nativeElement; 27 | } 28 | } -------------------------------------------------------------------------------- /app/controls/content/content.control.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AfterViewInit, 3 | Component, 4 | ContentChild, 5 | ContentChildren, 6 | ElementRef, 7 | EventEmitter, 8 | HostListener, 9 | Input, 10 | OnInit, 11 | Output, 12 | TemplateRef, 13 | ViewChild, 14 | } from "@angular/core"; 15 | import { NxPullToRefresh, NxPullToRefreshAnimateElement } from "../pullToRefresh/pullToRefresh.control"; 16 | import { Observable, Subject, Subscription } from "rxjs/Rx"; 17 | 18 | import { Logger } from "../../providers/logger"; 19 | import { PullToRefresh } from "nativescript-pulltorefresh"; 20 | 21 | @Component({ 22 | selector:"nx-content", 23 | template: ` 24 | 25 | 28 | 29 | 30 | 31 | 32 | 37 | 38 | 39 | `, 40 | providers: [] 41 | }) 42 | export class NxContent { 43 | private container: ElementRef; 44 | 45 | constructor(private logger:Logger) { 46 | } 47 | 48 | @Input() 49 | public isLoading : boolean = false; 50 | 51 | @ContentChild(NxPullToRefresh) 52 | private content : ElementRef; 53 | 54 | @Input() 55 | public refreshComplete : boolean = true; 56 | 57 | private refreshPage(args) { 58 | this.logger.Notify("content restart ->"); 59 | this.refreshStarted.next(args); 60 | this.isLoading = true; 61 | } 62 | 63 | private refreshPageCompleted($event) { 64 | this.refreshCompleted.next($event); 65 | this.isLoading = false; 66 | } 67 | 68 | @Output("refreshStarted") 69 | public refreshStarted = new EventEmitter(); 70 | @Output("refreshCompleted") 71 | public refreshCompleted = new EventEmitter(); 72 | } -------------------------------------------------------------------------------- /app/controls/controls.ref.ts: -------------------------------------------------------------------------------- 1 | export {NxCard} from "./card/card.control"; 2 | export {NxContent} from "./content/content.control"; 3 | export {NxDrawer} from "./drawer/drawer"; 4 | export {MaterialFab} from "./fab/fab.component"; 5 | export {NxFakeFab} from "./fab/fakeFab.component"; 6 | export {IonIcon,AlignLeft,AlignRight,NavIcon} from "./icons/ion-icon"; 7 | export {MaterialIcon} from "./icons/material-icon"; 8 | 9 | export {NxHeader} from "./list/header"; 10 | export {NxListItem} from "./list/list-item"; 11 | export {NxList} from "./list/list"; 12 | export {NxIcon} from "./icons/nx-icon"; 13 | export {NxNavBack} from "./nav/nav-back"; 14 | export {NxTitle} from "./nav/nav-title"; 15 | export {NxNav, NxNavRow} from "./nav/nav"; 16 | export {Paralax,ParallaxCollapsableItem,ParallaxExpandableItem} from "./parallax/parallax"; 17 | export {NxPullToRefresh, NxPullToRefreshView, NxPullToRefreshAnimateElement} from "./pullToRefresh/pullToRefresh.control"; 18 | -------------------------------------------------------------------------------- /app/controls/drawer/drawer.common.css: -------------------------------------------------------------------------------- 1 | .side-page{background-color:#fff} 2 | -------------------------------------------------------------------------------- /app/controls/drawer/drawer.common.scss: -------------------------------------------------------------------------------- 1 | @import "app/theme/_app-variables.scss"; 2 | 3 | .side-page { 4 | background-color:$primary-background-color; 5 | } 6 | -------------------------------------------------------------------------------- /app/controls/drawer/drawer.ts: -------------------------------------------------------------------------------- 1 | import * as Rx from "rxjs/Rx"; 2 | 3 | import { AbsoluteLayout } from "ui/layouts/absolute-layout"; 4 | import { AnimationPromise } from "ui/animation"; 5 | import {AppRoutingService} from "../../context/router.context"; 6 | import { Button } from "ui/button"; 7 | import { Component } from "@angular/core"; 8 | import { ContentChildren } from "@angular/core"; 9 | import { Directive } from "@angular/core"; 10 | import { ElementRef } from "@angular/core"; 11 | import { GridLayout } from "ui/layouts/grid-layout"; 12 | import { Logger } from "../../providers/logger"; 13 | import { NxNav } from "../nav/nav"; 14 | import {PageRoute} from "nativescript-angular"; 15 | import { PanGestureEventData } from "ui/gestures"; 16 | import { RadSideDrawerComponent } from "nativescript-telerik-ui/sidedrawer/angular"; 17 | import { StackLayout } from "ui/layouts/stack-layout"; 18 | import { ViewChild } from "@angular/core"; 19 | 20 | @Directive({ 21 | selector : "[nx-drawer-close]", 22 | }) 23 | export class NxCloseDrawer { 24 | } 25 | 26 | @Component({ 27 | selector:"nx-drawer", 28 | moduleId: module.id, 29 | styleUrls: ["drawer.common.css"], 30 | template:` 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ` 44 | }) 45 | export class NxDrawer { 46 | private childNavs : Array; 47 | private asideLeftContent : ElementRef; 48 | private asideRightContent: ElementRef; 49 | private centerContent: ElementRef; 50 | private sidebar : RadSideDrawerComponent; 51 | 52 | public constructor( 53 | private logger: Logger, 54 | private pageRoute: PageRoute, 55 | private context : AppRoutingService) { 56 | 57 | this.pageRoute.activatedRoute.subscribe(e=> { 58 | this.logger.Notify(`activatedRoute changed`); 59 | }); 60 | 61 | this.pageRoute.activatedRoute 62 | .switchMap(activatedRoute => activatedRoute.params.catch(ex => Rx.Observable.of({}))) 63 | .subscribe((params) => { 64 | context.UpdateFromParams(params); 65 | }); 66 | } 67 | 68 | private State = { 69 | Open : false, 70 | HasLeft : false, 71 | HasRight: false, 72 | NavAttached: false 73 | }; 74 | 75 | public OpenLeftAside():void { 76 | this.sidebar.sideDrawer.toggleDrawerState(); 77 | } 78 | 79 | public CloseLeftAside():void { 80 | this.sidebar.sideDrawer.toggleDrawerState(); 81 | } 82 | 83 | private ngOnInit():void { 84 | } 85 | 86 | @ViewChild("asideLeft") 87 | set _asideLeft(item: ElementRef){ 88 | this.asideLeftContent = item; 89 | this.State.HasLeft = true; 90 | } 91 | 92 | @ViewChild("asideRight") 93 | set _asideRight(item: ElementRef){ 94 | this.asideRightContent = item; 95 | this.State.HasRight = true; 96 | } 97 | 98 | @ViewChild("centerContent") 99 | set _setCenter(item: ElementRef){ 100 | this.centerContent = item; 101 | } 102 | 103 | @ViewChild(RadSideDrawerComponent) 104 | set _setMain(item: RadSideDrawerComponent){ 105 | this.sidebar = item; 106 | } 107 | 108 | @ContentChildren(NxNav) 109 | set _setNav(items: any) { 110 | if(this.State.NavAttached){ return; } 111 | 112 | ///this.logger.Notify("drawer.nav set: " + items); 113 | this.State.NavAttached = true; 114 | this.childNavs = items.toArray(); 115 | 116 | var anySelected = this.childNavs.map((item) => item.menuSelected); 117 | 118 | Rx.Observable.from(anySelected).flatMap(x=>x).subscribe(() => { 119 | this.logger.Notify("nav menu tapped -> open side"); 120 | 121 | if(this.State.Open) { 122 | this.CloseLeftAside(); 123 | } else { 124 | this.OpenLeftAside(); 125 | } 126 | 127 | }); 128 | } 129 | } -------------------------------------------------------------------------------- /app/controls/fab/fab.common.css: -------------------------------------------------------------------------------- 1 | .fab-font{font-size:36;color:#fff;text-align:center;horizontal-align:center;vertical-align:center;height:50;width:50;margin:15;padding-top:4}.left{horizontal-align:left}.right{horizontal-align:right}.h-center{horizontal-align:center}.top{vertical-align:top}.bottom{vertical-align:bottom}.v-center{vertical-align:center}.fab-button{background-color:#ff4081;height:50;width:50;margin:15}.fab-button-content{height:50;width:50;margin:15;horizontal-align:center;vertical-align:center}.fab-icon{text-align:center} 2 | -------------------------------------------------------------------------------- /app/controls/fab/fab.common.scss: -------------------------------------------------------------------------------- 1 | @import "app/theme/_app-variables.scss"; 2 | 3 | .fab-container { 4 | } 5 | 6 | /* 7 | to-do: follow the rules 8 | http://google.github.io/material-design-icons/ 9 | Styling icons in material design 10 | */ 11 | 12 | .fab-font { 13 | font-size: 36; 14 | color: $font-primary-title-color; 15 | text-align: center; 16 | horizontal-align: center; 17 | vertical-align: center; 18 | height: 50; 19 | width: 50; 20 | margin: 15; 21 | padding-top: 4; 22 | } 23 | 24 | .left { 25 | horizontal-align: left; 26 | } 27 | .right { 28 | horizontal-align: right; 29 | } 30 | .h-center { 31 | horizontal-align: center; 32 | } 33 | .top { 34 | vertical-align: top; 35 | } 36 | .bottom { 37 | vertical-align: bottom; 38 | } 39 | .v-center { 40 | vertical-align: center; 41 | } 42 | 43 | .fab-button { 44 | background-color: #ff4081; 45 | 46 | height: 50; 47 | width: 50; 48 | margin: 15; 49 | } 50 | 51 | .fab-button-content { 52 | height: 50; 53 | width: 50; 54 | margin: 15; 55 | horizontal-align: center; 56 | vertical-align: center; 57 | } 58 | 59 | .fab-icon { 60 | text-align: center; 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/controls/fab/fab.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ContentChildren, Directive, ElementRef, EventEmitter, Input, Output, ViewChild } from "@angular/core"; 2 | import { Observable, Subject, Subscription } from 'rxjs/Rx'; 3 | import { ViewClass, registerElement } from "nativescript-angular/element-registry"; 4 | 5 | import { AnimationPromise } from "ui/animation"; 6 | import { StackLayout } from "ui/layouts/stack-layout"; 7 | 8 | registerElement("Fab", () => require("nativescript-floatingactionbutton").Fab); 9 | /* 10 | Material icons 11 | http://google.github.io/material-design-icons/ 12 | */ 13 | @Component({ 14 | selector: "material-fab", 15 | template:` 16 | 24 | 25 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | `, 41 | outputs: ["tap"], 42 | styleUrls: ["./controls/fab/fab.common.css"], 43 | }) 44 | export class MaterialFab { 45 | @Input("horizontal-align") 46 | public horizontalAlign : string = "right"; 47 | @Input("vertical-align") 48 | public veritcalAlign : string = "top"; 49 | 50 | @Input("text") 51 | public text : string = "face" 52 | 53 | @Input("font-size") 54 | public fontSize : string = "md-24"; 55 | 56 | @ViewChild("fab") 57 | public element : ElementRef; 58 | 59 | constructor() 60 | { 61 | console.log("material-fab - started"); 62 | } 63 | 64 | public tapped($event){ 65 | console.log("tapped on fab"); 66 | this.tap.next($event); 67 | } 68 | 69 | public fabTap(){ 70 | console.log("fab pressed"); 71 | this.tap.next({ 72 | source : this.element.nativeElement 73 | }) 74 | } 75 | 76 | public tap = new EventEmitter(); 77 | } 78 | 79 | -------------------------------------------------------------------------------- /app/controls/fab/fakeFab.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ContentChildren, Directive, ElementRef, EventEmitter, Input, Output, ViewChild } from "@angular/core"; 2 | import { Observable, Subject, Subscription } from "rxjs/Rx"; 3 | import { ViewClass, registerElement } from "nativescript-angular/element-registry"; 4 | 5 | import { AnimationPromise } from "ui/animation"; 6 | import { StackLayout } from "ui/layouts/stack-layout"; 7 | 8 | @Component({ 9 | selector: "", 10 | template: ` 11 | 19 | 20 | 22 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | ` 38 | }) 39 | export class NxFakeFab { 40 | 41 | @Input("horizontal-align") 42 | public horizontalAlign : string = "right"; 43 | @Input("vertical-align") 44 | public veritcalAlign : string = "top"; 45 | 46 | @Input("text") 47 | public text : string = "face"; 48 | 49 | @Input("font-size") 50 | public fontSize : string = "md-24"; 51 | 52 | @ViewChild("fab") 53 | public element : ElementRef; 54 | 55 | public tapped($event: any): void { 56 | console.log("tapped on fab"); 57 | this.tap.next($event); 58 | } 59 | 60 | public fabTap(): void { 61 | console.log("fab pressed"); 62 | this.tap.next({ 63 | source : this.element.nativeElement 64 | }); 65 | } 66 | 67 | public tap = new EventEmitter(); 68 | } -------------------------------------------------------------------------------- /app/controls/icons/ion-icon.css: -------------------------------------------------------------------------------- 1 | .icon { 2 | font-size: 20; 3 | margin: 3; 4 | } 5 | 6 | .ion-icon { 7 | font-family: "Ionicons"; 8 | /* file must match exactly (indluding case) Ionicons.ttf */ 9 | /* app/fonts/Ionicons.ttf */ 10 | /* cheat sheet http://ionicons.com/cheatsheet.html */ 11 | font-size: 26 ; 12 | color: #4d75b8; 13 | text-align: center; 14 | } 15 | 16 | .text-left { 17 | text-align: left; 18 | } 19 | .text-right { 20 | text-align: right; 21 | } -------------------------------------------------------------------------------- /app/controls/icons/ion-icon.ts: -------------------------------------------------------------------------------- 1 | import { Component, Directive, ElementRef, EventEmitter, ViewChild } from "@angular/core"; 2 | 3 | import { Label } from "ui/label"; 4 | import { Logger } from "../../providers/logger"; 5 | 6 | @Directive({ 7 | selector:"nav-icon", 8 | // properties: [ 9 | // 'class: ion-icon nav-icon' 10 | // ] 11 | }) 12 | export class NavIcon { } 13 | 14 | @Directive({ 15 | selector:"[align-left]", 16 | host: { 17 | "class" : "text-left" 18 | } 19 | }) 20 | export class AlignLeft { } 21 | @Directive({ 22 | selector: "[align-right]", 23 | host: { 24 | "class" : "text-right" 25 | } 26 | }) 27 | export class AlignRight { } 28 | 29 | @Component({ 30 | selector:"ion-icon", 31 | template: ` 32 | 35 | `, 36 | providers: [], 37 | inputs:["icon", "nav"], 38 | outputs:["tap"], 39 | moduleId: module.id, 40 | styleUrls: ["ion-icon.css"] 41 | }) 42 | export class IonIcon { 43 | private container: ElementRef; 44 | 45 | constructor(private logger:Logger) { 46 | } 47 | 48 | @ViewChild("item") 49 | set _listItems(item: ElementRef){ 50 | this.container = item; 51 | } 52 | public GetIcon(): string { 53 | let key: string = this.icon ? this.icon : ""; 54 | key = this.Match(this.icon); 55 | 56 | return key; 57 | } 58 | 59 | public color = "#FF0000"; 60 | public icon : string; 61 | public nav : boolean = false; 62 | public tap = new EventEmitter(); 63 | public tapIcon($event: any): void { 64 | let label : Label = this.container.nativeElement; 65 | 66 | label.animate({ 67 | opacity: 0.7 68 | }).then(() => { 69 | return label.animate({ 70 | opacity: 1 71 | }); 72 | }); 73 | this.tap.next($event); 74 | } 75 | 76 | //http://ionicons.com/cheatsheet.html 77 | private Match(key: string): string { 78 | switch (key) { 79 | case "ion-alert": 80 | return "\uf101"; 81 | case "ion-alert-circled": 82 | return "\uf100"; 83 | case "ion-android-add": 84 | return "\uf2c7"; 85 | case "ion-android-add-circle": 86 | return "\uf359"; 87 | case "ion-calendar": 88 | return "\uf117"; 89 | case "ion-flame": 90 | return "\uf31a"; 91 | // .. 92 | 93 | case "ion-map" : 94 | return "\uf203"; 95 | case "ion-search" : 96 | return "\uf21f"; 97 | case "ion-chevron-left": 98 | return "\uf124"; 99 | case "ion-chevron-right": 100 | return "\uf125"; 101 | case "ion-clipboard": 102 | return "\uf127"; 103 | case "ion-android-favorite": 104 | return "\uf388"; 105 | case "ion-android-menu": 106 | return "\uf394"; 107 | case "ion-ribbon-a": 108 | return "\uf348;"; 109 | case "ion-ribbon-b": 110 | return "\uf349;"; 111 | /* 112 | ios 113 | */ 114 | case "ion-ios-star": 115 | return "\uf4b3"; 116 | case "ion-ios-people" : 117 | return "\uf47c"; 118 | 119 | default: 120 | //ion-alert 121 | return key; 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /app/controls/icons/material-icon.ts: -------------------------------------------------------------------------------- 1 | import {Directive} from "@angular/core"; 2 | 3 | @Directive({ 4 | selector: "[material-icon]", 5 | host: { 6 | "class": "material-icons" 7 | } 8 | }) 9 | export class MaterialIcon { 10 | } -------------------------------------------------------------------------------- /app/controls/icons/nx-icon.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/controls/icons/nx-icon.css -------------------------------------------------------------------------------- /app/controls/icons/nx-icon.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/controls/icons/nx-icon.scss -------------------------------------------------------------------------------- /app/controls/icons/nx-icon.ts: -------------------------------------------------------------------------------- 1 | import { Component, EventEmitter, Input } from "@angular/core"; 2 | 3 | @Component({ 4 | moduleId: module.id, 5 | selector: "nx-icon", 6 | styleUrls: ["nx-icon.css"], 7 | outputs: ["tap"], 8 | template: ` 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ` 22 | }) 23 | export class NxIcon { 24 | @Input("text") 25 | public justText: string; 26 | 27 | @Input("icon") 28 | public iconText: string; 29 | 30 | private click(args: any): void { 31 | if(this.tap) { 32 | this.tap.next(args); 33 | } 34 | } 35 | public tap = new EventEmitter(); 36 | } -------------------------------------------------------------------------------- /app/controls/list/header.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, Input, Output, EventEmitter, ContentChildren, ViewChild } from "@angular/core"; 2 | import { Logger } from "../../providers/logger"; 3 | import { Button } from "ui/button"; 4 | import { StackLayout} from "ui/layouts/stack-layout"; 5 | import { NxListItem } from "./list-item"; 6 | 7 | @Component({ 8 | selector:"nx-header", 9 | template: ` 10 | 11 | 12 | 13 | 14 | 15 | `, 16 | styleUrls: ["./controls/list/list.common.css"] 17 | }) 18 | export class NxHeader 19 | { 20 | private container: ElementRef; 21 | 22 | constructor(private logger: Logger){ 23 | //this.logger.Notify("add header"); 24 | } 25 | 26 | @ViewChild('item') 27 | set _setHeaderElement(item: ElementRef){ 28 | this.container = item; 29 | } 30 | 31 | public getNativeElement() : StackLayout { 32 | if(!this.container){ return ; } 33 | 34 | let stackLayout: StackLayout = this.container.nativeElement; 35 | 36 | return stackLayout; 37 | } 38 | } 39 | 40 | // 41 | // 42 | // 43 | // 44 | // -------------------------------------------------------------------------------- /app/controls/list/list-item.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ChangeDetectionStrategy, 3 | Component, 4 | ContentChild, 5 | ContentChildren, 6 | ElementRef, 7 | EventEmitter, 8 | HostListener, 9 | Input, 10 | Output, 11 | ViewChild, 12 | } from "@angular/core"; 13 | import { Observable, Subject, Subscription } from "rxjs/Rx"; 14 | 15 | import { AnimationCurve } from "ui/enums"; 16 | import { Button } from "ui/button"; 17 | import { Logger } from "../../providers/logger"; 18 | import { QueryList } from "@angular/core"; 19 | import { RouterExtensions } from "nativescript-angular/router"; 20 | import { StackLayout } from "ui/layouts/stack-layout"; 21 | 22 | @Component({ 23 | moduleId: module.id, 24 | selector:"nx-item", 25 | 26 | // create a 1 row template; 3 columns; 2 for the icons on the sides 27 | template: ` 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | `, 70 | changeDetection: ChangeDetectionStrategy.OnPush, 71 | outputs: ["tap"], 72 | styleUrls: ["list.common.css"] 73 | }) 74 | export class NxListItem { 75 | private container: ElementRef; 76 | 77 | @ViewChild("item") 78 | set _setListElement(item: ElementRef){ 79 | this.container = item; 80 | this.itemReady.next(this); 81 | } 82 | 83 | @ViewChild("animateItem") 84 | set _gridElement(item: ElementRef){ 85 | let element:StackLayout = item.nativeElement ; 86 | 87 | if(this.Animate) { 88 | element.className += " visible"; 89 | } 90 | } 91 | 92 | @Input("animate") 93 | public Animate : boolean; 94 | 95 | constructor(private logger:Logger, private routerExtensions: RouterExtensions){ 96 | } 97 | 98 | public itemReady: Subject = new Subject(); 99 | public itemSelected: Subject = new Subject(); 100 | 101 | public getNativeElement(): StackLayout { 102 | if(!this.container) { 103 | return; 104 | } 105 | 106 | let stackLayout: StackLayout = this.container.nativeElement; 107 | 108 | return stackLayout; 109 | } 110 | 111 | public tapWrapper = (args: any) => { 112 | this.logger.Notify("tap clicked on item"); 113 | 114 | let stackLayout: StackLayout = this.getNativeElement(); 115 | 116 | if(!stackLayout) { return ;} 117 | this.Navigate(args); 118 | // let moveRight = stackLayout.animate({ 119 | // duration: 100, 120 | // translate: { x: 15, y: 0 }, 121 | // opacity: 0.8, 122 | // curve: AnimationCurve.easeIn 123 | // }).then(() =>{ 124 | // this.itemSelected.next(this); 125 | 126 | // return stackLayout.animate({ 127 | // duration: 100, 128 | // translate: { x:0, y: 0}, 129 | // opacity: 1, 130 | // curve: AnimationCurve.easeIn 131 | // }); 132 | // }).then(() => { 133 | // setTimeout(() => { 134 | // this.Navigate(args); 135 | // }, 200); 136 | // }); 137 | } 138 | 139 | private Navigate(args: any): void { 140 | if(this.tap) { 141 | this.tap.next(args); 142 | } 143 | } 144 | 145 | public tap = new EventEmitter(); // : (args: EventEmitter) => void; 146 | } -------------------------------------------------------------------------------- /app/controls/list/list.common.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/controls/list/list.common.css -------------------------------------------------------------------------------- /app/controls/list/list.common.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/controls/list/list.common.scss -------------------------------------------------------------------------------- /app/controls/list/list.ts: -------------------------------------------------------------------------------- 1 | import { Component, ContentChildren, Directive, EventEmitter, Input, Output } from "@angular/core"; 2 | import { Observable, Subject, Subscription } from "rxjs/Rx"; 3 | 4 | import { AnimationCurve } from "ui/enums"; 5 | import { Logger } from "../../providers/logger"; 6 | import { NxHeader } from "./header"; 7 | import { NxListItem } from "./list-item"; 8 | import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout/stack-layout"; 9 | 10 | @Component({ 11 | moduleId: module.id, 12 | selector: "nx-list", 13 | styleUrls: ["list.common.css"], 14 | template:` 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ` 27 | }) 28 | export class NxList { 29 | 30 | constructor(private logger: Logger) { 31 | } 32 | 33 | public padding : boolean = false; 34 | public children : Array; 35 | public headers : Array; 36 | 37 | @ContentChildren(NxHeader) 38 | set _setHeader(items : any) { 39 | this.headers = items.toArray(); 40 | } 41 | 42 | @ContentChildren(NxListItem) 43 | set _listItems(items: any){ 44 | this.children = items.toArray(); 45 | 46 | var anyReady = this.children.map((item) => item.itemReady); 47 | var anySelected = this.children.map((item) => item.itemSelected); 48 | 49 | Observable.from(anySelected) 50 | .flatMap(x=> x) 51 | .subscribe((item) => { 52 | 53 | let indexOfSelected = this.children.indexOf(item); 54 | this.children.forEach((row) => { 55 | let indexOfRow : number = this.children.indexOf(row); 56 | let distance : number = Math.abs(indexOfSelected - indexOfRow); 57 | if (distance > 1) { 58 | return; 59 | } 60 | 61 | if(item === row) { 62 | return; 63 | } 64 | 65 | this.AnimateCollection(row, distance); 66 | }); 67 | 68 | }); 69 | 70 | } 71 | 72 | private AnimateCollection(row : NxListItem, distance: number): void { 73 | var stackPanel: StackLayout = row.getNativeElement(); 74 | setTimeout(()=> { 75 | stackPanel.animate({ 76 | opacity: 1, 77 | duration: 100, 78 | translate: { 79 | x : -15, 80 | y: 0 81 | }, 82 | curve: AnimationCurve.easeIn 83 | }).then(() => { 84 | return stackPanel.animate({ 85 | duration: 100, 86 | translate: { 87 | x: -200, 88 | y: 0 89 | }, 90 | opacity: 0, 91 | curve: AnimationCurve.easeOut 92 | }); 93 | }).then(() => { 94 | stackPanel.translateX = 0; 95 | return stackPanel.animate({ 96 | duration: 200, 97 | translate: { 98 | x: 0, 99 | y: 0 100 | }, 101 | opacity: 1, 102 | curve: AnimationCurve.easeIn 103 | }); 104 | }); 105 | 106 | 107 | }, (25*distance)); 108 | 109 | 110 | } 111 | } 112 | 113 | export interface ISearchEvent { 114 | Value: string; 115 | } -------------------------------------------------------------------------------- /app/controls/nav/nav-back.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef } from "@angular/core"; 2 | import { Location, LocationStrategy } from "@angular/common"; 3 | import { Observable, Subject, Subscription } from "rxjs/Rx"; 4 | 5 | import { Logger } from "../../providers/logger"; 6 | import { MaterialIcon } from "../icons/material-icon"; 7 | 8 | @Component ({ 9 | moduleId: module.id, 10 | selector:"nx-nav-back", 11 | styleUrls: ["nav.common.css"], 12 | template: ` 13 | 14 | `, 15 | providers: [], 16 | }) 17 | export class NxNavBack { 18 | 19 | public constructor( 20 | private location: Location, 21 | private element: ElementRef, 22 | private logger: Logger) { 23 | } 24 | 25 | public back(): void { 26 | this.logger.Notify("Back"); 27 | try { 28 | this.location.back(); 29 | } catch (ex) { } 30 | } 31 | 32 | public menuSelected = new Subject(); 33 | 34 | public tapWrapper = (args: any) => { 35 | this.logger.Notify("tap clicked on menu"); 36 | this.menuSelected.next(true); 37 | } 38 | } -------------------------------------------------------------------------------- /app/controls/nav/nav-title.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, ViewChild } from "@angular/core"; 2 | 3 | import { Logger } from "../../providers/logger"; 4 | 5 | @Directive({ 6 | selector: "[nav-title]", 7 | host: { 8 | "class" : "nav-title" 9 | } 10 | }) 11 | export class NxTitle { 12 | @ViewChild("item") private container: ElementRef; 13 | 14 | public constructor(private logger: Logger) { 15 | } 16 | } -------------------------------------------------------------------------------- /app/controls/nav/nav.common.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/controls/nav/nav.common.css -------------------------------------------------------------------------------- /app/controls/nav/nav.common.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/controls/nav/nav.common.scss -------------------------------------------------------------------------------- /app/controls/nav/nav.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, EventEmitter, Input, ViewChild } from "@angular/core"; 2 | import { IonIcon, NavIcon } from "../icons/ion-icon"; 3 | import { Observable, Subject, Subscription } from "rxjs/Rx"; 4 | 5 | import { Logger } from "../../providers/logger"; 6 | import { MaterialIcon } from "../icons/material-icon"; 7 | import { NxNavBack } from "./nav-back"; 8 | import { Page } from "ui/page"; 9 | 10 | @Component({ 11 | moduleId: module.id, 12 | selector: "nx-nav-row", 13 | styleUrls: ["nav.common.css"], 14 | template: ` 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ` 27 | }) 28 | export class NxNavRow { 29 | } 30 | 31 | @Component({ 32 | moduleId: module.id, 33 | selector:"nx-nav", 34 | styleUrls: ["nav.common.css"], 35 | template:` 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | `, 54 | inputs: [ "showBack", "showMenu", "title" ], 55 | outputs: [ "showLeftSidebar", "showRightSidebar" ] 56 | }) 57 | export class NxNav { 58 | @ViewChild("item") private container: ElementRef; 59 | 60 | @Input("showSubHeader") 61 | public ShowSubheader : boolean = true; 62 | 63 | public constructor( 64 | private element: ElementRef, 65 | private logger: Logger, 66 | private page : Page) { 67 | } 68 | 69 | ngOnInit(): void { 70 | this.page.actionBarHidden = true; 71 | this.page.actionBar.update(); 72 | } 73 | 74 | public title : string = "Default Title"; 75 | public showBack : boolean = true; 76 | public showMenu : boolean = false; 77 | 78 | public showLeftSidebar = new EventEmitter(); 79 | public showRightSidebar = new EventEmitter(); 80 | 81 | public menuSelected = new Subject(); 82 | 83 | public menuButtonTap(args: any): void { 84 | this.menuSelected.next(true); 85 | } 86 | } -------------------------------------------------------------------------------- /app/controls/pullToRefresh/pullToRefresh.control.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from "@angular/core"; 2 | import { ContentChild, ContentChildren, Directive, ElementRef, EventEmitter, Input, Output, ViewChild, ViewChildren } from "@angular/core"; 3 | import { Observable, Subject, Subscription } from 'rxjs/Rx'; 4 | import { ViewClass, registerElement } from "nativescript-angular/element-registry"; 5 | 6 | import { AnimationPromise } from "ui/animation"; 7 | import {LayoutBase} from "ui/layouts/layout-base"; 8 | import { ListView } from "ui/list-view"; 9 | import { ListViewComponent } from "nativescript-angular/directives/list-view-comp"; 10 | import { Logger } from "../../providers/logger"; 11 | import { PullToRefresh } from "nativescript-pulltorefresh"; 12 | import { StackLayout } from "ui/layouts/stack-layout"; 13 | 14 | registerElement("PullToRefresh", () => require("nativescript-pulltorefresh").PullToRefresh); 15 | 16 | @Directive({ 17 | selector: "[pull-to-animate]" 18 | }) 19 | export class NxPullToRefreshAnimateElement{ 20 | 21 | constructor(private element : ElementRef){ 22 | 23 | } 24 | 25 | public get Element() : StackLayout{ 26 | return this.element.nativeElement; 27 | } 28 | } 29 | 30 | @Directive({ 31 | selector: "[pull-list-view]", 32 | //outputs: ["refreshStarted", "refreshCompleted"], 33 | host: { 34 | "(refresh)" : "refreshMe($event)" 35 | } 36 | }) 37 | export class NxPullToRefreshView{ 38 | 39 | constructor(private element: ElementRef, private logger: Logger){ 40 | // this.logger.Notify("listview - that i want to pull"); 41 | // this.logger.NotifyObjectProperties(element.nativeElement); 42 | // this.logger.Notify(element.nativeElement.typeName); 43 | } 44 | 45 | public get Component(): ListView{ 46 | let component :ListViewComponent = this.element.nativeElement; 47 | let anon: any = component; 48 | 49 | let realThing : ListView = anon.listView ; 50 | return realThing; 51 | } 52 | 53 | @Output("refreshStarted") 54 | public refreshStarted = new EventEmitter(); 55 | @Output("refreshCompleted") 56 | public refreshCompleted = new EventEmitter(); 57 | 58 | private refreshMe(args : any){ 59 | this.logger.Notify("Refresh notified in the directive NxPullListView"); 60 | 61 | var notifyRefreshCompleted = () => { 62 | args.object.refreshing = false; 63 | 64 | this.refreshCompleted.next({ 65 | object: args.object 66 | }); 67 | this.grow(); 68 | }; 69 | 70 | this.refreshStarted.next({ 71 | object: args.object, 72 | completed : notifyRefreshCompleted 73 | }); 74 | 75 | this.shrink(); 76 | } 77 | 78 | private animateContentChildElement: NxPullToRefreshAnimateElement[]; 79 | @ContentChildren(NxPullToRefreshAnimateElement) 80 | public set contentChildren(elements) 81 | { 82 | this.animateContentChildElement = elements.toArray(); 83 | } 84 | 85 | private animateViewChild : NxPullToRefreshAnimateElement[]; 86 | @ViewChildren(NxPullToRefreshAnimateElement) 87 | public set viewChildren(elements){ 88 | this.animateViewChild = elements.toArray(); 89 | } 90 | 91 | private get AnimateElements() : NxPullToRefreshAnimateElement[]{ 92 | let a = []; 93 | if(this.animateContentChildElement && this.animateContentChildElement.length > 0) 94 | { 95 | this.logger.Notify("animateContentChildElement"); 96 | this.animateContentChildElement.forEach(item => { a.push(item); }); 97 | } 98 | if(this.animateViewChild && this.animateViewChild.length > 0) 99 | { 100 | this.logger.Notify("animateViewChild"); 101 | this.animateViewChild.forEach(item => { a.push(item); }); 102 | } 103 | 104 | if(a.length === 0){ 105 | this.logger.Notify("neither contentchild or viewchild is found"); 106 | } 107 | 108 | return a; 109 | } 110 | 111 | private transition: AnimationPromise = null; 112 | 113 | private shrink(){ 114 | var animateChildren = this.AnimateElements; 115 | 116 | animateChildren.forEach((child) => { 117 | let stackLayout = child.Element; 118 | let animation = stackLayout.animate({ opacity : 0.2, scale: { x : 0.5, y: 0.5 } }); 119 | animation.then(() => { 120 | let innerAnimation = stackLayout.animate({ opacity: 0, translate: { x: -1000, y: 0 }}); 121 | return innerAnimation; 122 | }); 123 | this.transition = animation; 124 | }); 125 | } 126 | 127 | private grow(){ 128 | var animateChildren = this.AnimateElements; 129 | 130 | 131 | animateChildren.forEach((child) => { 132 | let stackLayout = child.Element; 133 | 134 | let fadeIn = () => { 135 | console.log("fade in"); 136 | stackLayout.translateX = 0; 137 | return stackLayout.animate({ opacity : 1, scale: { x : 1, y: 1 }, translate: { x: 0, y: 0} }) 138 | }; 139 | 140 | this.transition 141 | .then(fadeIn); 142 | }); 143 | 144 | 145 | } 146 | 147 | } 148 | 149 | @Component({ 150 | selector: "nx-pull-to-refresh", 151 | template:` 152 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | `, 162 | outputs: ["refresh", "refreshCompleted"], 163 | //inputs: ["complete"] 164 | }) 165 | 166 | export class NxPullToRefresh { 167 | 168 | 169 | constructor(private logger: Logger) 170 | { 171 | this.logger.Notify("NxPullToRefresh - started"); 172 | } 173 | 174 | @ViewChild("item") 175 | public pullToRefreshElement : ElementRef; 176 | 177 | @Output("refreshStarted") 178 | public refreshStarted = new EventEmitter(); 179 | @Output("refreshCompleted") 180 | public refreshCompleted = new EventEmitter(); 181 | 182 | private refreshMeStarted(args : any){ 183 | this.refreshStarted.next(args); 184 | //this.shrink(); 185 | } 186 | 187 | private refreshMeCompleted($event){ 188 | console.log("completed"); 189 | this.refreshCompleted.next($event); 190 | //this.grow(); 191 | } 192 | 193 | 194 | 195 | 196 | } 197 | 198 | -------------------------------------------------------------------------------- /app/controls/searchList/searchList.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/controls/searchList/searchList.css -------------------------------------------------------------------------------- /app/controls/searchList/searchList.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/controls/searchList/searchList.ts: -------------------------------------------------------------------------------- 1 | import { Component, EventEmitter, Input, Output } from "@angular/core"; 2 | 3 | import { Logger } from "../../providers/logger"; 4 | import { Observable } from "data/observable"; 5 | import { SearchBar } from "ui/search-bar" 6 | 7 | //var observable = require("data/observable"); 8 | 9 | 10 | 11 | @Component({ 12 | selector: "search-list", 13 | templateUrl: "controls/searchList/searchList.html", 14 | inputs:["HintText", "SearchText"], 15 | outputs: ["OnSearch: OnSearch"] 16 | }) 17 | export class SearchList { 18 | 19 | constructor(private logger: Logger) 20 | { 21 | this.logger.Notify("SearchList control Started"); 22 | 23 | var searchBar = new SearchBar(); 24 | 25 | } 26 | 27 | //@Input() 28 | public HintText : string = "Search"; 29 | //@Input() 30 | public SearchText : string = ""; 31 | //@Output() 32 | public OnSearch = new EventEmitter();; 33 | 34 | public OnSubmit (args) : void { 35 | this.logger.Notify("ev: OnSubmit text"); 36 | this.logger.Notify(args.object.text); 37 | 38 | let searchText = args.object.text; 39 | this.OnSearch.next(searchText); 40 | } 41 | 42 | public OnClear(args) : void { 43 | this.logger.Notify("ev: OnClear"); 44 | this.OnSearch.next(); 45 | // this.Search.next({ 46 | // Value: "" 47 | // }); 48 | } 49 | } 50 | 51 | export interface ISearchEvent 52 | { 53 | Value: string; 54 | } -------------------------------------------------------------------------------- /app/decorators/log.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export function log(target: any, key : string, index : number){ 4 | 5 | } -------------------------------------------------------------------------------- /app/directives/primary.ts: -------------------------------------------------------------------------------- 1 | //to-do - assign primary colours 2 | import {Directive} from '@angular/core'; -------------------------------------------------------------------------------- /app/fonts/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/fonts/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /app/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/fonts/ionicons.ttf -------------------------------------------------------------------------------- /app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformNativeScriptDynamic } from "nativescript-angular/platform"; 2 | import { AppModule } from "./app.module"; 3 | 4 | platformNativeScriptDynamic({ 5 | cssFile : "app.css", 6 | startPageActionBarHidden : true 7 | }).bootstrapModule(AppModule); 8 | -------------------------------------------------------------------------------- /app/models/models.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from "rxjs/Rx"; 2 | 3 | export interface IRegion { 4 | Id: number; 5 | Name: string; 6 | Logo: string; 7 | } 8 | 9 | /* 10 | {"Id":17, 11 | "Name":"BUCS 2015 - Day 2 - Finals", 12 | "LocationName":"Sheffield Ice Arena", 13 | "CreatedUtc":"2015-02-22T10:41:22.197Z", 14 | "StartDateTimeUtc":"2015-02-22T09:00:00Z", 15 | "EndDateTimeUtc":"2015-08-23T16:00:00Z", 16 | "LastUploadedUtc":null, 17 | "Published":true, 18 | "Public":true, 19 | "Provider":{"Id":1,"Name":"BUCS","Logo":"content/logos/bucs-logo.jpg","CompetitionCount":null}, 20 | "Notices":"None","Documents":null},{"Id":16,"Name":"BUCS 2015 - DAY 1 & Syncro","LocationName":"Sheffield Ice Arena","CreatedUtc":"2015-02-21T16:53:17.077Z","StartDateTimeUtc":"2015-02-21T09:00:00Z","EndDateTimeUtc":"2015-02-21T17:30:00Z","LastUploadedUtc":null,"Published":true,"Public":true,"Provider":{"Id":1,"Name":"BUCS","Logo":"content/logos/bucs-logo.jpg","CompetitionCount":null},"Notices":"None","Documents":null} 21 | */ 22 | 23 | export interface ICompetition { 24 | Id: number; 25 | Name: string; 26 | LocationName: string; 27 | CreatedUtc: string; 28 | StartDateTimeUtc: string; 29 | EndDateTimeUtc: string; 30 | LastUploadedUtc?: string; 31 | Published: boolean; 32 | Public: boolean; 33 | } 34 | 35 | export interface ICompetitionGrades { 36 | Discipline : string; 37 | Grades : IGrade[]; 38 | } 39 | 40 | // {"Id":3359,"Name":"Bournemouth University","Letter":"B","Competitors":1,"Teams":[]} 41 | export interface IClub { 42 | Id: number; 43 | Letter: string; 44 | Name: string; 45 | Competitors: number; 46 | } 47 | 48 | // {"Id":1719,"ClassName":"BUCS 1 Elite Male","CompetitorsInFinal":0,"Discipline":"Individual","Competitors":11,"Enabled":true,"Panel":3} 49 | export interface IGrade { 50 | Id: number; 51 | ClassName: string; 52 | Discipline: string; 53 | CompetitorsInFinal: number; 54 | Competitors: number; 55 | Enabled: boolean; 56 | Panel : number; 57 | } 58 | 59 | export interface IGroup { 60 | Key: any; 61 | Items: Observable; 62 | } 63 | 64 | export interface IPage { 65 | title: string; 66 | page: any; 67 | } 68 | 69 | export interface ICompetitorContext { 70 | Expanded : boolean; 71 | Competitor : ICompetitor; 72 | } 73 | 74 | export interface ICompetitor { 75 | Id: number; 76 | FullName: string; 77 | Group: string; 78 | ScoreLines: Array; 79 | Pass1: ICompetitiorScoreLine; 80 | Pass2: ICompetitiorScoreLine; 81 | Pass3: ICompetitiorScoreLine; 82 | Pass4: ICompetitiorScoreLine; 83 | Rank: number; 84 | FinalRank: number; 85 | FinalRankDisplay: () => string; 86 | 87 | StartGroup?: number; 88 | StartNumber?: number; 89 | showDetail?: boolean; 90 | } 91 | 92 | export interface ICompetitiorScoreLine { 93 | Difficulty: number; 94 | 95 | Form1: number; 96 | Form2: number; 97 | Form3: number; 98 | Form4: number; 99 | Form5: number; 100 | 101 | Sync1: number; 102 | Sync2: number; 103 | Sync3: number; 104 | 105 | Min: number; 106 | Max: number; 107 | Position: number; 108 | Score: number; 109 | StartNumber: number; 110 | Total: number; 111 | Bonus: number; 112 | Penalty: number; 113 | 114 | } 115 | 116 | interface ICorrectedScore { 117 | Value: number; 118 | Corrected: boolean; 119 | Correction: number; 120 | } 121 | -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NativeScript version of WhatsMyScore2", 3 | "main": "main.js", 4 | "version": "0.1", 5 | "author": "Matthew Green", 6 | "description": "NativeScript version of What's My Score", 7 | "license": "Apache-2.0", 8 | "android": { 9 | "v8Flags": "--expose_gc" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/pages/competition/club/club.page.ts: -------------------------------------------------------------------------------- 1 | import * as Models from "../../../models/models"; 2 | 3 | import {Component, OnInit} from "@angular/core"; 4 | 5 | import {AppRoutingService} from "../../../context/router.context"; 6 | import {ClubService} from "../../../providers/leagues/clubService"; 7 | import {CompetitionCache} from "../../../providers/leagues/competitionCache"; 8 | import {CompetitionNav} from "../../nav/competition.nav"; 9 | import {CompetitionService} from "../../../providers/leagues/competitionService"; 10 | import {CompetitorResult} from "../../templates/competitor.results"; 11 | import {GradeService} from "../../../providers/leagues/gradeService"; 12 | import {Logger} from "../../../providers/logger"; 13 | import { Observable } from "rxjs/Rx"; 14 | 15 | @Component({ 16 | selector: "club-list-page", 17 | moduleId: module.id, 18 | template: ` 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ` 43 | }) 44 | export class ClubPage implements OnInit { 45 | constructor( 46 | private logger: Logger, 47 | private clubService: ClubService, 48 | private context: AppRoutingService, 49 | private cache: CompetitionCache) { 50 | this.logger.Notify("club page started"); 51 | } 52 | 53 | public list: Observable[]>; 54 | 55 | public clubSearch($event : any): void { 56 | this.logger.Notify("Search passed to region"); 57 | this.logger.Notify($event); 58 | } 59 | 60 | public ngOnInit(): void { 61 | this.logger.Notify("club-page ngOnInit"); 62 | 63 | this.loadDetail(); 64 | } 65 | 66 | public loadDetail(): Observable { 67 | let observable: Observable = this.clubService 68 | .ListCompetitors(this.context.CompetitionId, this.context.ClubId); 69 | 70 | this.list = observable 71 | .flatMap(e=> e) 72 | .groupBy(e=> e.Group) 73 | .map(e => { 74 | let items: Observable = e.map(e=> { 75 | let context : Models.ICompetitorContext = { 76 | Competitor : e, 77 | Expanded : false 78 | }; 79 | return context; 80 | }) 81 | .publishReplay() 82 | .refCount(); 83 | 84 | let group: Models.IGroup = { 85 | Key : e.key, 86 | Items: items.toArray() 87 | }; 88 | 89 | return group; 90 | }) 91 | .toArray(); 92 | 93 | return observable; 94 | } 95 | 96 | public refresh(args: any):void { 97 | this.loadDetail().subscribe(() => { 98 | args.completed(); 99 | }); 100 | } 101 | } -------------------------------------------------------------------------------- /app/pages/competition/clubList/club.list.page.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from "@angular/core"; 2 | 3 | import {AppRoutingService} from "../../../context/router.context"; 4 | import {ClubService} from "../../../providers/leagues/clubService"; 5 | import {CompetitionCache} from "../../../providers/leagues/competitionCache"; 6 | import {CompetitionNav} from "../../nav/competition.nav"; 7 | import {CompetitionService} from "../../../providers/leagues/competitionService"; 8 | import {GradeService} from "../../../providers/leagues/gradeService"; 9 | import {IClub} from "../../../models/models"; 10 | import {Logger} from "../../../providers/logger"; 11 | import { Observable } from "rxjs/Rx"; 12 | 13 | @Component({ 14 | selector: "club-list-page", 15 | moduleId: module.id, 16 | template: ` 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | `, 51 | providers: [CompetitionService, GradeService, ClubService] 52 | }) 53 | export class ClubListPage implements OnInit { 54 | 55 | constructor( 56 | private logger: Logger, 57 | private clubService: ClubService, 58 | private context: AppRoutingService, 59 | private cache: CompetitionCache) { 60 | this.logger.Notify("club list page started"); 61 | } 62 | 63 | public loading : boolean; 64 | public list : Observable; 65 | 66 | public clubSearch($event : any): void { 67 | this.logger.Notify("Search passed to region"); 68 | this.logger.Notify($event); 69 | } 70 | 71 | public loadDetail(): Observable { 72 | this.loading = true; 73 | let clubListObservable: Observable = this.clubService.List(this.context.CompetitionId); 74 | clubListObservable.subscribe(() => { 75 | this.loading = false; 76 | }); 77 | 78 | this.list = clubListObservable; 79 | 80 | return clubListObservable; 81 | } 82 | 83 | public refresh(args: any): void { 84 | this.loadDetail().subscribe(() => { 85 | args.completed(); 86 | }); 87 | } 88 | 89 | public ngOnInit(): void { 90 | this.logger.Notify("club-list-page ngOnInit"); 91 | 92 | this.loadDetail(); 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /app/pages/competition/competition.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/pages/competition/competition.page.ts: -------------------------------------------------------------------------------- 1 | import * as Rx from "rxjs/Rx"; 2 | 3 | import { Component, OnDestroy, OnInit } from "@angular/core"; 4 | import { IClub, ICompetition, IGrade } from "../../models/models"; 5 | 6 | import {AppRoutingService} from "../../context/router.context"; 7 | import {ClubService} from "../../providers/leagues/clubService"; 8 | import {CompetitionCache} from "../../providers/leagues/competitionCache"; 9 | import {CompetitionNav} from "../nav/competition.nav"; 10 | import {CompetitionService} from "../../providers/leagues/competitionService"; 11 | import {GradeService} from "../../providers/leagues/gradeService"; 12 | import {Logger} from "../../providers/logger"; 13 | import { Observable } from "rxjs/Rx"; 14 | 15 | @Component({ 16 | selector: "Competiton", 17 | moduleId: module.id, 18 | templateUrl: "competition.page.html" 19 | }) 20 | export class CompetitionPage implements OnInit { 21 | constructor( 22 | private logger: Logger, 23 | private context: AppRoutingService, 24 | private competitionCache: CompetitionCache, 25 | private competitionService: CompetitionService, 26 | private clubService: ClubService, 27 | private gradeService: GradeService) { 28 | } 29 | 30 | public competition : Observable; 31 | public gradeCount : Observable; 32 | public clubCount : Observable; 33 | public competitorCount : Observable; 34 | 35 | ngOnInit(): void { 36 | this.logger.Notify("ngOnInit: CompetitionPage"); 37 | this.loadCompetitionDetails(); 38 | } 39 | 40 | public loadCompetitionDetails(): Observable { 41 | let competitionId: number = this.context.CompetitionId; 42 | 43 | this.competition = this.competitionService.Get(competitionId); 44 | this.clubCount = this.clubService.List(competitionId).map(e=> e.length); 45 | 46 | let gradeList = this.gradeService.List(competitionId); 47 | this.gradeCount = gradeList.map(e=> e.length); 48 | this.competitorCount = gradeList.map(e=> { 49 | let competitors = e.map(a => a.Competitors); 50 | let total: number = competitors.reduce((a,b) => a+=b ); 51 | return total; 52 | }); 53 | 54 | let forAll: Observable = Observable.combineLatest(this.competition, this.clubCount, this.gradeCount); 55 | 56 | return forAll; // .combineLatest(observable,clubsObservable,gradesObservable); 57 | } 58 | 59 | public refresh(args: any): void { 60 | this.loadCompetitionDetails().subscribe(() => { 61 | args.completed(); 62 | }); 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /app/pages/competition/findCompetitor/find.competitor.page.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from "@angular/core"; 2 | 3 | import {AppRoutingService} from "../../../context/router.context"; 4 | import {ClubService} from "../../../providers/leagues/clubService"; 5 | import {CompetitionNav} from "../../nav/competition.nav"; 6 | import {CompetitionService} from "../../../providers/leagues/competitionService"; 7 | import {GradeService} from "../../../providers/leagues/gradeService"; 8 | import {Logger} from "../../../providers/logger"; 9 | 10 | @Component({ 11 | selector: "find-competitor-page", 12 | moduleId: module.id, 13 | template: ` 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | `, 41 | providers: [CompetitionService, GradeService, ClubService] 42 | }) 43 | export class FindCompetitorPage { 44 | 45 | constructor( 46 | private logger: Logger, 47 | private context: AppRoutingService) { 48 | 49 | this.logger.Notify("grade list page started"); 50 | } 51 | 52 | public list : Array = []; 53 | } -------------------------------------------------------------------------------- /app/pages/competition/grade/competitors/grade.competitors.page.ts: -------------------------------------------------------------------------------- 1 | import "rxjs/add/operator/max"; 2 | import "rxjs/add/operator/distinct"; 3 | 4 | import * as Models from "../../../../models/models"; 5 | import * as Rx from "rxjs"; 6 | 7 | import {Component, OnInit} from "@angular/core"; 8 | 9 | import {AppRoutingService} from "../../../../context/router.context"; 10 | import {ClubService} from "../../../../providers/leagues/clubService"; 11 | import {CompetitionCache} from "../../../../providers/leagues/competitionCache"; 12 | import {CompetitionNav} from "../../../nav/competition.nav"; 13 | import {CompetitionService} from "../../../../providers/leagues/competitionService"; 14 | import {CompetitorService} from "../../../../providers/leagues/competitorService"; 15 | import {GradeService} from "../../../../providers/leagues/gradeService"; 16 | import {Logger} from "../../../../providers/logger"; 17 | import { Observable } from "rxjs"; 18 | 19 | @Component({ 20 | selector: "grade-competitors-page", 21 | moduleId: module.id, 22 | template: ` 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | `, 51 | providers: [CompetitionService, GradeService, ClubService, CompetitorService] 52 | }) 53 | export class GradeCompetitorsPage implements OnInit { 54 | constructor( 55 | private logger: Logger, 56 | private gradeService: GradeService, 57 | private competitorService: CompetitorService, 58 | private context: AppRoutingService, 59 | private cache: CompetitionCache) { 60 | this.logger.Notify("grade list page started"); 61 | } 62 | 63 | public list: Observable; 64 | public groupedList: Models.IGroup; 65 | public groups: number = 0; // if more than one group change the label 66 | 67 | public gradeSearch($event: any):void { 68 | this.logger.Notify("Search passed to region"); 69 | this.logger.Notify($event); 70 | } 71 | 72 | public ngOnInit(): void { 73 | this.logger.Notify("grade-list-page ngOnInit"); 74 | 75 | this.loadDetail(); 76 | } 77 | 78 | public loadDetail(): Observable { 79 | let obseravable: Observable = this.competitorService 80 | .ListGradeCompetitors(this.context.CompetitionId, this.context.GradeId); 81 | 82 | obseravable 83 | .flatMap(e=> e) 84 | .groupBy(e=> e.StartGroup) 85 | .map(e=> { 86 | return e.publishReplay().refCount(); 87 | }) 88 | .toArray() 89 | 90 | return obseravable; 91 | } 92 | 93 | public refresh(args: any): void { 94 | this.loadDetail().subscribe(() => { 95 | args.completed(); 96 | }); 97 | } 98 | 99 | } -------------------------------------------------------------------------------- /app/pages/competition/grade/grade.page.ts: -------------------------------------------------------------------------------- 1 | import "rxjs/add/operator/max"; 2 | import "rxjs/add/operator/distinct"; 3 | 4 | import * as Models from "../../../models/models"; 5 | import * as Rx from "rxjs"; 6 | 7 | import {ChangeDetectionStrategy, Component, Input, OnInit} from "@angular/core"; 8 | 9 | import {AppRoutingService} from "../../../context/router.context"; 10 | import {ClubService} from "../../../providers/leagues/clubService"; 11 | import {CompetitionCache} from "../../../providers/leagues/competitionCache"; 12 | import {CompetitionNav} from "../../nav/competition.nav"; 13 | import {CompetitionService} from "../../../providers/leagues/competitionService"; 14 | import {CompetitorResult} from "../../templates/competitor.results"; 15 | import {CompetitorService} from "../../../providers/leagues/competitorService"; 16 | import {GradeService} from "../../../providers/leagues/gradeService"; 17 | import {Logger} from "../../../providers/logger"; 18 | import { Observable } from "rxjs"; 19 | 20 | @Component({ 21 | selector: "grade-competitors-page", 22 | template: ` 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | `, 47 | providers: [CompetitionService, GradeService, ClubService, CompetitorService], 48 | }) 49 | export class GradeCompetitorsPage implements OnInit { 50 | constructor( 51 | private logger: Logger, 52 | private gradeService: GradeService, 53 | private competitorService: CompetitorService, 54 | private context: AppRoutingService, 55 | private cache: CompetitionCache) { 56 | this.logger.Notify("grade list page started"); 57 | } 58 | 59 | public list: Observable; 60 | 61 | public gradeSearch($event: any): void { 62 | this.logger.Notify("Search passed to region"); 63 | this.logger.Notify($event); 64 | } 65 | 66 | public ngOnInit(): void { 67 | this.logger.Notify("grade-page ngOnInit"); 68 | 69 | this.loadDetail(); 70 | } 71 | 72 | public loadDetail(): Observable { 73 | let obseravable: Observable = this.competitorService 74 | .ListGradeCompetitors(this.context.CompetitionId, this.context.GradeId); 75 | 76 | let viewModel = obseravable 77 | .map((e) => { 78 | let list: Models.ICompetitor[] = e.sort((a,b) => { 79 | return a.FinalRank - b.FinalRank; 80 | }); 81 | return list; 82 | }) 83 | .map((e : Models.ICompetitor[]) => { 84 | let contexts: Models.ICompetitorContext[] = e.map(item => { 85 | return { 86 | Expanded : false, 87 | Competitor : item 88 | }; 89 | }); 90 | return contexts; 91 | }); 92 | 93 | this.list = viewModel; 94 | 95 | return obseravable; 96 | } 97 | 98 | public refreshStarted(args: any): void { 99 | this.logger.Notify("Grade: refresh starting"); 100 | this.loadDetail().subscribe(() => { 101 | args.completed(); 102 | }); 103 | } 104 | 105 | public refreshCompleted(): void { 106 | this.logger.Notify("Grade: refresh completed"); 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /app/pages/competition/gradeList/grade.list.page.ts: -------------------------------------------------------------------------------- 1 | import * as Rx from "rxjs"; 2 | 3 | import {Component, OnDestroy, OnInit} from "@angular/core"; 4 | 5 | import {AppRoutingService} from "../../../context/router.context"; 6 | import {ClubService} from "../../../providers/leagues/clubService"; 7 | import {CompetitionCache} from "../../../providers/leagues/competitionCache"; 8 | import {CompetitionNav} from "../../nav/competition.nav"; 9 | import {CompetitionService} from "../../../providers/leagues/competitionService"; 10 | import {GradeService} from "../../../providers/leagues/gradeService"; 11 | import {IGrade} from "../../../models/models"; 12 | import {Logger} from "../../../providers/logger"; 13 | import { Observable } from "rxjs"; 14 | 15 | @Component({ 16 | selector: "grade-list-page", 17 | template: ` 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | `, 52 | providers: [CompetitionService, GradeService, ClubService] 53 | }) 54 | export class GradeListPage implements OnInit { 55 | constructor( 56 | private logger: Logger, 57 | private competitionService : CompetitionService, 58 | private gradeService: GradeService, 59 | private context: AppRoutingService, 60 | private cache: CompetitionCache) { 61 | 62 | this.logger.Notify("grade list page started"); 63 | } 64 | 65 | public loading : boolean = true; 66 | public list : Observable; 67 | 68 | public gradeSearch($event : any): void { 69 | this.logger.Notify($event); 70 | } 71 | 72 | public loadDetail(): Observable { 73 | this.logger.Notify("load grade list"); 74 | this.list = this.gradeService.List(this.context.CompetitionId); 75 | this.list.subscribe(() => { 76 | this.logger.Notify("grade list loaded"); 77 | this.loading = false; 78 | }); 79 | return this.list; 80 | } 81 | 82 | public refresh(args: any): void { 83 | this.logger.Notify("Refresh grade-list page"); 84 | this.loadDetail().subscribe(() => { 85 | args.completed(); 86 | }); 87 | } 88 | 89 | public ngOnInit(): void { 90 | this.logger.Notify("grade-list-page ngOnInit"); 91 | 92 | this.loadDetail(); 93 | } 94 | } -------------------------------------------------------------------------------- /app/pages/competition/information/information.page.ts: -------------------------------------------------------------------------------- 1 | import {AppRoutingService} from "../../../context/router.context"; 2 | import {ClubService} from "../../../providers/leagues/clubService"; 3 | import {CompetitionCache} from "../../../providers/leagues/competitionCache"; 4 | import {CompetitionNav} from "../../nav/competition.nav"; 5 | import {CompetitionService} from "../../../providers/leagues/competitionService"; 6 | import {Component} from "@angular/core"; 7 | import {GradeService} from "../../../providers/leagues/gradeService"; 8 | import {ICompetition} from "../../../models/models"; 9 | import {Logger} from "../../../providers/logger"; 10 | import { Observable } from "rxjs/Rx"; 11 | 12 | @Component({ 13 | selector: "grade-list-page", 14 | template: ` 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | `, 38 | providers: [CompetitionService, GradeService, ClubService] 39 | }) 40 | export class InformationPage { 41 | constructor( 42 | private logger: Logger, 43 | private context: AppRoutingService, 44 | private competitionCache : CompetitionCache, 45 | private competitionService: CompetitionService) { 46 | this.logger.Notify("grade list page started"); 47 | } 48 | 49 | public competition : any; 50 | 51 | // passed to the child component 52 | public regionsHintText = "Hi from regions"; 53 | 54 | public ngOnInit(): void { 55 | if(this.competitionCache.Competition) { 56 | this.competition = this.competitionCache.Competition; 57 | return; 58 | } 59 | this.loadDetail(); 60 | } 61 | 62 | public loadDetail(): Observable { 63 | let competitionId: number = this.context.CompetitionId; 64 | let observable: Observable = this.competitionService.Get(competitionId); 65 | 66 | observable 67 | .subscribe((competition : ICompetition) => { 68 | this.competitionCache.Competition = competition; 69 | }, (error)=> { 70 | this.logger.Error(error); 71 | }); 72 | 73 | return observable; 74 | } 75 | 76 | public refresh(args: any): void { 77 | this.loadDetail().subscribe(() => { 78 | args.completed(); 79 | }); 80 | } 81 | } -------------------------------------------------------------------------------- /app/pages/competition/startList/obsolete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/pages/competition/startList/start.list.items.control.ts: -------------------------------------------------------------------------------- 1 | import {Observable, Subject, Subscription} from "rxjs/Rx"; 2 | 3 | import { Component } from "@angular/core"; 4 | import {GroupedObservable} from "rxjs/operator/groupBy"; 5 | import {IGrade} from "../../../models/models"; 6 | import {Logger} from "../../../providers/logger"; 7 | 8 | @Component({ 9 | selector : "StartListItems", 10 | template : ` 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | `, 21 | inputs: ["title", "items"] 22 | }) 23 | export class StartListItems { 24 | constructor(private logger: Logger) { 25 | 26 | } 27 | 28 | public title = ""; 29 | public grades: Observable; 30 | 31 | private _items: GroupedObservable; 32 | public get items() : GroupedObservable { 33 | return this._items; 34 | }; 35 | 36 | public set items(value: GroupedObservable) { 37 | this._items = value; 38 | value.subscribe(x=> { 39 | this.logger.Notify("key: " + value.key + " name:" + x.ClassName); 40 | }); 41 | this.grades = value.toArray() 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /app/pages/competition/startList/start.list.page.ts: -------------------------------------------------------------------------------- 1 | import * as Models from "../../../models/models"; 2 | 3 | import {Component, OnInit} from "@angular/core"; 4 | import { IGrade, IGroup } from "../../../models/models"; 5 | import { Observable, ReplaySubject, Subject, Subscription } from "rxjs/Rx"; 6 | 7 | import {AppRoutingService} from "../../../context/router.context"; 8 | import {ClubService} from "../../../providers/leagues/clubService"; 9 | import {CompetitionCache} from "../../../providers/leagues/competitionCache"; 10 | import {CompetitionNav} from "../../nav/competition.nav"; 11 | import {CompetitionService} from "../../../providers/leagues/competitionService"; 12 | import {GradeService} from "../../../providers/leagues/gradeService"; 13 | import {GroupedObservable} from "rxjs/operator/groupBy"; 14 | import {Logger} from "../../../providers/logger"; 15 | import {StartListItems} from "./start.list.items.control"; 16 | 17 | @Component({ 18 | selector: "start-list-page", 19 | template: ` 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | `, 52 | providers: [CompetitionService, GradeService, ClubService], 53 | }) 54 | export class StartListPage implements OnInit { 55 | constructor( 56 | private logger: Logger, 57 | private context: AppRoutingService, 58 | private cache: CompetitionCache, 59 | private gradeService : GradeService) { 60 | } 61 | 62 | public list : Observable[]>; 63 | 64 | public gradeSearch($event : any): void { 65 | this.logger.Notify("Search passed to start list"); 66 | this.logger.Notify($event); 67 | } 68 | 69 | private CreateViewModel(grades: Observable): void { 70 | 71 | var groupMap: Observable[]> = grades 72 | .flatMap(e=> e) 73 | .groupBy((x)=> x.Discipline) 74 | .map(disciplineGroups => { 75 | let items = disciplineGroups.publishReplay().refCount().toArray(); 76 | 77 | let group : IGroup = { 78 | Key: disciplineGroups.key, 79 | Items: items 80 | }; 81 | 82 | group.Items.subscribe(y=> { 83 | this.logger.Notify(`${disciplineGroups.key}: ${y.length}`); 84 | }); 85 | return group; 86 | }).toArray(); 87 | 88 | this.list = groupMap; 89 | this.list.subscribe(x => { 90 | this.logger.Notify(`groups: ${x.length}`); 91 | }); 92 | } 93 | 94 | public ngOnInit():void { 95 | this.logger.Notify("start-list-page ngOnInit"); 96 | 97 | if(this.cache.HasGrades()) { 98 | var items : Observable = Observable.of(this.cache.Grades); 99 | 100 | this.CreateViewModel(items) ; 101 | 102 | return; 103 | } 104 | 105 | this.loadDetail(); 106 | } 107 | 108 | public loadDetail(): Observable { 109 | let observable : Observable = this.gradeService 110 | .List(this.context.CompetitionId); 111 | 112 | this.CreateViewModel(observable); 113 | 114 | return observable; 115 | } 116 | 117 | public refresh(args: any): void { 118 | this.loadDetail().subscribe(() => { 119 | args.completed(); 120 | }); 121 | } 122 | } -------------------------------------------------------------------------------- /app/pages/competition/stats/stats.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/pages/competition/stats/stats.page.ts: -------------------------------------------------------------------------------- 1 | import {AppRoutingService} from "../../../context/router.context"; 2 | import {ClubService} from "../../../providers/leagues/clubService"; 3 | import {CompetitionNav} from "../../nav/competition.nav"; 4 | import {CompetitionService} from "../../../providers/leagues/competitionService"; 5 | import {Component} from '@angular/core'; 6 | import {GradeService} from "../../../providers/leagues/gradeService"; 7 | import {Logger} from "../../../providers/logger"; 8 | 9 | @Component({ 10 | selector: "stats-page", 11 | templateUrl: "pages/competition/stats/stats.page.html", 12 | providers: [CompetitionService, GradeService, ClubService] 13 | }) 14 | export class StatsPage 15 | { 16 | constructor( 17 | private logger: Logger, 18 | private context: AppRoutingService) 19 | { 20 | 21 | this.logger.Notify("grade list page started"); 22 | } 23 | 24 | public list : Array = []; 25 | 26 | 27 | //passed to the child component 28 | public regionsHintText = "Hi from regions"; 29 | 30 | //action to 31 | public regionSearch($event : any) 32 | { 33 | this.logger.Notify("Search passed to region"); 34 | this.logger.Notify($event); 35 | //this.logger.Notify("Search Term in Regions Page: " + $event.Value); 36 | } 37 | 38 | /* angular2 lifecycle */ 39 | public ngOnInit(){ 40 | 41 | 42 | this.logger.Notify("Region-page ngAfterViewInit"); 43 | 44 | //time to load the data 45 | 46 | } 47 | 48 | 49 | 50 | } -------------------------------------------------------------------------------- /app/pages/mapPage/mapPage.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/pages/mapPage/mapPage.html -------------------------------------------------------------------------------- /app/pages/mapPage/mapPage.ts: -------------------------------------------------------------------------------- 1 | import {Observable, EventData } from "data/observable"; 2 | import {alert} from "ui/dialogs"; 3 | 4 | import {Inject, Component} from '@angular/core'; 5 | import {Logger} from "../../providers/logger"; 6 | //import {Router} from "@angular/router-deprecated"; 7 | import {NxNav} from "../../controls/nav/nav"; 8 | import {NxList} from "../../controls/list/list"; 9 | import {NxListItem} from "../../controls/list/list-item"; 10 | import {NxHeader} from "../../controls/list/header"; 11 | import {IonIcon,NavIcon} from "../../controls/icons/ion-icon"; 12 | //import {TitleTransform} from "../../pipes/title"; 13 | @Component({ 14 | selector: "map-page", 15 | //move directives to App .. 16 | templateUrl: "pages/mapPage/mapPage.html" 17 | }) 18 | export class MapPage 19 | { 20 | constructor(private logger:Logger) 21 | { 22 | this.logger.Notify("Start Page - constructor hit"); 23 | } 24 | 25 | public pageLoaded(args: any): void { 26 | this.logger.Notify("start page - loaded"); 27 | console.log("start page - loaded - i happen alot?"); 28 | } 29 | 30 | public loadRegions(args: EventData) : void{ 31 | this.logger.Notify("time to load regions"); 32 | 33 | if(args){ 34 | this.logger.Notify("There are args"); 35 | //to do animate transition 36 | } 37 | 38 | alert("nav is broken - not sure why."); 39 | 40 | //let promise: Promise = this.router.navigate(["Regions"]); 41 | 42 | // promise.then(() => { 43 | // this.logger.Notify("I Should have navigated from start -> regions"); 44 | // }); 45 | 46 | // promise.catch(() => { 47 | // this.logger.Notify("I failed navigating from start -> regions"); 48 | // }); 49 | } 50 | 51 | public incomplete(args: EventData) : void { 52 | alert("Its not made yet"); 53 | } 54 | 55 | 56 | } 57 | 58 | 59 | //var vmModule = require("./main-view-model"); 60 | // export function pageLoaded(args) { 61 | // var page = args.object; 62 | // var vm = new startPage(); 63 | // page.bindingContext = vm; 64 | // } 65 | 66 | //exports.pageLoaded = pageLoaded; 67 | -------------------------------------------------------------------------------- /app/pages/menus.ref.ts: -------------------------------------------------------------------------------- 1 | export { CompetitionNav } from "./nav/competition.nav"; 2 | export { StartNav } from "./nav/start.nav.control" -------------------------------------------------------------------------------- /app/pages/nav/competition.nav.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/pages/nav/competition.nav.ts: -------------------------------------------------------------------------------- 1 | import {Component, Inject} from "@angular/core"; 2 | import {EventData, Observable} from "data/observable"; 3 | 4 | import {Logger} from "../../providers/logger"; 5 | import {Settings} from "../../providers/routes/routes"; 6 | import {alert} from "ui/dialogs"; 7 | 8 | @Component({ 9 | selector: "competition-nav", 10 | templateUrl: "pages/nav/competition.nav.html" 11 | }) 12 | export class CompetitionNav { 13 | constructor(private logger:Logger) { 14 | this.logger.Notify("competition-nav - constructor hit"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/pages/nav/start.nav.control.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/pages/nav/start.nav.control.ts: -------------------------------------------------------------------------------- 1 | import {Component, Inject} from "@angular/core"; 2 | import {EventData, Observable} from "data/observable"; 3 | 4 | import {Logger} from "../../providers/logger"; 5 | import {NxDrawer} from "../../controls/drawer/drawer"; 6 | import {Settings} from "../../providers/routes/routes"; 7 | import {StartListControl} from "../start/stat.list.start.control"; 8 | import {StartListSearchControl} from "../start/start.list.search.control"; 9 | import {alert} from "ui/dialogs"; 10 | 11 | @Component({ 12 | moduleId: module.id, 13 | selector: "start-nav", 14 | templateUrl: "start.nav.control.html", 15 | }) 16 | export class StartNav { 17 | 18 | constructor(private logger:Logger) { 19 | this.logger.Notify("Start Page - constructor hit"); 20 | } 21 | public loadRegions(args: EventData): void { 22 | this.logger.Notify("time to load regions"); 23 | } 24 | } -------------------------------------------------------------------------------- /app/pages/pages.ref.ts: -------------------------------------------------------------------------------- 1 | export { StatsPage } from "./competition/stats/stats.page"; 2 | // export { TestPage } from "./test/test.page"; 3 | // export { ParallaxTestPage } from "./test/parallax.page"; 4 | export { StartPage } from "./start/start.page"; 5 | export { StartListSearchControl } from "./start/start.list.search.control"; 6 | export { StartListControl} from "./start/stat.list.start.control"; 7 | 8 | export { RegionsPage } from "./regions/regions.page"; 9 | export { RegionPage } from "./region/region.page"; 10 | 11 | 12 | export { CompetitionPage } from "./competition/competition.page"; 13 | export { ClubListPage } from "./competition/clubList/club.list.page"; 14 | export {ClubPage} from "./competition/club/club.page"; 15 | export { FindCompetitorPage } from "./competition/findCompetitor/find.competitor.page"; 16 | export { GradeListPage } from "./competition/gradeList/grade.list.page"; 17 | export {GradeCompetitorsPage} from "./competition/grade/grade.page"; 18 | export { InformationPage } from "./competition/information/information.page"; 19 | export { StartListPage } from "./competition/startList/start.list.page"; 20 | export {StartListGradePage } from "./competition/startList/competitors/competitors.page"; 21 | 22 | //level 4 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/pages/region/region.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/pages/region/region.page.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnDestroy, OnInit} from "@angular/core"; 2 | import {ICompetition, IRegion} from "../../models/models"; 3 | import {Observable, Subscription} from "rxjs"; 4 | 5 | import {ActivatedRoute} from "@angular/router"; 6 | import {AppRoutingService} from "../../context/router.context"; 7 | import {CompetitionService} from "../../providers/leagues/competitionService"; 8 | import {Logger} from "../../providers/logger"; 9 | import {PullToRefresh} from "nativescript-pulltorefresh"; 10 | import {RegionCache} from "../../providers/leagues/regionCache"; 11 | import { RegionService } from "../../providers/leagues/regionService"; 12 | import {StartNav} from "../nav/start.nav.control"; 13 | 14 | @Component({ 15 | selector: "Region", 16 | moduleId: module.id, 17 | templateUrl: "region.page.html" 18 | }) 19 | export class RegionPage implements OnInit { 20 | constructor( 21 | private context : AppRoutingService, 22 | private logger: Logger, 23 | private regionCache: RegionCache, 24 | private regionService: RegionService, 25 | private competitionService: CompetitionService) { 26 | 27 | this.logger.Notify("region page loaded"); 28 | } 29 | 30 | public list : Observable; 31 | public region : Observable; 32 | 33 | public refresh(args: any): void { 34 | let control : PullToRefresh = args.object; 35 | 36 | this.loadDetail().subscribe(() => { 37 | args.completed(); 38 | }); 39 | } 40 | 41 | private loadDetail(): Observable { 42 | let regionObservable: Observable = this.regionService 43 | .Get(this.context.RegionId); 44 | let competitionsObservable: Observable = this.competitionService 45 | .List(this.context.RegionId); 46 | 47 | this.region = regionObservable; 48 | this.list = competitionsObservable; 49 | 50 | return Observable.combineLatest(regionObservable, competitionsObservable); 51 | } 52 | 53 | private regionSubscription: Subscription; 54 | 55 | ngOnInit(): void { 56 | this.logger.Notify(`ngOnInit: RegionPage ${this.context.RegionId}`); 57 | this.region = this.regionCache.RegionChange.filter(e=> e !== null); 58 | 59 | this.loadDetail(); 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /app/pages/regions/regions.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/pages/regions/regions.page.ts: -------------------------------------------------------------------------------- 1 | import * as Providers from "../../providers/providers.ref"; 2 | 3 | import { Component, OnInit, ViewChild } from "@angular/core"; 4 | 5 | import { IRegion } from "../../models/models"; 6 | import { Logger } from "../../providers/logger"; 7 | import { Observable } from "rxjs/Rx"; 8 | import { StartNav } from "../nav/start.nav.control"; 9 | 10 | @Component({ 11 | selector: "regions-page", 12 | moduleId: module.id, 13 | templateUrl: "regions.page.html", 14 | }) 15 | export class RegionsPage implements OnInit { 16 | constructor( 17 | private logger: Logger, 18 | private regions: Providers.RegionService) { 19 | } 20 | 21 | public list : Observable; 22 | 23 | public refresh(args: any): void { 24 | this.logger.Notify("regions page refresh => load data"); 25 | this.loadDetail().subscribe(() => { 26 | this.logger.Notify("load regions completed"); 27 | args.completed(); 28 | }); 29 | } 30 | 31 | public loadDetail(): Observable { 32 | this.logger.Notify("load regions"); 33 | 34 | this.list = this.regions.List(); 35 | 36 | return this.list; 37 | } 38 | 39 | public ngOnInit(): void { 40 | this.loadDetail(); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /app/pages/start/start.list.search.control.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "start-list-search", 5 | template: ` 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ` 18 | }) 19 | export class StartListSearchControl { 20 | } -------------------------------------------------------------------------------- /app/pages/start/start.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/pages/start/start.page.ts: -------------------------------------------------------------------------------- 1 | import {Component, Inject, OnInit} from "@angular/core"; 2 | import {Headers, Http, RequestOptionsArgs} from "@angular/http"; 3 | 4 | import {ActionItem} from "ui/action-bar"; 5 | import {AppRoutingService} from "../../context/router.context"; 6 | import {Logger} from "../../providers/logger"; 7 | import {NxDrawer} from "../../controls/drawer/drawer"; 8 | import {PageRoute} from "nativescript-angular"; 9 | import {Settings} from "../../providers/routes/routes"; 10 | import {StartListControl} from "./stat.list.start.control"; 11 | import {StartListSearchControl} from "./start.list.search.control"; 12 | import {StartNav} from "../nav/start.nav.control"; 13 | import {alert} from "ui/dialogs"; 14 | 15 | // import {Observable, EventData } from "data/observable"; 16 | 17 | 18 | @Component({ 19 | selector: "start", 20 | templateUrl: "pages/start/start.page.html", 21 | }) 22 | export class StartPage { 23 | 24 | constructor(private logger:Logger, private appRouteingService: AppRoutingService) { 25 | } 26 | 27 | public refresh(args: any): void { 28 | 29 | setTimeout(()=> { 30 | args.completed(); 31 | }, 1000); 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/pages/start/stat.list.start.control.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "start-list-main", 5 | template: ` 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ` 19 | }) 20 | export class StartListControl { 21 | } -------------------------------------------------------------------------------- /app/pages/templates.ref.ts: -------------------------------------------------------------------------------- 1 | export {CompetitorResult, ResultsDetailRow} from "./templates/competitor.results"; 2 | export {CompetitorResultRow, CompetitorResultRowHeader} from "./templates/competitor.result.score.row" -------------------------------------------------------------------------------- /app/pages/templates/competitor.result.score.row.ts: -------------------------------------------------------------------------------- 1 | import {ChangeDetectionStrategy, Component, Input} from "@angular/core"; 2 | 3 | import {ICompetitiorScoreLine} from "../../models/models"; 4 | import {Logger} from "../../providers/logger"; 5 | 6 | @Component({ 7 | selector: "competitor-result-row-header", 8 | template: ` 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | `, 20 | styleUrls: ["./pages/templates/competitor.results.css"] 21 | }) 22 | export class CompetitorResultRowHeader { 23 | 24 | } 25 | 26 | @Component({ 27 | selector: "competitor-result-row", 28 | changeDetection: ChangeDetectionStrategy.OnPush, 29 | template: ` 30 | 31 | 32 | 35 | 38 | 41 | 44 | 47 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | `, 58 | styleUrls: ["./pages/templates/competitor.results.css"] 59 | }) 60 | export class CompetitorResultRow { 61 | private model : ICompetitiorScoreLine; 62 | 63 | private formMinIndex : number; 64 | private formMaxIndex : number; 65 | 66 | public excludeIndividualTrampolineScore(index: number): boolean { 67 | this.logger.Notify("check score"); 68 | this.logger.Notify("compare: "+ index + " to " + this.formMinIndex + " or " + this.formMinIndex); 69 | return index === this.formMinIndex || index === this.formMaxIndex; 70 | } 71 | 72 | @Input() 73 | public set scoreline(value : ICompetitiorScoreLine){ 74 | this.model = value; 75 | this.setupIndividual(); 76 | this.logger.NotifyObjectProperties(value); 77 | } 78 | 79 | private setupIndividual(): void { 80 | let formScores : number[] = [ 81 | this.model.Form1, 82 | this.model.Form2, 83 | this.model.Form3, 84 | this.model.Form4, 85 | this.model.Form5 86 | ]; 87 | 88 | let min : number = formScores[0]; 89 | let max : number = formScores[0]; 90 | 91 | this.formMinIndex = 0; 92 | this.formMaxIndex = 0; 93 | 94 | for (let i: number = 1; i < formScores.length; i++) { 95 | if (formScores[i] > max) { 96 | this.formMaxIndex = i; 97 | max = formScores[i]; 98 | }else if(formScores[i] < min) { 99 | this.formMinIndex = i; 100 | min = formScores[i]; 101 | } 102 | } 103 | } 104 | 105 | constructor(private logger: Logger) { 106 | 107 | } 108 | } -------------------------------------------------------------------------------- /app/pages/templates/competitor.results.css: -------------------------------------------------------------------------------- 1 | GridLayout Label { 2 | padding: 5; 3 | } 4 | 5 | GridLayout.header { 6 | border-top-left-radius: 4; 7 | border-top-right-radius: 4; 8 | } 9 | StackLayout.header Label{ 10 | background-color: #1E88E5; 11 | color: #BBDEFB; 12 | font-size: 14; 13 | } 14 | GridLayout.header Label{ 15 | background-color: #1E88E5; 16 | color: #BBDEFB; 17 | font-size: 14; 18 | } 19 | 20 | GridLayout.result Label { 21 | font-size: 14; 22 | color: #37474F; 23 | 24 | } 25 | GridLayout.result Label.invalid { 26 | color: #90A4AE; 27 | text-decoration: line-through; 28 | } 29 | 30 | .blue { color: #2196F3; } 31 | .blue-100 { color: #BBDEFB; } 32 | .blue-200 { color: #90CAF9; } 33 | .blue-300 { color: #64B5F6; } 34 | .blue-400 { color: #42A5F5; } 35 | .blue-500 { color: #2196F3; } 36 | .blue-600 { color: #1E88E5; } 37 | .blue-700 { color: #1976D2; } 38 | .blue-800 { color: #1565C0; } 39 | .blue-900 { color: #0D47A1; } 40 | .blue-a1 { color: #82B1FF; } 41 | .blue-a2 { color: #448AFF; } 42 | .blue-a4 { color: #2979FF; } 43 | .blue-a7 { color: #2962FF; } 44 | 45 | .blue-grey { color: #607D8B; } 46 | .blue-grey-100 { color: #CFD8DC; } 47 | .blue-grey-200 { color: #B0BEC5; } 48 | .blue-grey-300 { color: #90A4AE; } 49 | .blue-grey-400 { color: #78909C; } 50 | .blue-grey-500 { color: #607D8B; } 51 | .blue-grey-600 { color: #546E7A; } 52 | .blue-grey-700 { color: #455A64; } 53 | .blue-grey-800 { color: #37474F; } 54 | .blue-grey-900 { color: #263238; } 55 | -------------------------------------------------------------------------------- /app/pages/templates/competitor.results.ts: -------------------------------------------------------------------------------- 1 | import {ChangeDetectionStrategy, Component, Input} from "@angular/core"; 2 | import {CompetitorResultRow, CompetitorResultRowHeader} from "./competitor.result.score.row"; 3 | 4 | import {ICompetitorContext} from "../../models/models"; 5 | import {Logger} from "../../providers/logger"; 6 | 7 | @Component({ 8 | selector: "competitor-result-detail-row", 9 | template: `` 10 | }) 11 | export class ResultsDetailRow { 12 | @Input() 13 | public person; 14 | } 15 | 16 | @Component({ 17 | selector: "competitor-result", 18 | styleUrls: ["./pages/templates/competitor.results.css"], 19 | template: ` 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 52 | 53 | `, 54 | changeDetection: ChangeDetectionStrategy.Default, 55 | }) 56 | 57 | export class CompetitorResult { 58 | private context : ICompetitorContext = undefined; 59 | 60 | public ShowHideResults(): void { 61 | this.logger.Notify("expand: " + this.context.Competitor.FullName); 62 | this.context.Expanded = !this.context.Expanded; 63 | } 64 | 65 | @Input("competitor") 66 | public set competitor(value: ICompetitorContext){ 67 | this.context = value; 68 | } 69 | 70 | public IsExpanded(): boolean { 71 | return this.context.Expanded; 72 | } 73 | 74 | public GetRank(): string { 75 | if(!this.context) { 76 | return "-"; 77 | } 78 | 79 | return this.context.Competitor.FinalRank > 0 80 | // for those competitors reaching the final 81 | ? CompetitorResult.DisplayRank(this.context.Competitor.FinalRank) 82 | // everyone else 83 | : CompetitorResult.DisplayRank(this.context.Competitor.Rank); 84 | } 85 | 86 | constructor(private logger: Logger) { 87 | } 88 | 89 | public static DisplayRank(value: number): string { 90 | if (value <= 0) { return value.toString(); } 91 | switch (value % 100) { 92 | case 11: 93 | case 12: 94 | case 13: 95 | return value + "th"; 96 | } 97 | switch (value % 10) { 98 | case 1: 99 | return value + "st"; 100 | case 2: 101 | return value + "nd"; 102 | case 3: 103 | return value + "rd"; 104 | default: 105 | return value + "th"; 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /app/pipes/dates/dates.ts: -------------------------------------------------------------------------------- 1 | import { PipeTransform, Pipe } from "@angular/core"; 2 | import { Logger } from "../../providers/logger"; 3 | var moment = require("moment"); 4 | 5 | @Pipe({name: 'DisplayDate', pure: true}) 6 | export class DisplayDate implements PipeTransform { 7 | constructor(private logger: Logger) 8 | { 9 | } 10 | 11 | transform(value: any, args: any[] = []) { 12 | var date = moment(value); 13 | 14 | return date.format('llll'); 15 | } 16 | } -------------------------------------------------------------------------------- /app/pipes/orderBy/orderBy.ts: -------------------------------------------------------------------------------- 1 | import { PipeTransform, Pipe } from "@angular/core"; 2 | import { Logger } from "../../providers/logger"; 3 | var _ = require("underscore"); 4 | 5 | //import {orderBy} from 'lodash/orderBy'; 6 | //var orderBy = require("lodash/orderBy") 7 | 8 | // import { 9 | // StringWrapper, 10 | // isBlank, 11 | // isString, 12 | // isArray, 13 | // CONST, 14 | // FunctionWrapper 15 | // } 16 | // from 'angular2/src/facade/lang'; 17 | 18 | export function isBlank(obj: any): boolean { 19 | return obj === undefined || obj === null; 20 | } 21 | export function isArray(obj: any): boolean { 22 | return Array.isArray(obj); 23 | } 24 | export function isString(obj: any): boolean { 25 | return typeof obj === "string"; 26 | } 27 | 28 | @Pipe({ 29 | name: 'orderBy', 30 | pure: true 31 | }) 32 | export class OrderByPipe implements PipeTransform { 33 | constructor(private logger: Logger) {} 34 | 35 | transform(value: any, args: any = []) { 36 | console.log("orderBy pipe - transform"); 37 | let expression: string = null; 38 | let ascending: boolean = true; 39 | 40 | if (isBlank(args)) return value; 41 | if (isString(args)){ 42 | expression = args; 43 | }else{ 44 | expression = args[0]; 45 | } 46 | if (isArray(args) && args.length > 1){ 47 | ascending = args[1]; 48 | } 49 | //var descending: boolean = args.length > 1 ? args[1] : false; 50 | 51 | let orderedAsc = _.sortBy(value, expression); 52 | 53 | if(ascending) { return orderedAsc; } 54 | 55 | return orderedAsc.reverse(); 56 | //let result = descending ? orderedAsc.reverse() : orderedAsc; 57 | 58 | //return result; 59 | } 60 | } 61 | 62 | @Pipe({ 63 | name: "groupBy", 64 | pure: true 65 | }) 66 | export class GroupByPipe { 67 | constructor(private logger: Logger) {} 68 | 69 | transform(value: any, args: string) { 70 | console.log("groupBy by pipe - transform"); 71 | 72 | if (isBlank(args)) return value; 73 | 74 | 75 | var expression = args; //args.length > 0 ? args[0] : null; 76 | 77 | let grouped = _.chain(value).groupBy(expression).map((value, key) => { 78 | return { 79 | key: key, 80 | items: value 81 | } 82 | }).value(); 83 | 84 | return grouped; 85 | } 86 | } -------------------------------------------------------------------------------- /app/pipes/pipes.ref.ts: -------------------------------------------------------------------------------- 1 | export { DisplayDate } from "./dates/dates"; 2 | export { OrderByPipe, GroupByPipe } from "./orderBy/orderBy"; 3 | export { FormScoreFormatter, ScoreFormatter } from "./score/score"; 4 | export { TitleTransform } from "./title/title"; -------------------------------------------------------------------------------- /app/pipes/score/score.ts: -------------------------------------------------------------------------------- 1 | import { PipeTransform, Pipe } from "@angular/core"; 2 | 3 | @Pipe({name: 'FormScore', pure: true}) 4 | export class FormScoreFormatter implements PipeTransform { 5 | transform(value: any, args: any[] = []) { 6 | return parseFloat(value).toFixed(2); 7 | } 8 | } 9 | 10 | @Pipe({name: 'TotalScore', pure: true}) 11 | export class ScoreFormatter implements PipeTransform { 12 | 13 | transform(value: any, args: any[] = []) { 14 | return parseFloat(value).toFixed(3); 15 | } 16 | } -------------------------------------------------------------------------------- /app/pipes/startGroup/startGroup.ts: -------------------------------------------------------------------------------- 1 | import { PipeTransform, Pipe } from "@angular/core"; 2 | import { Logger } from "../../providers/logger" 3 | 4 | @Pipe({name: 'StartGroup', pure: true}) 5 | export class TitleTransform implements PipeTransform { 6 | constructor(private logger: Logger) 7 | { 8 | } 9 | 10 | transform(value: any, args: any[] = []) { 11 | 12 | let k : string = value; 13 | k = k.toUpperCase(); 14 | 15 | return k; 16 | } 17 | } -------------------------------------------------------------------------------- /app/pipes/title/title.ts: -------------------------------------------------------------------------------- 1 | import { PipeTransform, Pipe } from "@angular/core"; 2 | import { Logger } from "../../providers/logger"; 3 | 4 | @Pipe({name: 'Title', pure: true}) 5 | export class TitleTransform implements PipeTransform { 6 | constructor(private logger: Logger) 7 | { 8 | } 9 | 10 | transform(value: string, args: any[] = []) { 11 | let k = value.toUpperCase(); 12 | 13 | return k; 14 | } 15 | } -------------------------------------------------------------------------------- /app/providers/leagues/clubCache.ts: -------------------------------------------------------------------------------- 1 | import * as Rx from "rxjs/Rx"; 2 | import * as appSettings from "application-settings"; 3 | 4 | import { 5 | IClub, 6 | ICompetition, 7 | IGrade, 8 | IRegion, 9 | } 10 | from "../../models/models"; 11 | import { Inject, Injectable } from "@angular/core"; 12 | 13 | import { AppRoutingService } from "../../context/router.context"; 14 | 15 | @Injectable() 16 | export class ClubCache { 17 | public ClubChanges = new Rx.Subject(); 18 | 19 | private club: IClub; 20 | 21 | public get Club(): IClub { 22 | return this.club; 23 | } 24 | public set Club(value: IClub) { 25 | this.club = value; 26 | this.ClubChanges.next(this.club); 27 | } 28 | } -------------------------------------------------------------------------------- /app/providers/leagues/clubService.ts: -------------------------------------------------------------------------------- 1 | import {Http, Response} from "@angular/http"; 2 | import {IClub, ICompetition, ICompetitor} from "../../models/models"; 3 | 4 | import {AppRoutingService} from "../../context/router.context"; 5 | import {ClubCache} from "./clubCache"; 6 | import {CompetitionCache} from "./competitionCache"; 7 | import {Injectable} from "@angular/core"; 8 | import {Logger} from "../logger"; 9 | import { Observable } from "rxjs/Rx"; 10 | import {Settings} from "../routes/routes"; 11 | 12 | @Injectable() 13 | export class ClubService { 14 | 15 | constructor( 16 | private http: Http, 17 | private logger: Logger, 18 | private routingService: AppRoutingService, 19 | private competitionCache: CompetitionCache, 20 | private clubCache : ClubCache) { 21 | logger.Notify("ProviderService created"); 22 | } 23 | 24 | public Get(competitionId: number, clubId: number): Observable { 25 | let base: string = Settings.WebApiBaseUrl; 26 | let route: string = base + `${base}/Api/Competitions/${competitionId}/Clubs/${clubId}`; 27 | let promise: Observable = this.http.get(route); 28 | let result: Observable = promise.map(response => response.json()); 29 | 30 | //this.logger.NotifyResponse(promise); 31 | 32 | result.subscribe((club) => { 33 | this.clubCache.Club = club; 34 | }); 35 | 36 | return result; 37 | } 38 | 39 | public List(competitionId: number): Observable { 40 | this.logger.Notify(`load clubs from ${competitionId}`); 41 | let base: string = Settings.WebApiBaseUrl; 42 | let route: string = `${base}/Api/Competition/${competitionId}/Clubs`; 43 | let request: Observable = this.http.get(route); 44 | let result: Observable = request.map(response => response.json()); 45 | 46 | this.logger.NotifyResponse(request); 47 | 48 | result.subscribe((clubs : Array) => { 49 | this.competitionCache.Clubs = clubs; 50 | }); 51 | 52 | return result; 53 | } 54 | 55 | public ListCompetitors(competitionId: number, clubId: number): Observable { 56 | 57 | let base: string = Settings.WebApiBaseUrl; 58 | let route: string = `${base}/Api/Competition/${competitionId}/Competitors/Club2/${clubId}`; 59 | let request: Observable = this.http.get(route); 60 | let result: Observable = request.map(response => response.json()); 61 | 62 | this.logger.NotifyResponse(request); 63 | 64 | return result; 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /app/providers/leagues/competitionCache.ts: -------------------------------------------------------------------------------- 1 | import * as Rx from "rxjs/Rx"; 2 | import * as appSettings from "application-settings"; 3 | 4 | import { 5 | IClub, 6 | ICompetition, 7 | IGrade, 8 | IRegion, 9 | } 10 | from "../../models/models"; 11 | import { Inject, Injectable } from "@angular/core"; 12 | 13 | import {ClubCache} from "./clubCache"; 14 | import {GradeCache} from "./gradeCache"; 15 | 16 | @Injectable() 17 | export class CompetitionCache { 18 | 19 | public CompetitionChanges = new Rx.BehaviorSubject(null); 20 | 21 | constructor( 22 | public clubCache: ClubCache, 23 | public gradeCache: GradeCache) { 24 | } 25 | 26 | private competition: ICompetition; 27 | public get Competition(): ICompetition { 28 | return this.competition; 29 | } 30 | public set Competition(value: ICompetition) { 31 | if (this.competition && value) { 32 | // if different then invalidate current values and collections. 33 | if (this.competition.Id !== value.Id) { 34 | 35 | this.Grades = null; 36 | this.Clubs = null; 37 | 38 | this.clubCache.Club = null; 39 | this.gradeCache.Grade = null; 40 | } 41 | } 42 | 43 | this.competition = value; 44 | this.CompetitionChanges.next(this.competition); 45 | } 46 | 47 | private grades: IGrade[]; 48 | public get Grades(): Array { 49 | return this.grades; 50 | } 51 | public set Grades(value: Array ) { 52 | this.grades = value; 53 | } 54 | 55 | public HasGrades(): boolean { 56 | return this.grades && this.grades.length > 0; 57 | } 58 | 59 | private clubs: IClub[]; 60 | public get Clubs(): Array { 61 | return this.clubs; 62 | } 63 | public set Clubs(value: Array) { 64 | this.clubs = value; 65 | } 66 | 67 | public HasClubs(): boolean { 68 | return this.clubs && this.clubs.length > 0; 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /app/providers/leagues/competitionService.ts: -------------------------------------------------------------------------------- 1 | import {BehaviorSubject, Observable, Subscription} from "rxjs/Rx"; 2 | import {Http, Response} from "@angular/http"; 3 | import {ICompetition, IRegion} from "../../models/models"; 4 | 5 | import {CompetitionCache} from "./competitionCache"; 6 | import {Injectable} from "@angular/core"; 7 | import {Logger} from "../logger"; 8 | import {Settings} from "../routes/routes"; 9 | 10 | @Injectable() 11 | export class CompetitionService { 12 | 13 | constructor(private http: Http, private logger: Logger, private competitionCache: CompetitionCache) { 14 | logger.Notify("ProviderService created"); 15 | } 16 | 17 | public Get(competitionId: number): Observable { 18 | let base: string = Settings.WebApiBaseUrl; 19 | let route: string = `${base}/Api/Competition/${competitionId}`; 20 | 21 | let rquest: Observable = this.http.get(route); 22 | let result: Observable = rquest.map(response => response.json()); 23 | 24 | result.subscribe((competition : ICompetition) => { 25 | this.competitionCache.Competition = competition; 26 | }); 27 | 28 | this.logger.NotifyResponse(rquest); 29 | 30 | return result; 31 | } 32 | 33 | public List(regionId: number): Observable { 34 | let base: string = Settings.WebApiBaseUrl; 35 | let route: string = `${base}/Api/Providers/${regionId}/Competitions/Enabled`; 36 | 37 | let promise: Observable = this.http.get(route); 38 | let result: Observable = promise.map(response => response.json()); 39 | 40 | return result; 41 | } 42 | } -------------------------------------------------------------------------------- /app/providers/leagues/competitorService.ts: -------------------------------------------------------------------------------- 1 | import {Http, Response} from "@angular/http"; 2 | 3 | import {ICompetitor} from "../../models/models"; 4 | import {Injectable} from "@angular/core"; 5 | import {Logger} from "../logger"; 6 | import { Observable } from "rxjs/Rx"; 7 | import {Settings} from "../routes/routes"; 8 | 9 | @Injectable() 10 | export class CompetitorService { 11 | constructor(private http : Http, private logger: Logger) { 12 | 13 | } 14 | 15 | public ListGradeCompetitors(competitionId: number, gradeId: number): Observable { 16 | let base: string = Settings.WebApiBaseUrl; 17 | let route: string = `${base}/Api/Competition/${competitionId}/Competitors/Grade2/${gradeId}`; 18 | 19 | let observable: Observable = this.http.get(route); 20 | let result: Observable = observable.map(e=> e.json()); 21 | 22 | return result; 23 | } 24 | 25 | public ListClubCompetitors(competitionId: number, clubId: number): Observable { 26 | let base: string = Settings.WebApiBaseUrl; 27 | let route: string = `${base}/Api/Competition/${competitionId}/Competitors/Club/${clubId}`; 28 | 29 | let observable: Observable = this.http.get(route); 30 | let result: Observable = observable.map(e=> e.json()); 31 | // this.logger.NotifyResponse(observable); 32 | 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /app/providers/leagues/displayService.ts: -------------------------------------------------------------------------------- 1 | import {AppRoutingService, IClubRoute, ICompetitionRoute, IGradeRoute, IRegionRoute} from "../../context/router.context"; 2 | import {Component, Injectable, OnInit} from "@angular/core"; 3 | import {IClub, ICompetitionGrades, IGrade} from "../../models/models"; 4 | import {Observable, Subject, Subscription} from "rxjs/Rx"; 5 | 6 | import {ClubService} from "./clubService"; 7 | import {CompetitionCache} from "./competitionCache"; 8 | import {CompetitionService} from "./competitionService"; 9 | import {GradeService} from "./gradeService"; 10 | import {GroupedObservable} from "rxjs/operator/groupBy"; 11 | import {Logger} from "../../providers/logger"; 12 | 13 | @Injectable() 14 | export class DisplayService { 15 | 16 | constructor( 17 | private logger: Logger, 18 | private context: AppRoutingService, 19 | private competitionCache: CompetitionCache, 20 | private gradeService : GradeService, 21 | private clubService : ClubService) { 22 | } 23 | 24 | // public GetOrderedClubs(context: IClubRoute, refresh: boolean): Observable { 25 | // let clubResults : Observable; 26 | // let useCache: boolean = this.competitionCache.HasClubs(); 27 | 28 | // clubResults = useCache 29 | // ? Observable.of(this.competitionCache.Clubs) 30 | // : this.clubService.List(this.context.ClubId); 31 | 32 | // return clubResults; 33 | // } 34 | 35 | // public GetOrderedGrades(context: IGradeRoute, refresh: boolean): Observable { 36 | 37 | // let gradeResults : Observable; 38 | // let useCache: boolean = this.competitionCache.HasGrades(); 39 | 40 | // gradeResults = useCache 41 | // ? Observable.of(this.competitionCache.Grades) 42 | // : this.gradeService.List(this.context.CompetitionId); 43 | 44 | // let grouped = gradeResults.groupBy(e=> e.Discipline, e=> e).map(group=> { 45 | // let grades : IGrade[] = []; 46 | 47 | // group.subscribe(k => { 48 | // grades.push(k); 49 | // }, (error) => { 50 | 51 | // }, () => { 52 | // let orderedGrades = grades.sort((a,b) => 53 | // a.ClassName.toLowerCase() < b.ClassName.toLowerCase() ? -1 : a.ClassName > b.ClassName ? 1 : 0 54 | // ); 55 | // grades = orderedGrades; 56 | // }); 57 | 58 | // return { 59 | // Discipline : group.key, 60 | // Grades : grades 61 | // }; 62 | // }); 63 | 64 | // return grouped.toArray(); 65 | // } 66 | 67 | 68 | } -------------------------------------------------------------------------------- /app/providers/leagues/gradeCache.ts: -------------------------------------------------------------------------------- 1 | import * as Rx from "rxjs/Rx"; 2 | import * as appSettings from "application-settings"; 3 | 4 | import { 5 | IClub, 6 | ICompetition, 7 | IGrade, 8 | IRegion, 9 | } 10 | from "../../models/models"; 11 | import { Inject, Injectable } from "@angular/core"; 12 | 13 | @Injectable() 14 | export class GradeCache { 15 | public GradeChanges = new Rx.Subject(); 16 | 17 | private _grade: IGrade; 18 | public get Grade(): IGrade { 19 | return this._grade; 20 | } 21 | public set Grade(value: IGrade) { 22 | this._grade = value; 23 | this.GradeChanges.next(this._grade); 24 | } 25 | } -------------------------------------------------------------------------------- /app/providers/leagues/gradeService.ts: -------------------------------------------------------------------------------- 1 | import {Http, Response} from "@angular/http"; 2 | import {ICompetition, IGrade} from "../../models/models"; 3 | 4 | import {CompetitionCache} from "./competitionCache"; 5 | import {GradeCache} from "./gradeCache"; 6 | import {Injectable} from "@angular/core"; 7 | import {Logger} from "../logger"; 8 | import { Observable } from "rxjs/Rx"; 9 | import {Settings} from "../routes/routes"; 10 | 11 | @Injectable() 12 | export class GradeService { 13 | constructor(private http: Http, private logger: Logger, 14 | private competitionCache : CompetitionCache, 15 | private gradeCache: GradeCache) { 16 | logger.Notify("ProviderService created"); 17 | } 18 | 19 | public Get(competitionId: number, gradeId: number): Observable { 20 | let base: string = Settings.WebApiBaseUrl; 21 | let route: string = `${base}/Api/Competitions/${competitionId}/Group/${gradeId}`; 22 | 23 | let request: Observable = this.http.get(route); 24 | let result: Observable = request.map(response => response.json()); 25 | 26 | result.subscribe((grade : IGrade) => { 27 | this.gradeCache.Grade = grade; 28 | }); 29 | this.logger.NotifyResponse(request); 30 | 31 | return result; 32 | } 33 | 34 | public List(competitionId: number): Observable { 35 | let base: string = Settings.WebApiBaseUrl; 36 | let route: string = `${base}/Api/Competition/${competitionId}/Grades`; 37 | 38 | this.logger.Notify(`load grades from ${competitionId} | '${route}'`); 39 | 40 | let request: Observable = this.http.get(route); 41 | let result: Observable = request.map(response => response.json()); 42 | 43 | result.subscribe((grades : IGrade[]) => { 44 | this.logger.Notify(`grades loaded: ${grades.length}`); 45 | this.competitionCache.Grades = grades; 46 | }); 47 | 48 | // this.logger.NotifyResponse(request); 49 | 50 | return result; 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /app/providers/leagues/regionCache.ts: -------------------------------------------------------------------------------- 1 | import * as Rx from "rxjs/Rx"; 2 | import * as appSettings from "application-settings"; 3 | 4 | import { 5 | IClub, 6 | ICompetition, 7 | IGrade, 8 | IRegion, 9 | } 10 | from "../../models/models"; 11 | import { Inject, Injectable } from "@angular/core"; 12 | 13 | @Injectable() 14 | export class RegionCache { 15 | public RegionsChange : Rx.Subject = new Rx.BehaviorSubject(null); 16 | public RegionChange : Rx.Subject = new Rx.BehaviorSubject(null); 17 | 18 | // region 19 | private _region : IRegion; 20 | 21 | public get Region(): IRegion { 22 | return this._region; 23 | } 24 | public set Region(value: IRegion) { 25 | this._region = value; 26 | this.RegionChange.next(value); 27 | } 28 | 29 | // regions 30 | private _regions : IRegion[]; 31 | 32 | public get Regions(): IRegion[] { 33 | return this._regions; 34 | } 35 | public set Regions(value : IRegion[]){ 36 | this._regions = value; 37 | this.RegionsChange.next(this._regions); 38 | } 39 | } 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/providers/leagues/regionService.ts: -------------------------------------------------------------------------------- 1 | import {BehaviorSubject, Observable, Subscription} from "rxjs/Rx"; 2 | import {Http, Response} from "@angular/http"; 3 | 4 | import {AppRoutingService} from "../../context/router.context"; 5 | import {IRegion} from "../../models/models"; 6 | import {Injectable} from "@angular/core"; 7 | import {Logger} from "../logger"; 8 | import {RegionCache} from "./regionCache"; 9 | import {Settings} from "../routes/routes"; 10 | 11 | @Injectable() 12 | export class RegionService { 13 | constructor( 14 | private http: Http, 15 | private logger: Logger, 16 | private routingService: AppRoutingService, 17 | private cache: RegionCache) { 18 | } 19 | 20 | public Get(regionId: any): Observable { 21 | let base: string = Settings.WebApiBaseUrl; 22 | let route: string = `${base}/api/Providers/Get/${regionId}`; 23 | 24 | let request: Observable = this.http.get(route); 25 | let result: Observable = request.map(response => response.json()); 26 | 27 | result.subscribe((region : IRegion) => { 28 | this.cache.Region = region; 29 | }); 30 | 31 | return result; 32 | } 33 | 34 | public List(): Observable { 35 | let base: string = Settings.WebApiBaseUrl; 36 | let route: string = `${base}/Api/Providers/List/Enabled`; 37 | 38 | let request: Observable = this.http.get(route); 39 | let result: Observable = request.map(response => response.json()); 40 | 41 | result.subscribe((regions: IRegion[]) => { 42 | this.cache.Regions = regions; 43 | }); 44 | 45 | return result; 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /app/providers/logger.ts: -------------------------------------------------------------------------------- 1 | import {Observable, Subject, Subscription} from "rxjs/Rx"; 2 | 3 | import { Injectable } from "@angular/core"; 4 | import {Response} from "@angular/http"; 5 | 6 | interface ILogMessage { 7 | level: string; 8 | message: string; 9 | } 10 | 11 | const debugLevel: string = "Notify"; 12 | const errorLevel: string = "Error"; 13 | 14 | @Injectable() 15 | export class Logger { 16 | private distinctLog: Subject = new Subject(); 17 | 18 | constructor() { 19 | let varients = this.distinctLog; 20 | 21 | let notifyStream = varients 22 | .filter((x) => x.level === debugLevel) 23 | .distinctUntilChanged((x, y) => x === y) 24 | .map(e=> e.message) 25 | .subscribe((msg) => { 26 | var d : Date = new Date(); 27 | var ds : string = d.toISOString(); 28 | console.log("=Debug==============="); 29 | console.log(ds + ": " + msg); 30 | console.log("======================"); 31 | }); 32 | 33 | let errorStream = varients 34 | .filter(x=> x.level === errorLevel) 35 | .distinctUntilChanged((x, y) => x === y) 36 | .map(e=> e.message) 37 | .subscribe((msg) => { 38 | console.log("*ERROR*****************"); 39 | console.log(msg); 40 | console.log("**********************"); 41 | }); 42 | } 43 | 44 | public Notify(message: string): void { 45 | this.distinctLog.next({ 46 | level: debugLevel, 47 | message: message 48 | }); 49 | } 50 | 51 | public NotifyObject(object: any): void { 52 | let s: string = JSON.stringify(object); 53 | this.distinctLog.next({ 54 | level: debugLevel, 55 | message: s 56 | }); 57 | } 58 | 59 | public NotifyArray(items: any[]): void { 60 | for(let i : number = 0; i>): void { 66 | items.subscribe(x=> this.NotifyArray(x)); 67 | } 68 | 69 | public Error(message: string): void { 70 | this.distinctLog.next({ 71 | level: errorLevel, 72 | message: message 73 | }); 74 | } 75 | 76 | public NotifyObjectProperties(object: any): void { 77 | for (let item in object) { 78 | if (object.hasOwnProperty(item)) { 79 | console.log("Property: " + item); 80 | } 81 | } 82 | } 83 | 84 | public NotifyResponse(requestObservable: Observable): void { 85 | var subscription = requestObservable.subscribe(response => { 86 | let text = response.text(); 87 | let json = response.json(); 88 | 89 | 90 | let jsonAsText = JSON.stringify(json); 91 | this.Notify(jsonAsText); 92 | }); 93 | } 94 | 95 | private ObjextAsString(any : any): string { 96 | return JSON.stringify(any); 97 | } 98 | } -------------------------------------------------------------------------------- /app/providers/navHelper.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/providers/navHelper.ts -------------------------------------------------------------------------------- /app/providers/providers.ref.ts: -------------------------------------------------------------------------------- 1 | export { AppRoutingService } from "../context/router.context"; 2 | export { GradeCache } from "./leagues/gradeCache"; 3 | export { ClubService } from "./leagues/clubService"; 4 | export { CompetitionCache } from "./leagues/competitionCache"; 5 | export { CompetitionService } from "./leagues/competitionService"; 6 | export { RegionCache } from "./leagues/regionCache"; 7 | export { ClubCache } from "./leagues/clubCache"; 8 | export { DisplayService } from "./leagues/displayService"; 9 | export { GradeService } from "./leagues/gradeService"; 10 | export { RegionService } from "./leagues/regionService"; 11 | export { CompetitorService } from "./leagues/competitorService"; 12 | export { Logger } from "./logger"; 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/providers/routes/routes.ts: -------------------------------------------------------------------------------- 1 | 2 | export class Settings { 3 | public static HubUrl = "https://breakouttrampoliningwebservices.azurewebsites.net"; 4 | public static WebApiBaseUrl ="https://breakouttrampoliningwebservices.azurewebsites.net"; 5 | } -------------------------------------------------------------------------------- /app/references.d.ts: -------------------------------------------------------------------------------- 1 | /// Enable smart suggestions and completions in Visual Studio Code JavaScript projects. 2 | -------------------------------------------------------------------------------- /app/theme/_app-common.scss: -------------------------------------------------------------------------------- 1 | // Import the theme’s variables. If you’re using a color scheme 2 | // other than “light”, switch the path to the alternative scheme, 3 | // for example 'nativescript-theme-core/scss/dark'. 4 | //@import 'nativescript-theme-core/scss/light'; 5 | 6 | // Customize any of the theme’s variables here, for instance $btn-color: red; 7 | 8 | // Import the theme’s main ruleset. 9 | //@import 'nativescript-theme-core/scss/index'; -------------------------------------------------------------------------------- /app/theme/_app-variables.scss: -------------------------------------------------------------------------------- 1 | $primary-color: green; 2 | $primary-background-color : #FFFFFF; 3 | 4 | /* content padding */ 5 | $primary-content-padding : 14; 6 | 7 | 8 | /* font colors */ 9 | $font-primary-color : #000; 10 | $font-primary-color1 : lighten( $font-primary-color , 10% ); 11 | $font-primary-color2 : lighten( $font-primary-color , 15% ); 12 | $font-primary-color3 : lighten( $font-primary-color , 20% ); 13 | 14 | $font-primary-title-color: #FFFFFF; 15 | $font-primary-title-color1 : darken( $font-primary-title-color, 10% ); 16 | $font-primary-title-color2 : darken( $font-primary-title-color, 15% ); 17 | $font-primary-title-color3 : darken( $font-primary-title-color, 20% ); 18 | 19 | $background-color-primary : #01579b; 20 | $background-color-primary-lighter : #4f83cc; 21 | $background-color-primary-darker :#002f6c; 22 | 23 | $background-color-secondary : #2196f3; 24 | $background-color-secondary-lighter : #42a5f5; 25 | $background-color-secondary-darker : #1e88e5; 26 | -------------------------------------------------------------------------------- /app/theme/_components.scss: -------------------------------------------------------------------------------- 1 | 2 | @import './components/icons.scss'; 3 | @import './components/nav.scss'; 4 | @import './components/list.scss'; -------------------------------------------------------------------------------- /app/theme/app.android.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/theme/app.android.css -------------------------------------------------------------------------------- /app/theme/app.android.scss: -------------------------------------------------------------------------------- 1 | //@import 'app-common'; 2 | //@import 'nativescript-theme-core/scss/platforms/index.android'; -------------------------------------------------------------------------------- /app/theme/app.ios.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/theme/app.ios.css -------------------------------------------------------------------------------- /app/theme/app.ios.scss: -------------------------------------------------------------------------------- 1 | //@import 'app-common'; 2 | //@import 'nativescript-theme-core/scss/platforms/index.ios'; -------------------------------------------------------------------------------- /app/theme/button.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/theme/button.css -------------------------------------------------------------------------------- /app/theme/button.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/theme/button.scss -------------------------------------------------------------------------------- /app/theme/colors.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/theme/colors.css -------------------------------------------------------------------------------- /app/theme/components/icons.css: -------------------------------------------------------------------------------- 1 | .icon-layer-back{background-color:#fff;border-style:solid;border-width:1;border-color:#e6e6e6;border-radius:15;height:29;width:29}.icon-layer-front{background-color:#fafafa;border-style:solid;border-width:1;border-color:#ccc;border-radius:15;text-align:center;horizontal-align:center;vertical-align:center;height:28;width:28;padding-top:2}.icon-wrapper{text-align:center;horizontal-align:center;vertical-align:center;height:28;width:28;padding-top:2}.icon-wrapper .icon-text{color:#b3b3b3;font-size:18} 2 | -------------------------------------------------------------------------------- /app/theme/components/icons.scss: -------------------------------------------------------------------------------- 1 | @import "../_app-variables.scss"; 2 | 3 | $icon-background-color: #fff; 4 | $icon-background-color1 : darken($icon-background-color, 2% ); 5 | $icon-border-color: darken($icon-background-color, 10% ); 6 | $icon-border-color2: darken($icon-background-color, 20% ); 7 | 8 | $icon-font-color: darken($icon-background-color, 30% ); 9 | 10 | .icon-layer-back { 11 | background-color:$icon-background-color; 12 | border-style: solid; 13 | border-width: 1; 14 | border-color: $icon-border-color; 15 | border-radius: 15; 16 | height: 29; 17 | width: 29; 18 | } 19 | .icon-layer-front { 20 | background-color:$icon-background-color1; 21 | border-style: solid; 22 | border-width: 1; 23 | border-color: $icon-border-color2; 24 | border-radius: 15; 25 | text-align: center; 26 | horizontal-align: center; 27 | vertical-align: center; 28 | height: 28; 29 | width: 28; 30 | padding-top: 2; 31 | } 32 | 33 | .icon-wrapper { 34 | text-align: center; 35 | horizontal-align: center; 36 | vertical-align: center; 37 | height: 28; 38 | width: 28; 39 | padding-top: 2; 40 | 41 | .icon-text { 42 | color: $icon-font-color; 43 | font-size: 18; 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /app/theme/components/list.css: -------------------------------------------------------------------------------- 1 | .nx-header{padding:14;border-radius:4;background-color:#01579b;color:#fff}.nx-header .title{font-weight:bold}.nx-header-ext{background-color:#01579b;border-color:#01579b}.nx-list{margin-bottom:14;border-width:1;border-radius:4;border-color:#eee;background-color:#fff}.nx-item{border-bottom-width:1;border-color:#c8c7cc;border-style:solid}.nx-item-top-border{height:1;border-radius:0;border-width:1;border-color:#c8c7cc}.nx-item-column{vertical-align:center}.inset{padding:14}.inset-sides{padding-left:14;padding-right:14}.inset-top{padding-top:14}.inset-bottom{padding-bottom:14} 2 | -------------------------------------------------------------------------------- /app/theme/components/list.scss: -------------------------------------------------------------------------------- 1 | @import "../_app-variables.scss"; 2 | 3 | $header-primary-backgound-color: $background-color-primary; 4 | 5 | $list-backgorund-color: #FFF; 6 | $list-item-border-color: #c8c7cc; 7 | $list-margin: $primary-content-padding; 8 | $list-header-text-color:$font-primary-title-color; 9 | 10 | .nx-header { 11 | padding: $list-margin; 12 | border-radius: 4; 13 | background-color: $header-primary-backgound-color; 14 | color: $list-header-text-color; 15 | 16 | .title { 17 | font-weight: bold; 18 | } 19 | } 20 | .nx-header-ext { 21 | background-color:$header-primary-backgound-color; 22 | border-color:$header-primary-backgound-color; 23 | } 24 | 25 | .nx-list { 26 | margin-bottom: $list-margin; 27 | border-width: 1; 28 | border-radius: 4; 29 | border-color: #eee; 30 | background-color: $list-backgorund-color; 31 | } 32 | 33 | .nx-item { 34 | border-bottom-width: 1; 35 | border-color: $list-item-border-color; 36 | border-style: solid; 37 | } 38 | 39 | .nx-item-top-border { 40 | height: 1; 41 | border-radius: 0; 42 | border-width: 1; 43 | border-color: $list-item-border-color; 44 | } 45 | 46 | .nx-item-column { 47 | vertical-align: center; 48 | } 49 | 50 | .inset { 51 | padding: $list-margin; 52 | } 53 | 54 | .inset-sides 55 | { 56 | padding-left: $list-margin; 57 | padding-right:$list-margin; 58 | } 59 | 60 | .inset-top { 61 | padding-top: $list-margin; 62 | } 63 | 64 | .inset-bottom { 65 | padding-bottom: $list-margin; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /app/theme/components/nav.css: -------------------------------------------------------------------------------- 1 | .nx-nav-row{height:40;padding:0}.nx-nav-row .title{color:#fff;font-weight:bold;text-align:center}.nx-nav-row .nx-nav-col{padding-left:14;vertical-align:center}.nx-nav-row .nx-nav-col2{text-align:center;horizontal-align:center}.nx-nav-row .nx-nav-col2 label{vertical-align:center}.nx-nav-row .nx-nav-col3{padding-right:14}.nx-nav-wrapper{border-bottom-color:#015da5;border-bottom-width:1;border-bottom-style:solid}.row1{border-bottom-color:#015aa0;border-bottom-width:1;border-bottom-style:solid}.row1 .nx-nav-row{background-color:#01579b}.row2{border-bottom-color:#015da5;border-bottom-width:1;border-bottom-style:solid}.row2 .nx-nav-row{background-color:#0165b4}.nx-nav .icon-layer-front{background-color:#0168b9;border-color:#0162af}.nx-nav .icon-layer-back{background-color:#016ec4;border-color:#015da5}.nx-nav .icon-wrapper .icon-text{color:#fff} 2 | -------------------------------------------------------------------------------- /app/theme/components/nav.scss: -------------------------------------------------------------------------------- 1 | @import "../_app-variables.scss"; 2 | 3 | $nav-background-color: $background-color-primary; 4 | $nav-background-color1: $nav-background-color; 5 | $nav-background-color2: lighten($nav-background-color, 5% ); 6 | 7 | $nav-margin: $primary-content-padding; 8 | $font-color: $font-primary-title-color; 9 | 10 | $nav-border-color1: lighten($nav-background-color, 1% ); 11 | $nav-border-color2: lighten($nav-background-color, 2% ); 12 | 13 | .nx-nav-row { 14 | height: 40; 15 | padding : 0; 16 | 17 | .title { 18 | color: $font-color; 19 | font-weight: bold; 20 | text-align: center; 21 | } 22 | .nx-nav-col { 23 | padding-left: $nav-margin; 24 | vertical-align: center; 25 | } 26 | .nx-nav-col2 { 27 | text-align: center; 28 | horizontal-align:center; 29 | 30 | label { 31 | vertical-align: center; 32 | } 33 | } 34 | .nx-nav-col3 { 35 | padding-right: $nav-margin; 36 | } 37 | } 38 | 39 | .nx-nav-wrapper { 40 | border-bottom-color: $nav-border-color2; 41 | border-bottom-width: 1; 42 | border-bottom-style: solid; 43 | } 44 | 45 | .row1 { 46 | .nx-nav-row { 47 | background-color: $nav-background-color1; 48 | } 49 | border-bottom-color: $nav-border-color1; 50 | border-bottom-width: 1; 51 | border-bottom-style: solid; 52 | } 53 | .row2 { 54 | .nx-nav-row { 55 | background-color: $nav-background-color2; 56 | } 57 | border-bottom-color: $nav-border-color2; 58 | border-bottom-width: 1; 59 | border-bottom-style: solid; 60 | } 61 | 62 | /* icon overrides */ 63 | $nav-icon-background-1: lighten($nav-background-color, 6%); 64 | $nav-icon-background-2: lighten($nav-background-color, 8%); 65 | $nav-icon-border-color1: darken($nav-icon-background-1, 2%); 66 | $nav-icon-border-color2: darken($nav-icon-background-1, 4%); 67 | $nav-icon-font-color: #fff; 68 | 69 | 70 | .nx-nav { 71 | .icon-layer-front { 72 | background-color: $nav-icon-background-1; 73 | border-color: $nav-icon-border-color1; 74 | } 75 | .icon-layer-back{ 76 | background-color: $nav-icon-background-2; 77 | border-color: $nav-icon-border-color2; 78 | } 79 | 80 | .icon-wrapper { 81 | .icon-text { 82 | color: $nav-icon-font-color; 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /app/theme/fonts.css: -------------------------------------------------------------------------------- 1 | .material-icons{font-family:"Material Icons", "MaterialIcons-Regular";font-style:normal;font-weight:400} 2 | -------------------------------------------------------------------------------- /app/theme/fonts.scss: -------------------------------------------------------------------------------- 1 | .material-icons { 2 | font-family: "Material Icons", "MaterialIcons-Regular"; 3 | font-style: normal; 4 | font-weight: 400; 5 | } -------------------------------------------------------------------------------- /app/theme/padding.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/theme/padding.css -------------------------------------------------------------------------------- /app/vendor-platform.android.ts: -------------------------------------------------------------------------------- 1 | require("application"); 2 | require("ui/frame"); 3 | require("ui/frame/activity"); 4 | -------------------------------------------------------------------------------- /app/vendor-platform.ios.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/app/vendor-platform.ios.ts -------------------------------------------------------------------------------- /app/vendor.ts: -------------------------------------------------------------------------------- 1 | require("./vendor-platform"); 2 | 3 | require("reflect-metadata"); 4 | require("@angular/platform-browser"); 5 | require("@angular/core"); 6 | require("@angular/common"); 7 | require("@angular/forms"); 8 | require("@angular/http"); 9 | require("@angular/router"); 10 | 11 | require("nativescript-angular/platform-static"); 12 | require("nativescript-angular/forms"); 13 | require("nativescript-angular/router"); 14 | -------------------------------------------------------------------------------- /gruntfile.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var fs = require("fs"); 3 | 4 | module.exports = function (grunt) { 5 | grunt.loadNpmTasks('grunt-ts'); 6 | grunt.loadNpmTasks('grunt-contrib-copy'); 7 | grunt.loadNpmTasks('grunt-contrib-clean'); 8 | grunt.loadNpmTasks('grunt-shell'); 9 | 10 | var nsDistPath = process.env.NSDIST || './deps/NativeScript/bin/dist'; 11 | 12 | var androidAvd = grunt.option('avd') || "nexus" 13 | var genyDevice = grunt.option('geny') || "nexus7" 14 | var iOSDevice = grunt.option('device') || "iPhone-6" 15 | var androidPlatfrom = "platforms/android/"; 16 | 17 | var hasAndroidPlatform = false; 18 | try { 19 | hasAndroidPlatform = fs.statSync(androidPlatfrom) && fs.statSync(androidPlatfrom).isDirectory(); 20 | } 21 | catch (e) { 22 | // ... 23 | } 24 | 25 | grunt.initConfig({ 26 | ts: { 27 | build: { 28 | tsconfig: './tsconfig.json', 29 | options: { 30 | fast: "never", 31 | compiler: "node_modules/typescript/bin/tsc" 32 | }, 33 | }, 34 | }, 35 | copy: { 36 | widgets: { 37 | src: "widgets.jar", 38 | dest: path.join(androidPlatfrom, "libs") + "/", 39 | cwd: "deps/android-widgets", 40 | expand: true 41 | }, 42 | localInstallModules: { 43 | src: "<%= nsPackagePath %>", 44 | dest: "deps/tns-core-modules.tgz" 45 | } 46 | }, 47 | clean: { 48 | app: { 49 | cwd: 'app', 50 | expand: true, 51 | src: [ 52 | '**/*.js', 53 | '**/*.map', 54 | ] 55 | }, 56 | nodeModulesGz: { 57 | // HACK: Work around a {N} CLI bug that prevents you from using 58 | // NPM packages containing *.gz files. 59 | // https://github.com/NativeScript/nativescript-cli/issues/393 60 | expand: true, 61 | cwd: './node_modules', 62 | src: [ 63 | '**/*.gz', 64 | ] 65 | }, 66 | }, 67 | shell: { 68 | depNSInit: { 69 | command: [ 70 | 'npm install', 71 | 'grunt --no-runtslint', 72 | ].join('&&'), 73 | options: { 74 | execOptions: { 75 | cwd: 'deps/NativeScript', 76 | } 77 | } 78 | }, 79 | localInstallModules: { 80 | command: "npm install 'deps/tns-core-modules.tgz'" 81 | }, 82 | emulateGeny: { 83 | command: "tns emulate android --geny '" + genyDevice + "'" 84 | }, 85 | emulateAndroid: { 86 | command: "tns emulate android --avd '" + androidAvd + "'" 87 | }, 88 | emulateIOS: { 89 | command: "tns emulate ios --device '" + iOSDevice + "'" 90 | }, 91 | removeAndroid: { 92 | command: "tns platform remove android" 93 | }, 94 | addAndroid: { 95 | command: "tns platform add android" 96 | } 97 | } 98 | }); 99 | 100 | grunt.registerTask("updateModules", [ 101 | "getNSPackage", 102 | "copy:localInstallModules", 103 | "shell:localInstallModules", 104 | ]); 105 | 106 | grunt.registerTask("getNSPackage", function () { 107 | var packageFiles = grunt.file.expand({ 108 | cwd: nsDistPath 109 | }, [ 110 | 'tns-core-modules*.tgz' 111 | ]); 112 | var nsPackagePath = path.join(nsDistPath, packageFiles[0]); 113 | grunt.config('nsPackagePath', nsPackagePath); 114 | }); 115 | 116 | grunt.registerTask("app", [ 117 | "ts:build", 118 | ]); 119 | 120 | // Copy custom version of widgets.jar to be up to date 121 | grunt.registerTask("fix-android-widgets", hasAndroidPlatform ? ["copy:widgets"] : []) 122 | grunt.registerTask("prepare", [ 123 | "shell:depNSInit", 124 | "updateModules", 125 | "clean:nodeModulesGz", 126 | "fix-android-widgets" 127 | ]); 128 | 129 | grunt.registerTask("app-full", [ 130 | "clean:app", 131 | "app", 132 | ]); 133 | 134 | grunt.registerTask("refresh-android", ["shell:removeAndroid", "shell:addAndroid", "fix-android-widgets"]) 135 | grunt.registerTask("run-android", ["app", "shell:emulateAndroid"]) 136 | grunt.registerTask("run-ios", ["app", "shell:emulateIOS"]) 137 | } -------------------------------------------------------------------------------- /hooks/after-prepare/nativescript-dev-sass.js: -------------------------------------------------------------------------------- 1 | module.exports = require("nativescript-dev-sass/lib/after-prepare.js"); 2 | -------------------------------------------------------------------------------- /hooks/before-livesync/nativescript-angular-sync.js: -------------------------------------------------------------------------------- 1 | module.exports = require("nativescript-angular/hooks/before-livesync"); 2 | -------------------------------------------------------------------------------- /hooks/before-prepare/nativescript-dev-sass.js: -------------------------------------------------------------------------------- 1 | module.exports = require("nativescript-dev-sass/lib/before-prepare.js"); 2 | -------------------------------------------------------------------------------- /hooks/before-prepare/nativescript-dev-typescript.js: -------------------------------------------------------------------------------- 1 | module.exports = require("nativescript-dev-typescript/lib/before-prepare.js"); 2 | -------------------------------------------------------------------------------- /hooks/before-watch/nativescript-dev-sass.js: -------------------------------------------------------------------------------- 1 | module.exports = require("nativescript-dev-sass/lib/watch.js"); 2 | -------------------------------------------------------------------------------- /hooks/before-watch/nativescript-dev-typescript.js: -------------------------------------------------------------------------------- 1 | module.exports = require("nativescript-dev-typescript/lib/watch.js"); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "nativescript": { 3 | "id": "whatsmyscore.breakoutdeveloper.com", 4 | "tns-android": { 5 | "version": "3.0.0" 6 | }, 7 | "tns-ios": { 8 | "version": "3.0.0" 9 | } 10 | }, 11 | "scripts": { 12 | "tslint": "tslint \"app/**/*.ts\"", 13 | "ns-bundle": "ns-bundle", 14 | "start-android-bundle": "npm run ns-bundle --android --start-app", 15 | "start-ios-bundle": "npm run ns-bundle --ios --start-app", 16 | "build-android-bundle": "npm run ns-bundle --android --build-app", 17 | "build-ios-bundle": "npm run ns-bundle --ios --build-app" 18 | }, 19 | "dependencies": { 20 | "@angular/common": "~4.1.0", 21 | "@angular/compiler": "~4.1.0", 22 | "@angular/core": "~4.1.0", 23 | "@angular/forms": "~4.1.0", 24 | "@angular/http": "~4.1.0", 25 | "@angular/platform-browser": "~4.1.0", 26 | "@angular/router": "~4.1.0", 27 | "angular2-moment": "^1.3.3", 28 | "ionicons": "~2.0.0", 29 | "lodash": "^4.13.1", 30 | "moment": "~2.18.1", 31 | "nativescript-angular": "~3.0.0", 32 | "nativescript-cardview": "^2.0.0-rc.0", 33 | "nativescript-enumerable": "~3.3.7", 34 | "nativescript-fancyalert": "^1.1.2", 35 | "nativescript-floatingactionbutton": "^3.0.0", 36 | "nativescript-pulltorefresh": "^2.0.0-rc.1", 37 | "nativescript-social-share": "~1.3.2", 38 | "nativescript-telerik-ui": "~2.0.1", 39 | "nativescript-theme-core": "~1.0.2", 40 | "nativescript-videoplayer": "^3.0.5", 41 | "ngx-pipes": "~1.5.10", 42 | "reflect-metadata": "~0.1.8", 43 | "rxjs": "^5.3.1", 44 | "tns-core-modules": "^3.0.0", 45 | "underscore": "~1.8.3", 46 | "zone.js": "^0.8.4" 47 | }, 48 | "devDependencies": { 49 | "@angular/compiler-cli": "~4.1.0", 50 | "@ngtools/webpack": "1.3.1", 51 | "@types/lodash": "~4.14.64", 52 | "@types/moment":"~2.13.0", 53 | "babel-traverse": "6.24.1", 54 | "babel-types": "6.24.1", 55 | "babylon": "6.17.0", 56 | "codelyzer": "^3.0.1", 57 | "copy-webpack-plugin": "~4.0.1", 58 | "extract-text-webpack-plugin": "~2.1.0", 59 | "filewalker": "^0.1.3", 60 | "jasmine-core": "^2.6.1", 61 | "karma": "^1.7.0", 62 | "karma-jasmine": "^1.0.2", 63 | "karma-nativescript-launcher": "^0.4.0", 64 | "lazy": "1.0.11", 65 | "nativescript-css-loader": "~0.26.0", 66 | "nativescript-dev-sass": "^1.1.1", 67 | "nativescript-dev-typescript": "^0.4.2", 68 | "nativescript-dev-webpack": "^0.5.0", 69 | "raw-loader": "~0.5.1", 70 | "resolve-url-loader": "~2.0.2", 71 | "tslint": "^5.2.0", 72 | "typescript": "~2.3.2", 73 | "webpack": "~2.5.1", 74 | "webpack-sources": "~0.2.3" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /package.json.bak: -------------------------------------------------------------------------------- 1 | { 2 | "nativescript": { 3 | "id": "whatsmyscore.breakoutdeveloper.com", 4 | "tns-android": { 5 | "version": "2.1.1" 6 | } 7 | }, 8 | "dependencies": { 9 | "@angular/common": "2.4.3", 10 | "@angular/compiler": "2.4.3", 11 | "@angular/core": "2.4.3", 12 | "@angular/forms": "2.4.3", 13 | "@angular/http": "2.4.3", 14 | "@angular/platform-browser": "2.4.3", 15 | "@angular/platform-browser-dynamic": "2.4.3", 16 | "@angular/router": "3.4.3", 17 | "nativescript-angular": "1.4.0", 18 | "nativescript-theme-core": "~1.0.2", 19 | "reflect-metadata": "~0.1.8", 20 | "rxjs": "~5.0.1", 21 | "tns-core-modules": "2.5.0", 22 | "ionicons": "~2.0.0", 23 | "lodash": "^4.13.1", 24 | "moment": "~2.11.2", 25 | "nativescript-cardview": "1.0.1", 26 | "nativescript-enumerable": "~3.3.7", 27 | "nativescript-floatingactionbutton": "~2.2.4", 28 | "nativescript-pulltorefresh": "~1.1.4", 29 | "nativescript-videoplayer": "~0.2.0", 30 | "underscore": "~1.8.3" 31 | }, 32 | "devDependencies": { 33 | "nativescript-dev-android-snapshot": "^0.*.*", 34 | "nativescript-dev-typescript": "^0.3.5", 35 | "typescript": "~2.1.0", 36 | "zone.js": "~0.7.2" 37 | }, 38 | "scripts": {} 39 | } -------------------------------------------------------------------------------- /references.d.ts: -------------------------------------------------------------------------------- 1 | /// Needed for autocompletion and compilation. 2 | /// -------------------------------------------------------------------------------- /screenshots/CompetitionList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/CompetitionList.png -------------------------------------------------------------------------------- /screenshots/RegionsPage-drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/RegionsPage-drawer.png -------------------------------------------------------------------------------- /screenshots/RegionsPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/RegionsPage.png -------------------------------------------------------------------------------- /screenshots/StartPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/StartPage.png -------------------------------------------------------------------------------- /screenshots/animation/load-page.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/animation/load-page.gif -------------------------------------------------------------------------------- /screenshots/animation/refresh-page.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/animation/refresh-page.gif -------------------------------------------------------------------------------- /screenshots/animation/refresh-pointless-page.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/animation/refresh-pointless-page.gif -------------------------------------------------------------------------------- /screenshots/card+refresh view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/card+refresh view.png -------------------------------------------------------------------------------- /screenshots/competitionPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/competitionPage.png -------------------------------------------------------------------------------- /screenshots/controls/sidebar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/controls/sidebar.gif -------------------------------------------------------------------------------- /screenshots/pages/club-list.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/pages/club-list.gif -------------------------------------------------------------------------------- /screenshots/pages/grade.page.competitor.results(minus ordering).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/pages/grade.page.competitor.results(minus ordering).png -------------------------------------------------------------------------------- /screenshots/pages/regions.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/pages/regions.gif -------------------------------------------------------------------------------- /screenshots/pipes/groupBy+orderBy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/pipes/groupBy+orderBy.gif -------------------------------------------------------------------------------- /screenshots/style-bug/after-nav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/style-bug/after-nav.png -------------------------------------------------------------------------------- /screenshots/style-bug/before-nav_20160314015641.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt4446/WhatsMyScore2-NativeScript/abff36d3e6a0a3a858d7af40d44c195bae5241be/screenshots/style-bug/before-nav_20160314015641.png -------------------------------------------------------------------------------- /tsconfig.aot.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "application": ["node_modules/tns-core-modules/application"], 7 | "application-settings": ["node_modules/tns-core-modules/application-settings"], 8 | "camera": ["node_modules/tns-core-modules/camera"], 9 | "color": ["node_modules/tns-core-modules/color"], 10 | "connectivity": ["node_modules/tns-core-modules/connectivity"], 11 | "console": ["node_modules/tns-core-modules/console"], 12 | "data/*": ["node_modules/tns-core-modules/data/*"], 13 | "fetch": ["node_modules/tns-core-modules/fetch"], 14 | "file-system": ["node_modules/tns-core-modules/file-system"], 15 | "fps-meter": ["node_modules/tns-core-modules/fps-meter"], 16 | "globals": ["node_modules/tns-core-modules/globals"], 17 | "http": ["node_modules/tns-core-modules/http"], 18 | "image-asset": ["node_modules/tns-core-modules/image-asset"], 19 | "image-source": ["node_modules/tns-core-modules/image-source"], 20 | "location": ["node_modules/tns-core-modules/location"], 21 | "platform": ["node_modules/tns-core-modules/platform"], 22 | "text": ["node_modules/tns-core-modules/text"], 23 | "timer": ["node_modules/tns-core-modules/timer"], 24 | "trace": ["node_modules/tns-core-modules/trace"], 25 | "ui/*": ["node_modules/tns-core-modules/ui/*"], 26 | "utils/*": ["node_modules/tns-core-modules/utils/*"], 27 | "xhr": ["node_modules/tns-core-modules/xhr"], 28 | "xml": ["node_modules/tns-core-modules/xml"] 29 | }, 30 | "skipLibCheck": true 31 | }, 32 | "exclude": [ 33 | "node_modules", 34 | "platforms" 35 | ], 36 | "angularCompilerOptions": { 37 | "skipMetadataEmit": true, 38 | "genDir": "./" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "experimentalDecorators": true, 6 | "emitDecoratorMetadata": true, 7 | "noEmitHelpers": true, 8 | "noEmitOnError": true, 9 | "lib": [ 10 | "dom", 11 | "es6", 12 | "es2015.iterable" 13 | ], 14 | "baseUrl": ".", 15 | "paths": { 16 | "*": [ 17 | "./node_modules/tns-core-modules/*", 18 | "./node_modules/*" 19 | ] 20 | } 21 | }, 22 | "exclude": [ 23 | "node_modules", 24 | "platforms", 25 | "**/*.aot.ts" 26 | ] 27 | } -------------------------------------------------------------------------------- /tsconfig.json.bak: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "app", 4 | "rootDir": "app", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "inlineSourceMap": true, 8 | "experimentalDecorators": true, 9 | "removeComments": false, 10 | "emitDecoratorMetadata": true, 11 | "noEmitOnError": true 12 | }, 13 | "exclude": [ 14 | "typings/browser", 15 | "typings/browser/browser.d.ts", 16 | "node_modules", 17 | "platforms" 18 | ] 19 | } -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ambientDependencies": { 3 | }, 4 | "ambientDevDependencies": {} 5 | } 6 | -------------------------------------------------------------------------------- /typings/dummy.ios.d.ts: -------------------------------------------------------------------------------- 1 | declare type UIRefreshControl = any; -------------------------------------------------------------------------------- /typings/main.d.ts: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const { resolve, join } = require("path"); 2 | 3 | const webpack = require("webpack"); 4 | const nsWebpack = require("nativescript-dev-webpack"); 5 | const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target"); 6 | const CopyWebpackPlugin = require("copy-webpack-plugin"); 7 | const ExtractTextPlugin = require("extract-text-webpack-plugin"); 8 | 9 | const { AotPlugin } = require("@ngtools/webpack"); 10 | 11 | const mainSheet = `app.css`; 12 | 13 | module.exports = env => { 14 | const platform = getPlatform(env); 15 | 16 | // Default destination inside platforms//... 17 | const path = resolve(nsWebpack.getAppPath(platform)); 18 | 19 | const entry = { 20 | // Discover entry module from package.json 21 | bundle: `./${nsWebpack.getEntryModule()}`, 22 | 23 | // Vendor entry with third-party libraries 24 | vendor: `./vendor`, 25 | 26 | // Entry for stylesheet with global application styles 27 | [mainSheet]: `./${mainSheet}`, 28 | }; 29 | 30 | const rules = getRules(); 31 | const plugins = getPlugins(platform, env); 32 | const extensions = getExtensions(platform); 33 | 34 | return { 35 | context: resolve("./app"), 36 | target: nativescriptTarget, 37 | entry, 38 | output: { 39 | pathinfo: true, 40 | path, 41 | libraryTarget: "commonjs2", 42 | filename: "[name].js", 43 | }, 44 | resolve: { 45 | extensions, 46 | 47 | // Resolve {N} system modules from tns-core-modules 48 | modules: [ 49 | "node_modules/tns-core-modules", 50 | "node_modules", 51 | ] 52 | }, 53 | node: { 54 | // Disable node shims that conflict with NativeScript 55 | "http": false, 56 | "timers": false, 57 | "setImmediate": false, 58 | "fs": "empty", 59 | }, 60 | module: { rules }, 61 | plugins, 62 | }; 63 | }; 64 | 65 | 66 | function getPlatform(env) { 67 | return env.android ? "android" : 68 | env.ios ? "ios" : 69 | () => { throw new Error("You need to provide a target platform!") }; 70 | } 71 | 72 | function getRules() { 73 | return [ 74 | { 75 | test: /\.html$|\.xml$/, 76 | use: [ 77 | "raw-loader", 78 | ] 79 | }, 80 | // Root stylesheet gets extracted with bundled dependencies 81 | { 82 | test: new RegExp(mainSheet), 83 | use: ExtractTextPlugin.extract([ 84 | { 85 | loader: "resolve-url-loader", 86 | options: { silent: true }, 87 | }, 88 | "nativescript-css-loader", 89 | "nativescript-dev-webpack/platform-css-loader", 90 | ]), 91 | }, 92 | // Other CSS files get bundled using the raw loader 93 | { 94 | test: /\.css$/, 95 | exclude: new RegExp(mainSheet), 96 | use: [ 97 | "raw-loader", 98 | ] 99 | }, 100 | // SASS support 101 | { 102 | test: /\.scss$/, 103 | use: [ 104 | "raw-loader", 105 | "resolve-url-loader", 106 | "sass-loader", 107 | ] 108 | }, 109 | 110 | 111 | // Compile TypeScript files with ahead-of-time compiler. 112 | { 113 | test: /\.ts$/, 114 | loaders: [ 115 | "nativescript-dev-webpack/tns-aot-loader", 116 | "@ngtools/webpack", 117 | ] 118 | } 119 | 120 | ]; 121 | } 122 | 123 | function getPlugins(platform, env) { 124 | let plugins = [ 125 | new ExtractTextPlugin(mainSheet), 126 | 127 | // Vendor libs go to the vendor.js chunk 128 | new webpack.optimize.CommonsChunkPlugin({ 129 | name: ["vendor"], 130 | }), 131 | 132 | // Define useful constants like TNS_WEBPACK 133 | new webpack.DefinePlugin({ 134 | "global.TNS_WEBPACK": "true", 135 | }), 136 | 137 | // Copy assets to out dir. Add your own globs as needed. 138 | new CopyWebpackPlugin([ 139 | { from: mainSheet }, 140 | { from: "css/**" }, 141 | { from: "fonts/**" }, 142 | { from: "**/*.jpg" }, 143 | { from: "**/*.png" }, 144 | { from: "**/*.xml" }, 145 | ], { ignore: ["App_Resources/**"] }), 146 | 147 | // Generate a bundle starter script and activate it in package.json 148 | new nsWebpack.GenerateBundleStarterPlugin([ 149 | "./vendor", 150 | "./bundle", 151 | ]), 152 | 153 | // Angular AOT compiler 154 | new AotPlugin({ 155 | tsConfigPath: "tsconfig.aot.json", 156 | entryModule: resolve(__dirname, "app/app.module#AppModule"), 157 | typeChecking: false 158 | }), 159 | 160 | // Resolve .ios.css and .android.css component stylesheets 161 | new nsWebpack.StyleUrlResolvePlugin({platform}), 162 | 163 | ]; 164 | 165 | if (env.uglify) { 166 | plugins.push(new webpack.LoaderOptionsPlugin({ minimize: true })); 167 | 168 | // Work around an Android issue by setting compress = false 169 | const compress = platform !== "android"; 170 | plugins.push(new webpack.optimize.UglifyJsPlugin({ 171 | mangle: { except: nsWebpack.uglifyMangleExcludes }, 172 | compress, 173 | })); 174 | } 175 | 176 | return plugins; 177 | } 178 | 179 | // Resolve platform-specific modules like module.android.js 180 | function getExtensions(platform) { 181 | return Object.freeze([ 182 | `.${platform}.ts`, 183 | `.${platform}.js`, 184 | ".aot.ts", 185 | ".ts", 186 | ".js", 187 | ".css", 188 | `.${platform}.css`, 189 | ]); 190 | } --------------------------------------------------------------------------------