├── .gitattributes ├── .gitignore ├── .nvmrc ├── LICENSE ├── README.md ├── cordova ├── config.xml ├── config_livereload.xml └── hooks │ ├── android │ └── after_platform_add_add_plugins.js │ └── ios │ └── after_platform_add_add_plugins.js ├── electron ├── icon.png ├── index.js └── package.json ├── gulp.config.js ├── gulpTasks ├── cordova.js ├── electron.js └── web.js ├── gulpfile.js ├── package.json ├── resources ├── icon.icns ├── icon.ico ├── icon.png ├── icon_256.ico └── splash.png ├── src ├── BoardZ │ ├── app │ │ ├── apiConfig.ts │ │ ├── app.html │ │ ├── app.ts │ │ ├── components │ │ │ ├── dashboard │ │ │ │ ├── dashboard.html │ │ │ │ └── dashboard.ts │ │ │ ├── games │ │ │ │ ├── details.html │ │ │ │ ├── details.ts │ │ │ │ ├── gamesRoot.html │ │ │ │ ├── gamesRoot.ts │ │ │ │ ├── list.html │ │ │ │ └── list.ts │ │ │ ├── header │ │ │ │ ├── header.html │ │ │ │ └── header.ts │ │ │ ├── locateIt │ │ │ │ ├── locateIt.html │ │ │ │ └── locateIt.ts │ │ │ ├── login │ │ │ │ ├── login.html │ │ │ │ └── login.ts │ │ │ ├── notifications │ │ │ │ ├── notifications.html │ │ │ │ └── notifications.ts │ │ │ ├── pictureIt │ │ │ │ ├── pictureIt.html │ │ │ │ └── pictureIt.ts │ │ │ ├── radiusSearch │ │ │ │ ├── radiusSearch.html │ │ │ │ └── radiusSearch.ts │ │ │ ├── sidebar │ │ │ │ ├── sidebar.html │ │ │ │ └── sidebar.ts │ │ │ └── widget │ │ │ │ ├── widget.html │ │ │ │ └── widget.ts │ │ ├── directives │ │ │ ├── backButtonDirective.ts │ │ │ └── closeSidebarOnClickDirective.ts │ │ ├── guards │ │ │ └── authenticationGuard.ts │ │ ├── interfaces │ │ │ └── boardzAppWindow.ts │ │ ├── main.ts │ │ ├── models │ │ │ ├── game.ts │ │ │ ├── geoLocation.ts │ │ │ ├── logLevel.ts │ │ │ ├── navigationEntry.ts │ │ │ ├── nearbyPlayer.ts │ │ │ ├── notification.ts │ │ │ ├── notificationType.ts │ │ │ ├── picture.ts │ │ │ ├── player.ts │ │ │ └── tokenData.ts │ │ ├── modules │ │ │ ├── appModule.ts │ │ │ ├── gamesModule.ts │ │ │ ├── modulesConfig.ts │ │ │ └── sharedModule.ts │ │ ├── resolvers │ │ │ └── gameDetailsResolver.ts │ │ ├── routing │ │ │ └── routingConfig.ts │ │ └── services │ │ │ ├── authenticatedHttp.ts │ │ │ ├── cameraService.ts │ │ │ ├── desktopCameraService.ts │ │ │ ├── gamesService.ts │ │ │ ├── geolocationService.ts │ │ │ ├── logService.ts │ │ │ ├── loginService.ts │ │ │ ├── mobileCameraService.ts │ │ │ ├── nativeIntegrationService.ts │ │ │ ├── notificationService.ts │ │ │ ├── platformInformationService.ts │ │ │ ├── playersService.ts │ │ │ ├── signalrService.ts │ │ │ ├── tokenService.ts │ │ │ └── uiNotificationService.ts │ ├── assets │ │ ├── favicon.ico │ │ └── images │ │ │ ├── layers-2x.png │ │ │ ├── layers.png │ │ │ ├── marker-icon-2x.png │ │ │ ├── marker-icon.png │ │ │ └── marker-shadow.png │ ├── cordova.js │ ├── css │ │ └── app.css │ ├── index.html │ ├── system.setup.js │ └── vendor │ │ ├── admin-lte │ │ ├── css │ │ │ ├── AdminLTE.css │ │ │ └── skins │ │ │ │ └── _all-skins.css │ │ └── js │ │ │ └── app.js │ │ ├── bootstrap │ │ ├── css │ │ │ └── bootstrap.css │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ │ └── bootstrap.js │ │ ├── fastclick │ │ └── fastclick.js │ │ ├── font-awesome │ │ ├── css │ │ │ └── font-awesome.css │ │ └── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── hammerjs │ │ └── hammer.js │ │ ├── jquery │ │ ├── jquery-2.1.4.js │ │ ├── jquery.hammer.js │ │ └── jquery.slimscroll.js │ │ ├── leaflet-js │ │ ├── leaflet-src.js │ │ └── leaflet.css │ │ ├── pNotify │ │ ├── pnotify-adapter.js │ │ ├── pnotify.custom.css │ │ └── pnotify.custom.js │ │ └── signalr │ │ └── signalr.js └── BoardZApi │ ├── BoardGame.Api.sln │ ├── BoardGame.Api │ ├── BoardGame.Api.csproj │ ├── Controllers │ │ ├── BoardGamesController.cs │ │ └── PlayersController.cs │ ├── Helpers │ │ ├── DistanceCalculator.cs │ │ └── IPrincipalExtensions.cs │ ├── Hubs │ │ ├── IPlayer.cs │ │ └── PlayerHub.cs │ ├── Models │ │ ├── BoardGame.cs │ │ ├── Coordinate.cs │ │ ├── Packshot.cs │ │ └── Player.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Security │ │ ├── AuthorizationServerProvider.cs │ │ ├── SecurityStartup.cs │ │ └── SignalRAuthorizationMiddleware.cs │ ├── Startup.cs │ ├── Storages │ │ ├── BoardGameStorage.cs │ │ ├── IStorage.cs │ │ └── PlayersStorage.cs │ ├── SwaggerUi │ │ └── CustomAssets │ │ │ └── lang │ │ │ ├── en.js │ │ │ ├── es.js │ │ │ ├── pt.js │ │ │ ├── ru.js │ │ │ ├── tr.js │ │ │ └── translator.js │ ├── app.config │ └── packages.config │ ├── BoardGame.Host │ ├── App.config │ ├── BoardGame.Host.csproj │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SwaggerUi │ │ └── CustomAssets │ │ │ └── lang │ │ │ ├── en.js │ │ │ ├── es.js │ │ │ ├── pt.js │ │ │ ├── ru.js │ │ │ ├── tr.js │ │ │ └── translator.js │ └── packages.config │ ├── BoardGame.WebHost │ ├── BoardGame.WebHost.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SwaggerUi │ │ └── CustomAssets │ │ │ └── lang │ │ │ ├── en.js │ │ │ ├── es.js │ │ │ ├── pt.js │ │ │ ├── ru.js │ │ │ ├── tr.js │ │ │ └── translator.js │ ├── packages.config │ └── web.config │ └── docs │ └── BoardGame.Api.xml ├── system.config.js ├── tsconfig.json ├── tslint.json └── typings.json /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | 3 | # Mac 4 | .DS_Store 5 | 6 | platforms/ 7 | plugins/ 8 | 9 | cordova/www/ 10 | 11 | # res 12 | resources/signing 13 | node_modules 14 | 15 | # Created by https://www.gitignore.io/api/windows,visualstudio 16 | 17 | ### Windows ### 18 | # Windows image file caches 19 | Thumbs.db 20 | ehthumbs.db 21 | 22 | # Folder config file 23 | Desktop.ini 24 | 25 | # Recycle Bin used on file shares 26 | $RECYCLE.BIN/ 27 | 28 | # Windows Installer files 29 | *.cab 30 | *.msi 31 | *.msm 32 | *.msp 33 | 34 | # Windows shortcuts 35 | *.lnk 36 | 37 | 38 | ### VisualStudio ### 39 | ## Ignore Visual Studio temporary files, build results, and 40 | ## files generated by popular Visual Studio add-ons. 41 | 42 | # User-specific files 43 | *.suo 44 | *.user 45 | *.userosscache 46 | *.sln.docstates 47 | 48 | # User-specific files (MonoDevelop/Xamarin Studio) 49 | *.userprefs 50 | 51 | # Build results 52 | [Dd]ebug/ 53 | [Dd]ebugPublic/ 54 | [Rr]elease/ 55 | [Rr]eleases/ 56 | x64/ 57 | x86/ 58 | build/ 59 | bld/ 60 | [Bb]in/ 61 | [Oo]bj/ 62 | 63 | # Visual Studio 2015 cache/options directory 64 | .vs/ 65 | # Uncomment if you have tasks that create the project's static files in wwwroot 66 | #wwwroot/ 67 | 68 | # MSTest test Results 69 | [Tt]est[Rr]esult*/ 70 | [Bb]uild[Ll]og.* 71 | 72 | # NUNIT 73 | *.VisualState.xml 74 | TestResult.xml 75 | 76 | # Build Results of an ATL Project 77 | [Dd]ebugPS/ 78 | [Rr]eleasePS/ 79 | dlldata.c 80 | 81 | # DNX 82 | project.lock.json 83 | artifacts/ 84 | 85 | *_i.c 86 | *_p.c 87 | *_i.h 88 | *.ilk 89 | *.meta 90 | *.obj 91 | *.pch 92 | *.pdb 93 | *.pgc 94 | *.pgd 95 | *.rsp 96 | *.sbr 97 | *.tlb 98 | *.tli 99 | *.tlh 100 | *.tmp 101 | *.tmp_proj 102 | *.log 103 | *.vspscc 104 | *.vssscc 105 | .builds 106 | *.pidb 107 | *.svclog 108 | *.scc 109 | 110 | # Chutzpah Test files 111 | _Chutzpah* 112 | 113 | # Visual C++ cache files 114 | ipch/ 115 | *.aps 116 | *.ncb 117 | *.opensdf 118 | *.sdf 119 | *.cachefile 120 | 121 | # Visual Studio profiler 122 | *.psess 123 | *.vsp 124 | *.vspx 125 | 126 | # TFS 2012 Local Workspace 127 | $tf/ 128 | 129 | # Guidance Automation Toolkit 130 | *.gpState 131 | 132 | # ReSharper is a .NET coding add-in 133 | _ReSharper*/ 134 | *.[Rr]e[Ss]harper 135 | *.DotSettings.user 136 | 137 | # JustCode is a .NET coding add-in 138 | .JustCode 139 | 140 | # TeamCity is a build add-in 141 | _TeamCity* 142 | 143 | # DotCover is a Code Coverage Tool 144 | *.dotCover 145 | 146 | # NCrunch 147 | _NCrunch_* 148 | .*crunch*.local.xml 149 | nCrunchTemp_* 150 | 151 | # MightyMoose 152 | *.mm.* 153 | AutoTest.Net/ 154 | 155 | # Web workbench (sass) 156 | .sass-cache/ 157 | 158 | # Installshield output folder 159 | [Ee]xpress/ 160 | 161 | # DocProject is a documentation generator add-in 162 | DocProject/buildhelp/ 163 | DocProject/Help/*.HxT 164 | DocProject/Help/*.HxC 165 | DocProject/Help/*.hhc 166 | DocProject/Help/*.hhk 167 | DocProject/Help/*.hhp 168 | DocProject/Help/Html2 169 | DocProject/Help/html 170 | 171 | # Click-Once directory 172 | publish/ 173 | 174 | # Publish Web Output 175 | *.[Pp]ublish.xml 176 | *.azurePubxml 177 | # TODO: Comment the next line if you want to checkin your web deploy settings 178 | # but database connection strings (with potential passwords) will be unencrypted 179 | *.pubxml 180 | *.publishproj 181 | 182 | # NuGet Packages 183 | *.nupkg 184 | # The packages folder can be ignored because of Package Restore 185 | **/packages/* 186 | # except build/, which is used as an MSBuild target. 187 | !**/packages/build/ 188 | # Uncomment if necessary however generally it will be regenerated when needed 189 | #!**/packages/repositories.config 190 | 191 | # Windows Azure Build Output 192 | csx/ 193 | *.build.csdef 194 | 195 | # Windows Store app package directory 196 | AppPackages/ 197 | 198 | # Visual Studio cache files 199 | # files ending in .cache can be ignored 200 | *.[Cc]ache 201 | # but keep track of directories ending in .cache 202 | !*.[Cc]ache/ 203 | 204 | # Others 205 | ClientBin/ 206 | [Ss]tyle[Cc]op.* 207 | ~$* 208 | *~ 209 | *.dbmdl 210 | *.dbproj.schemaview 211 | *.pfx 212 | *.publishsettings 213 | node_modules/ 214 | orleans.codegen.cs 215 | 216 | # RIA/Silverlight projects 217 | Generated_Code/ 218 | 219 | # Backup & report files from converting an old project file 220 | # to a newer Visual Studio version. Backup files are not needed, 221 | # because we have git ;-) 222 | _UpgradeReport_Files/ 223 | Backup*/ 224 | UpgradeLog*.XML 225 | UpgradeLog*.htm 226 | 227 | # SQL Server files 228 | *.mdf 229 | *.ldf 230 | 231 | # Business Intelligence projects 232 | *.rdl.data 233 | *.bim.layout 234 | *.bim_*.settings 235 | 236 | # Microsoft Fakes 237 | FakesAssemblies/ 238 | 239 | # Node.js Tools for Visual Studio 240 | .ntvs_analysis.dat 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio LightSwitch build output 249 | **/*.HTMLClient/GeneratedArtifacts 250 | **/*.DesktopClient/GeneratedArtifacts 251 | **/*.DesktopClient/ModelManifest.xml 252 | **/*.Server/GeneratedArtifacts 253 | **/*.Server/ModelManifest.xml 254 | _Pvt_Extensions 255 | nwjs/www 256 | cache 257 | dist 258 | .temp 259 | 260 | cordova/resources 261 | electron-build 262 | electron/www 263 | typings 264 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 6.5.0 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Thinktecture AG 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 | -------------------------------------------------------------------------------- /cordova/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | BoardZ2 4 | 5 | Small demo app. 6 | 7 | 8 | Thinktecture AG 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 | 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 | -------------------------------------------------------------------------------- /cordova/config_livereload.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | BoardZ2 4 | 5 | Small demo app. 6 | 7 | 8 | Thinktecture AG 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 | 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 | -------------------------------------------------------------------------------- /cordova/hooks/android/after_platform_add_add_plugins.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var pluginlist = [ 4 | "cordova-plugin-crosswalk-webview" 5 | ]; 6 | 7 | var util = require('util') 8 | var exec = require('child_process').exec; 9 | 10 | function puts(error, stdout, stderr) { 11 | util.puts(stdout) 12 | } 13 | 14 | pluginlist.forEach(function(plugin) { 15 | exec("cordova plugin add " + plugin, puts); 16 | }); -------------------------------------------------------------------------------- /cordova/hooks/ios/after_platform_add_add_plugins.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var pluginlist = [ 4 | "https://github.com/apache/cordova-plugins.git#master:wkwebview-engine-localhost" 5 | ]; 6 | 7 | var util = require('util') 8 | var exec = require('child_process').exec; 9 | 10 | function puts(error, stdout, stderr) { 11 | util.puts(stdout) 12 | } 13 | 14 | pluginlist.forEach(function(plugin) { 15 | exec("cordova plugin add " + plugin, puts); 16 | }); -------------------------------------------------------------------------------- /electron/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/electron/icon.png -------------------------------------------------------------------------------- /electron/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let isLiveReload = process.argv[2] === '--livereload'; 4 | 5 | const electron = require('electron'); 6 | const { app, globalShortcut, BrowserWindow, Menu, shell } = electron; 7 | const path = require('path'); 8 | 9 | let client; 10 | if (isLiveReload) { 11 | client = require('electron-connect').client; 12 | } 13 | 14 | let mainWindow; 15 | let trayApp; 16 | 17 | app.on('window-all-closed', () => { 18 | //https://github.com/atom/electron/issues/2312 19 | app.quit(); 20 | }); 21 | 22 | app.on('will-quit', () => { 23 | globalShortcut.unregisterAll(); 24 | }); 25 | 26 | app.on('ready', () => { 27 | mainWindow = new BrowserWindow({ 28 | title: 'BoardZ2', 29 | width: 1024, 30 | minWidth: 768, 31 | height: 700, 32 | titleBarStyle: 'hidden', 33 | webPreferences: { 34 | nodeIntegration: true 35 | } 36 | }); 37 | 38 | buildTrayIcon(); 39 | 40 | globalShortcut.register('CmdOrCtrl+Shift+d', function () { 41 | mainWindow.webContents.toggleDevTools(); 42 | }); 43 | 44 | mainWindow.loadURL('file://' + __dirname + '/index.html'); 45 | mainWindow.setTitle(app.getName()); 46 | 47 | mainWindow.on('closed', () => { 48 | mainWindow = null; 49 | }); 50 | 51 | if (client) { 52 | client.create(mainWindow); 53 | } 54 | 55 | if (process.platform == 'darwin') { 56 | buildNativeAppMenu(); 57 | } 58 | }); 59 | 60 | let buildNativeAppMenu = () => { 61 | var template = [{ 62 | label: "Application", 63 | submenu: [ 64 | { 65 | label: "About Application", selector: "orderFrontStandardAboutPanel:" 66 | }, 67 | { 68 | type: "separator" 69 | }, 70 | { 71 | label: 'Browse Repository', accelerator: 'CmdOrCtrl+G', 72 | click: () => { 73 | shell.openExternal('https://github.com/thinktecture/boardz-cross-platform-sample/') 74 | } 75 | }, 76 | { 77 | type: "separator" 78 | }, 79 | { 80 | label: "Reload", accelerator: "CmdOrCtrl+R", 81 | click: () => { 82 | mainWindow.loadURL('file://' + __dirname + '/index.html'); 83 | } 84 | }, 85 | { 86 | label: "Quit", accelerator: "Command+Q", 87 | click: () => { 88 | app.quit(); 89 | } 90 | } 91 | ] 92 | }, { 93 | label: "Edit", 94 | submenu: [ 95 | { 96 | label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" 97 | }, 98 | { 99 | label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" 100 | }, 101 | { 102 | type: "separator" 103 | }, 104 | { 105 | label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" 106 | }, 107 | { 108 | label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" 109 | }, 110 | { 111 | label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" 112 | }, 113 | { 114 | label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" 115 | } 116 | ] 117 | } 118 | ]; 119 | 120 | Menu.setApplicationMenu(Menu.buildFromTemplate(template)); 121 | }; 122 | let buildTrayIcon = () => { 123 | let trayIconPath = path.join(__dirname, 'icon.png'); 124 | var contextMenu = Menu.buildFromTemplate([ 125 | { 126 | label: 'Radius Search...', 127 | type: 'normal', 128 | click: function () { 129 | mainWindow.webContents.send('navigateTo', '/radiussearch'); 130 | } 131 | }, 132 | { 133 | label: 'Quit', 134 | accelerator: 'Command+Q', 135 | selector: 'terminate:' 136 | } 137 | ]); 138 | 139 | trayApp = new electron.Tray(trayIconPath); 140 | trayApp.setToolTip('BoardZ2'); 141 | trayApp.setContextMenu(contextMenu); 142 | }; 143 | -------------------------------------------------------------------------------- /electron/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BoardZ2", 3 | "version": "0.1.0", 4 | "main": "index.js" 5 | } 6 | -------------------------------------------------------------------------------- /gulp.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | systemJsConfig: './system.config.js', 5 | source: { 6 | folder: './src/BoardZ/', 7 | files: { 8 | injectables: [ 9 | './dist/www/scripts/vendor.min.js', 10 | './dist/www/scripts/system.min.js', 11 | './dist/www/scripts/system.setup.js', 12 | './dist/www/css/vendor.min.css', 13 | './dist/www/css/app.css', 14 | './dist/www/scripts/shim.min.js', 15 | './dist/www/scripts/zone.js', 16 | './dist/www/scripts/reflect.js' 17 | ], 18 | electronFiles: './electron/**/*.*', 19 | cordovaFiles: './cordova/', 20 | cordova: './src/BoardZ/cordova.js', 21 | main: [ 22 | './src/BoardZ/index.html' 23 | ], 24 | systemSetupScript: './src/BoardZ/system.setup.js', 25 | app: { 26 | everything: ['./src/BoardZ/app/**/*', './src/BoardZ/system.setup.js'], 27 | ts: [ 28 | './src/BoardZ/app/**/*.ts' 29 | ], 30 | html: [ 31 | './src/BoardZ/app/**/*.html' 32 | ], 33 | css: [ 34 | 35 | './src/BoardZ/css/**/*.css' 36 | ], 37 | componentCss: [ 38 | './src/BoardZ/app/**/*.css' 39 | ], 40 | assets: [ 41 | './src/BoardZ/assets/**/*.*' 42 | ] 43 | }, 44 | vendorStylesheets: [ 45 | './src/BoardZ/vendor/bootstrap/css/bootstrap.css', 46 | './src/BoardZ/vendor/admin-lte/css/AdminLTE.css', 47 | './src/BoardZ/vendor/admin-lte/css/skins/_all-skins.css', 48 | './src/BoardZ/vendor/font-awesome/css/font-awesome.css', 49 | './src/BoardZ/vendor/pNotify/pnotify.custom.css', 50 | './src/BoardZ/vendor/leaflet-js/leaflet.css' 51 | ], 52 | vendorFonts: [ 53 | './src/BoardZ/vendor/font-awesome/fonts/*.*', 54 | './src/BoardZ/vendor/bootstrap/fonts/*.*' 55 | ], 56 | shim: [ 57 | './node_modules/es6-shim/es6-shim.min.js', 58 | './node_modules/angular2/es6/dev/src/testing/shims_for_IE.js' 59 | ], 60 | vendorJs: [ 61 | './src/BoardZ/vendor/hammerjs/hammer.js', 62 | './src/BoardZ/vendor/jquery/jquery-2.1.4.js', 63 | './src/BoardZ/vendor/jquery/jquery.hammer.js', 64 | './src/BoardZ/vendor/jquery/jquery.slimscroll.js', 65 | './src/BoardZ/vendor/pNotify/pnotify-adapter.js', 66 | './src/BoardZ/vendor/pNotify/pnotify.custom.js', 67 | './src/BoardZ/vendor/signalr/signalr.js', 68 | './src/BoardZ/vendor/bootstrap/js/bootstrap.js', 69 | './src/BoardZ/vendor/fastclick/fastclick.js', 70 | './src/BoardZ/vendor/admin-lte/js/app.js', 71 | './src/BoardZ/vendor/leaflet-js/leaflet-src.js' 72 | 73 | ], 74 | angular2rc1deps: [ 75 | './node_modules/core-js/client/shim.min.js', 76 | './node_modules/zone.js/dist/zone.js', 77 | './node_modules/reflect-metadata/reflect.js' 78 | ], 79 | angular2: './node_modules/@angular/**/*', 80 | rxjs: './node_modules/rxjs/**/*', 81 | systemJs: './node_modules/systemjs/dist/system.src.js' 82 | } 83 | }, 84 | ts: { 85 | config: './tsconfig.json' 86 | }, 87 | targets: { 88 | systemMinJs: 'system.min.js', 89 | vendorMinJs: 'vendor.min.js', 90 | vendorMinCss: 'vendor.min.css', 91 | buildFolder: './dist/www', 92 | electronFolder: './dist/desktop', 93 | cordovaFolder: './dist/mobile', 94 | resourcesFolder: './resources/', 95 | hooksFolder: './cordova/hooks/', 96 | appFolder: 'app', 97 | stylesFolder: 'css', 98 | minified: { 99 | js: 'app.js', 100 | css: 'app.css', 101 | templateCache: 'ng-templates.js' 102 | } 103 | } 104 | }; 105 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | // main gulpfile 2 | 3 | (function () { 4 | 'use strict'; 5 | 6 | var config = require('./gulp.config'), 7 | gulp = require('gulp'), 8 | del = require('del'), 9 | runSequence = require('run-sequence'), 10 | gulptasks = require('require-dir')('./gulpTasks'); 11 | 12 | 13 | for (var gulpTask in gulptasks) { 14 | gulptasks[gulpTask].init(gulp, config); 15 | } 16 | 17 | gulp.task('default', function (done) { 18 | return runSequence( 19 | 'build-web', done 20 | ); 21 | }); 22 | 23 | gulp.task('clean', function () { 24 | return del(config.targets.buildFolder + '/**/*', { force: true }); 25 | }); 26 | 27 | gulp.task('build-all', function (done) { 28 | return runSequence( 29 | 'build-web', 30 | [ 31 | 'build-electron', 32 | 'build-cordova' 33 | ] 34 | , done 35 | ); 36 | }); 37 | 38 | })(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "boardz-xplatform-sample", 3 | "version": "1.0.0", 4 | "description": "Sample for demonstrating various aspects of modern cross-platform applications.", 5 | "main": "gulpfile.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/thinktecture/boardz-cross-platform-sample.git" 9 | }, 10 | "scripts": { 11 | "gulp": "gulp", 12 | "typings": "typings", 13 | "watch": "gulp watch-web", 14 | "postinstall": "npm run typings install", 15 | "build": "gulp", 16 | "watch-ios": "gulp [private-web]:watch:no-liveserver & gulp cordova:watch:ios" 17 | }, 18 | "author": "Thinktecture AG ", 19 | "bugs": { 20 | "url": "https://github.com/thinktecture/boardz-cross-platform-sample/issues" 21 | }, 22 | "homepage": "https://github.com/thinktecture/boardz-cross-platform-sample#readme", 23 | "devDependencies": { 24 | "bootstrap": "^3.3.6", 25 | "cordova-icon": "^0.7.0", 26 | "cordova-splash": "^0.7.1", 27 | "del": "^2.0.2", 28 | "electron-connect": "^0.3.7", 29 | "electron-prebuilt": "^0.37.2", 30 | "event-stream": "^3.3.1", 31 | "font-awesome": "^4.5.0", 32 | "gulp": "^3.9.0", 33 | "gulp-atom-electron": "^1.4.0", 34 | "gulp-awesome-electron": "^1.2.0", 35 | "gulp-batch": "1.0.5", 36 | "gulp-clean-css": "^2.0.10", 37 | "gulp-concat": "^2.6.0", 38 | "gulp-filelog": "^0.4.1", 39 | "gulp-inject": "^3.0.0", 40 | "gulp-minify-html": "^1.0.4", 41 | "gulp-ng-annotate": "^1.1.0", 42 | "gulp-ng-template": "^0.2.1", 43 | "gulp-rename": "^1.2.2", 44 | "gulp-rewrite-css": "0.0.7", 45 | "gulp-server-livereload": "^1.5.3", 46 | "gulp-sourcemaps": "^1.6.0", 47 | "gulp-symdest": "^1.0.0", 48 | "gulp-tap": "^0.1.3", 49 | "gulp-tslint": "^6.1.1", 50 | "gulp-typescript": "^2.10.0", 51 | "gulp-uglify": "^1.4.1", 52 | "gulp-watch": "^4.3.5", 53 | "merge2": "^0.3.7", 54 | "require-dir": "^0.3.0", 55 | "run-sequence": "^1.2.2", 56 | "shelljs": "^0.5.3", 57 | "stream-series": "^0.1.1", 58 | "systemjs-builder": "0.15.13", 59 | "tether": "^1.1.1", 60 | "tslint": "^3.15.1", 61 | "typescript": "^2.0.2", 62 | "typings": "^1.3.2" 63 | }, 64 | "dependencies": { 65 | "@angular/common": "2.0.0", 66 | "@angular/compiler": "2.0.0", 67 | "@angular/core": "2.0.0", 68 | "@angular/forms": "2.0.0", 69 | "@angular/http": "2.0.0", 70 | "@angular/platform-browser": "2.0.0", 71 | "@angular/platform-browser-dynamic": "2.0.0", 72 | "@angular/router": "3.0.0", 73 | "core-js": "2.4.1", 74 | "reflect-metadata": "0.1.3", 75 | "rxjs": "5.0.0-beta.12", 76 | "systemjs": "0.19.27", 77 | "zone.js": "^0.6.23" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /resources/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/resources/icon.icns -------------------------------------------------------------------------------- /resources/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/resources/icon.ico -------------------------------------------------------------------------------- /resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/resources/icon.png -------------------------------------------------------------------------------- /resources/icon_256.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/resources/icon_256.ico -------------------------------------------------------------------------------- /resources/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/resources/splash.png -------------------------------------------------------------------------------- /src/BoardZ/app/apiConfig.ts: -------------------------------------------------------------------------------- 1 | export class ApiConfig { 2 | 3 | public get rootUrl(): string { 4 | return 'https://boardzapi.azurewebsites.net/'; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/BoardZ/app/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 | 7 |
8 |
9 | 10 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /src/BoardZ/app/app.ts: -------------------------------------------------------------------------------- 1 | import {Component, AfterViewInit} from '@angular/core'; 2 | import {LogService} from './services/logService'; 3 | import {LogLevel} from './models/logLevel'; 4 | import {SignalRService} from './services/signalrService'; 5 | import {LoginService} from './services/loginService'; 6 | import {NotificationService} from './services/notificationService'; 7 | import {UiNotificationService} from './services/uiNotificationService'; 8 | import {NativeIntegrationService} from './services/nativeIntegrationService'; 9 | import {IBoardZAppWindow} from './interfaces/boardzAppWindow'; 10 | 11 | declare var window: IBoardZAppWindow; 12 | 13 | @Component({ 14 | moduleId: module.id, 15 | selector: 'boardz-app', 16 | templateUrl: 'app.html' 17 | }) 18 | 19 | export class BoardzAppComponent implements AfterViewInit { 20 | constructor(private _signalRService: SignalRService, 21 | private _loginService: LoginService, 22 | private _notificationService: NotificationService, 23 | private _nativeIntegrationService: NativeIntegrationService, 24 | private _uiNotificationService: UiNotificationService, 25 | private _logService: LogService) { 26 | _logService.maximumLogLevel = LogLevel.Verbose; 27 | _uiNotificationService.subscribeToNotifications(); 28 | } 29 | 30 | public ngAfterViewInit(): any { 31 | if (window.initAdminLTE) { 32 | window.initAdminLTE(); 33 | } 34 | 35 | if (this._loginService.isAuthenticated) { 36 | this._signalRService.start(); 37 | } 38 | 39 | this._signalRService.someoneJoinedAGame.subscribe(message => { 40 | this._notificationService.notifyInformation(message); 41 | }); 42 | 43 | this._nativeIntegrationService.registerNavigationHook(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/dashboard/dashboard.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Dashboard

4 |
5 | 6 |
7 | 8 |
9 |
10 | 11 |
12 |
13 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/dashboard/dashboard.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | import {GamesService} from '../../services/gamesService'; 4 | import {PlayersService} from '../../services/playersService'; 5 | 6 | @Component({ 7 | moduleId: module.id, 8 | selector: 'dashboard', 9 | templateUrl: 'dashboard.html' 10 | }) 11 | export class DashboardComponent implements OnInit { 12 | public playerCount: string = '-'; 13 | public gameCount: string = '-'; 14 | 15 | constructor(private _gamesService: GamesService, 16 | private _playersService: PlayersService) { 17 | } 18 | 19 | public ngOnInit(): any { 20 | this._playersService.getPlayerCount() 21 | .subscribe(result => this.playerCount = result.toString()); 22 | 23 | this._gamesService.getGameCount() 24 | .subscribe(result => this.gameCount = result.toString()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/games/details.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |

New game

6 |

Game details

7 |
8 |
9 |
10 |
11 | 12 |
13 | 16 |
17 | Game name is required 18 |
19 |
20 |
21 |
22 | 23 |
24 | 28 |
29 | Game description is required 30 |
31 |
32 |
33 |
34 | 45 |
46 |
47 |
48 |
49 | 50 |
51 | 52 |
53 | 54 |
55 |
56 | 57 |
58 |
59 |
60 |
61 |

I'm playing this game

62 |
63 | 65 |
66 |
67 |
68 |

The "I am gaming!" function uploads an image and your current location for other gamers to join you 69 | on your journey!

70 |
71 | 76 |
77 |
78 |
79 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/games/gamesRoot.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Games

4 |
5 |
6 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/games/gamesRoot.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | moduleId: module.id, 5 | templateUrl: 'gamesRoot.html' 6 | }) 7 | export class GamesRootComponent { 8 | } 9 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/games/list.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |

All Games

6 | 7 |
8 | 11 |
12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
NameDescription
{{game.name}}{{game.description}}
28 |
29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/games/list.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Router, ActivatedRoute} from '@angular/router'; 3 | 4 | import {Game} from '../../models/game'; 5 | import {GamesService} from '../../services/gamesService'; 6 | import {NotificationService} from '../../services/notificationService'; 7 | 8 | @Component({ 9 | moduleId: module.id, 10 | selector: 'game-list', 11 | templateUrl: 'list.html' 12 | }) 13 | export class GameListComponent implements OnInit { 14 | public games: Game[]; 15 | 16 | constructor(private _gamesService: GamesService, 17 | private _router: Router, 18 | private _route: ActivatedRoute, 19 | private _notificationService: NotificationService) { 20 | } 21 | 22 | public openGameDetails(game: Game): void { 23 | this._router.navigate(['../details', game.id], { relativeTo: this._route }); 24 | } 25 | 26 | public openCreateGame(): void { 27 | this._router.navigate(['../new'], { relativeTo: this._route }); 28 | } 29 | 30 | public ngOnInit(): void { 31 | this._gamesService.getAll() 32 | .subscribe( 33 | (games) => this.games = games, 34 | (err) => this._notificationService.notifyError('Error while fetching game data') 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/header/header.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | 51 |
52 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/header/header.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | import {Notification} from '../../models/notification'; 4 | import {LoginService} from '../../services/loginService'; 5 | import {TokenService} from '../../services/tokenService'; 6 | import {NotificationService} from '../../services/notificationService'; 7 | 8 | @Component({ 9 | moduleId: module.id, 10 | selector: 'boardz-header', 11 | templateUrl: 'header.html' 12 | }) 13 | export class HeaderComponent implements OnInit { 14 | private notifications: Notification[] = []; 15 | 16 | public loggedIn: boolean = false; 17 | 18 | constructor(public loginService: LoginService, 19 | private _tokenService: TokenService, 20 | private _notificationService: NotificationService) { 21 | } 22 | 23 | public ngOnInit(): any { 24 | this._notificationService.notifications.subscribe( 25 | (notification) => this.onNotification(notification) 26 | ); 27 | this._tokenService.isAuthenticated().subscribe(result => this.loggedIn = result); 28 | } 29 | 30 | public dismiss(notification: Notification): boolean { 31 | if (notification) { 32 | let index = this.notifications.indexOf(notification); 33 | 34 | if (index > -1) { 35 | this.notifications.splice(index, 1); 36 | } 37 | } else { 38 | this.notifications = []; 39 | } 40 | 41 | return false; 42 | } 43 | 44 | private onNotification(notification: Notification): void { 45 | this.notifications.unshift(notification); 46 | } 47 | 48 | logout(event): void { 49 | event.preventDefault(); 50 | 51 | this.loginService.logout(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/locateIt/locateIt.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 |

Your location

6 |
7 |
8 |

Looking up your location...

9 | 10 |

Sorry, we can't access your location.

11 |
12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/locateIt/locateIt.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import {Component, Output, OnInit, EventEmitter} from '@angular/core'; 4 | 5 | import {GeoLocation} from '../../models/geoLocation'; 6 | import {GeolocationService} from '../../services/geolocationService'; 7 | 8 | @Component({ 9 | moduleId: module.id, 10 | selector: 'locate-it', 11 | templateUrl: 'locateIt.html' 12 | }) 13 | export class LocateItComponent implements OnInit { 14 | private _hasError: boolean = false; 15 | private _isLocating: boolean = false; 16 | private _coords: GeoLocation = null; 17 | @Output('onLocated') 18 | private _onLocated: EventEmitter = new EventEmitter(); 19 | 20 | public map; 21 | 22 | constructor(private _geolocationService: GeolocationService) { 23 | L.Icon.Default.imagePath = 'app/images'; 24 | } 25 | 26 | ngOnInit(): any { 27 | // Berlin ;-) 28 | this.map = L.map('map').setView([52.5167, 13.3833], 7); 29 | 30 | L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', { 31 | maxZoom: 13 32 | }).addTo(this.map); 33 | 34 | this._isLocating = true; 35 | this._geolocationService.locate() 36 | .then((coords: GeoLocation) => { 37 | this._hasError = false; 38 | this._isLocating = false; 39 | this._coords = coords; 40 | this._onLocated.emit(coords); 41 | 42 | this.setMapMarkerAndView(); 43 | }) 44 | .catch(() => { 45 | this._hasError = true; 46 | this._isLocating = false; 47 | }); 48 | } 49 | 50 | private setMapMarkerAndView() { 51 | const coordinates = [this._coords.latitude, this._coords.longitude]; 52 | this.map.setView(coordinates, 13); 53 | L.marker(coordinates).addTo(this.map); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/login/login.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |

Welcome to BoardZ!

6 |
7 |
8 | 9 | 10 | 13 |
14 | Username is required 15 |
16 |
17 | 18 |
19 | 20 | 21 | 24 | 25 |
26 |

Required: Password is required

27 |
28 |
29 |
30 |
 
31 |
32 | Login failed. Please check your credentials and try again. 33 |
34 |
35 | 36 |
37 | 45 |
46 |
47 |
48 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/login/login.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | 4 | import {LoginService} from '../../services/loginService'; 5 | import {LogService} from '../../services/logService'; 6 | import {NotificationService} from '../../services/notificationService'; 7 | import {SignalRService} from '../../services/signalrService'; 8 | 9 | @Component({ 10 | moduleId: module.id, 11 | selector: 'login', 12 | templateUrl: 'login.html' 13 | }) 14 | export class LoginComponent { 15 | private _userName: string; 16 | private _password: string; 17 | public _hasError: boolean = false; 18 | 19 | constructor(private _router: Router, 20 | private _loginService: LoginService, 21 | private _logService: LogService, 22 | private _notificationService: NotificationService, 23 | private _signalRService: SignalRService) { 24 | } 25 | 26 | public doLogin(): void { 27 | this._logService.logDebug('LoginComponent.doLogin called'); 28 | 29 | this._loginService.login(this._userName, this._password) 30 | .subscribe( 31 | () => { 32 | this._signalRService.start(); 33 | this.setError(false); 34 | this._router.navigate(['']); 35 | }, 36 | () => { 37 | this.setError(true); 38 | this._notificationService.notifyError('Login was unsuccessful.'); 39 | } 40 | ); 41 | } 42 | 43 | setError(value: boolean) { 44 | this._logService.logDebug('LoginComponent.setError: Setting error state to: ' + value); 45 | this._hasError = value; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/notifications/notifications.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Test Notifications

4 |
5 |
6 |
7 |
8 |
9 | 10 | 11 |
Send as:
12 | 15 | 18 | 21 | 24 |
25 |
26 |
27 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/notifications/notifications.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | import {NotificationService} from '../../services/notificationService'; 4 | 5 | @Component({ 6 | moduleId: module.id, 7 | selector: 'notifications', 8 | templateUrl: 'notifications.html' 9 | }) 10 | export class NotificationsComponent { 11 | constructor(public notificationService: NotificationService) { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/pictureIt/pictureIt.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Add a picture

4 |
5 |
6 | 7 |

Take a picture of you and your game!

8 | 11 | 12 |

13 | Sorry, but we can't access your camera to take a picture. :-(

14 | 15 |
16 |
17 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/pictureIt/pictureIt.ts: -------------------------------------------------------------------------------- 1 | import {Component, Output, EventEmitter} from '@angular/core'; 2 | 3 | import {CameraService} from '../../services/cameraService'; 4 | 5 | @Component({ 6 | moduleId: module.id, 7 | selector: 'picture-it', 8 | templateUrl: 'pictureIt.html' 9 | }) 10 | export class PictureItComponent { 11 | @Output('onPictureTaken') 12 | private _onPictureTaken: EventEmitter = new EventEmitter(); 13 | 14 | public pictureUrl: string; 15 | public hasError: boolean; 16 | 17 | constructor(private _cameraService: CameraService) { 18 | } 19 | 20 | public takePicture() { 21 | this.hasError = false; 22 | 23 | this._cameraService.getPhoto() 24 | .subscribe( 25 | picture => this._onPictureTaken.emit(this.pictureUrl = picture), 26 | () => this.hasError = true 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/radiusSearch/radiusSearch.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Find players around you

4 |
5 |
6 | 7 |
8 |
9 | 18 |
19 |
20 | 21 |
22 |
23 | 24 |
25 |
26 |
27 |
28 |

{{p.player.name}}

29 |
30 |
31 |

{{p.player.name}} is playing {{p.player.boardGameName}}

32 | Photo 33 |
34 | 35 | 38 |
39 |
40 |
41 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/radiusSearch/radiusSearch.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | import {GeoLocation} from '../../models/geoLocation'; 4 | import {GeolocationService} from '../../services/geolocationService'; 5 | import {PlayersService} from '../../services/playersService'; 6 | import {NearByPlayer} from '../../models/nearbyPlayer'; 7 | 8 | @Component({ 9 | moduleId: module.id, 10 | selector: 'radius-search', 11 | templateUrl: 'radiusSearch.html' 12 | }) 13 | export class RadiusSearchComponent implements OnInit { 14 | private _location: GeoLocation; 15 | private _radius: number = 10; 16 | private _players: NearByPlayer[]; 17 | 18 | constructor(private _geoLocationService: GeolocationService, 19 | private _playersService: PlayersService) { 20 | } 21 | 22 | public ngOnInit() { 23 | this._geoLocationService.locate() 24 | .then((coordinates: GeoLocation) => this._location = coordinates); 25 | } 26 | 27 | public search() { 28 | this._playersService.findNearby(this._radius, this._location) 29 | .subscribe(results => this._players = results); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/sidebar/sidebar.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/sidebar/sidebar.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | import {NavigationEntry} from '../../models/navigationEntry'; 4 | 5 | @Component({ 6 | moduleId: module.id, 7 | selector: 'sidebar', 8 | templateUrl: 'sidebar.html' 9 | }) 10 | export class SidebarComponent { 11 | public expanded: boolean = true; 12 | public navigationEntries: Array; 13 | 14 | constructor() { 15 | this.navigationEntries = []; 16 | this.navigationEntries.push(new NavigationEntry([''], 'dashboard', 'Dashboard')); 17 | this.navigationEntries.push(new NavigationEntry(['/games/all'], 'list', 'Games')); 18 | this.navigationEntries.push(new NavigationEntry(['/radiussearch'], 'location-arrow', 'Players search')); 19 | 20 | //this.navigationEntries.push(new NavigationEntry(['/notifications'], 'bell', 'Test Notifcations')); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/widget/widget.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

{{_count}}

4 | 5 |

{{_caption}}

6 |
7 |
8 | 9 |
10 | More info 11 |
12 | -------------------------------------------------------------------------------- /src/BoardZ/app/components/widget/widget.ts: -------------------------------------------------------------------------------- 1 | import {Component, Input, ChangeDetectionStrategy} from '@angular/core'; 2 | 3 | @Component({ 4 | moduleId: module.id, 5 | selector: 'widget', 6 | templateUrl: 'widget.html', 7 | changeDetection: ChangeDetectionStrategy.OnPush 8 | }) 9 | export class WidgetComponent { 10 | @Input('caption') 11 | _caption: string; 12 | @Input('count') 13 | _count: string; 14 | @Input('icon') 15 | _icon: string; 16 | @Input('color') 17 | _color: string; 18 | @Input('target') 19 | _target: string; 20 | } 21 | -------------------------------------------------------------------------------- /src/BoardZ/app/directives/backButtonDirective.ts: -------------------------------------------------------------------------------- 1 | import {Directive, HostListener} from '@angular/core'; 2 | import {Location} from '@angular/common'; 3 | 4 | import {PlatformInformationService} from '../services/platformInformationService'; 5 | 6 | @Directive({ 7 | selector: '[back-button]', 8 | host: { 9 | '[attr.hidden]': 'isHidden' 10 | } 11 | }) 12 | export class BackButtonDirective { 13 | public isHidden: boolean = true; 14 | 15 | constructor(private _platformInformationService: PlatformInformationService, 16 | private _location: Location) { 17 | this.setHidden(); 18 | } 19 | 20 | private setHidden(): void { 21 | this.isHidden = this._platformInformationService.isWeb; 22 | } 23 | 24 | @HostListener('click') 25 | public onClick() { 26 | this._location.back(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/BoardZ/app/directives/closeSidebarOnClickDirective.ts: -------------------------------------------------------------------------------- 1 | import {Directive, HostListener} from '@angular/core'; 2 | 3 | import {PlatformInformationService} from '../services/platformInformationService'; 4 | 5 | // This is currently _not_ the correct Angular 2 way of doing this. 6 | // There is no Angular 2 way, yet :) 7 | @Directive({ 8 | selector: '[close-sidebar-on-click]' 9 | }) 10 | export class CloseSidebarOnClickDirective { 11 | constructor(private _platformInformationService: PlatformInformationService) { 12 | } 13 | 14 | @HostListener('click') 15 | public onClick() { 16 | if (!this._platformInformationService.isMobile) { 17 | } 18 | 19 | document.body.classList.remove('sidebar-open'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/BoardZ/app/guards/authenticationGuard.ts: -------------------------------------------------------------------------------- 1 | import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from '@angular/router'; 2 | import {Injectable} from '@angular/core'; 3 | import {Observable} from 'rxjs/Rx'; 4 | 5 | import {TokenService} from '../services/tokenService'; 6 | 7 | @Injectable() 8 | export class AuthenticationGuard implements CanActivate { 9 | 10 | constructor(private _router: Router, private _tokenService: TokenService) { 11 | } 12 | 13 | public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { 14 | return Observable.create(observer => { 15 | this._tokenService.isAuthenticated() 16 | .subscribe( 17 | (isAuthenticated) => { 18 | isAuthenticated ? observer.next(isAuthenticated) : this.navigateToLogin() && observer.next(false); 19 | }, 20 | (error) => { 21 | this.navigateToLogin(); 22 | observer.next(false); 23 | }, () => { 24 | observer.complete(); 25 | }); 26 | }); 27 | } 28 | 29 | private navigateToLogin() { 30 | this._router.navigate(['/login']); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/BoardZ/app/interfaces/boardzAppWindow.ts: -------------------------------------------------------------------------------- 1 | export interface IBoardZAppWindow extends Window { 2 | initAdminLTE(): void; 3 | require(name: string): any; 4 | } 5 | -------------------------------------------------------------------------------- /src/BoardZ/app/main.ts: -------------------------------------------------------------------------------- 1 | // require all 3rd party libs 2 | import 'bootstrap/js/bootstrap'; 3 | import 'admin-lte/js/app'; 4 | import 'hammerjs/hammer'; 5 | import 'jquery/jquery.hammer'; 6 | import 'jquery/jquery.slimscroll'; 7 | import 'pNotify/pnotify-adapter'; 8 | import 'signalr/signalr'; 9 | import 'leaflet/leaflet'; 10 | import 'fastclick/fastclick'; 11 | import {enableProdMode} from '@angular/core'; 12 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; 13 | import 'rxjs/add/observable/of'; 14 | import 'rxjs/add/operator/map'; 15 | import {AppModule} from './modules/appModule'; 16 | 17 | enableProdMode(); 18 | 19 | platformBrowserDynamic().bootstrapModule(AppModule); 20 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/game.ts: -------------------------------------------------------------------------------- 1 | export class Game { 2 | public id: string = null; 3 | public name: string; 4 | public description: string; 5 | public userName: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/geoLocation.ts: -------------------------------------------------------------------------------- 1 | export class GeoLocation { 2 | 3 | constructor(public latitude: number, public longitude: number, public zoom: number) { 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/logLevel.ts: -------------------------------------------------------------------------------- 1 | export enum LogLevel { 2 | Critical, 3 | Error, 4 | Warning, 5 | Info, 6 | Debug, 7 | Verbose 8 | } 9 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/navigationEntry.ts: -------------------------------------------------------------------------------- 1 | export class NavigationEntry { 2 | constructor(public links: Array, public icon: string, public displayName: string) { 3 | } 4 | } 5 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/nearbyPlayer.ts: -------------------------------------------------------------------------------- 1 | import {Player} from './player'; 2 | 3 | export class NearByPlayer { 4 | public distance: number; 5 | public player: Player; 6 | } 7 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/notification.ts: -------------------------------------------------------------------------------- 1 | import {NotificationType} from './notificationType'; 2 | 3 | export class Notification { 4 | constructor(public message: string, 5 | public type: NotificationType = NotificationType.Information) { 6 | } 7 | 8 | get iconCssClass() { 9 | switch (this.type) { 10 | case NotificationType.Information: 11 | return 'fa-info'; 12 | case NotificationType.Success: 13 | return 'fa-hand-peace-o'; 14 | case NotificationType.Warning: 15 | return 'fa-warning'; 16 | case NotificationType.Error: 17 | return 'fa-exclamation-triangle danger'; 18 | default: 19 | return 'fa-info'; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/notificationType.ts: -------------------------------------------------------------------------------- 1 | export enum NotificationType { 2 | Information, 3 | Success, 4 | Warning, 5 | Error, 6 | } 7 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/picture.ts: -------------------------------------------------------------------------------- 1 | export class Picture { 2 | 3 | constructor(public pictureUrl: string) { 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/player.ts: -------------------------------------------------------------------------------- 1 | import {GeoLocation} from './geoLocation'; 2 | 3 | export class Player{ 4 | public id: string; 5 | public name: string; 6 | public boardGameId: string; 7 | public boardGameName: string; 8 | public coordinate: GeoLocation; 9 | public imageUrl: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/BoardZ/app/models/tokenData.ts: -------------------------------------------------------------------------------- 1 | export interface TokenData { 2 | access_token: string; 3 | token_type: string; 4 | expires_in: number; 5 | } 6 | -------------------------------------------------------------------------------- /src/BoardZ/app/modules/appModule.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {SharedModule} from './sharedModule'; 3 | import {GamesModule} from './gamesModule'; 4 | import {ModuleConfiguration} from './modulesConfig'; 5 | 6 | @NgModule({ 7 | imports: [ModuleConfiguration.App.imports, SharedModule, GamesModule], 8 | exports: ModuleConfiguration.App.exports, 9 | declarations: ModuleConfiguration.App.declarations, 10 | providers: ModuleConfiguration.App.providers, 11 | bootstrap: ModuleConfiguration.App.bootstraps 12 | }) 13 | export class AppModule { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/BoardZ/app/modules/gamesModule.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {ModuleConfiguration} from './modulesConfig'; 3 | import {SharedModule} from './sharedModule'; 4 | 5 | @NgModule({ 6 | imports: [ModuleConfiguration.Games.imports, SharedModule], 7 | exports: ModuleConfiguration.Games.exports, 8 | declarations: ModuleConfiguration.Games.declarations, 9 | providers: ModuleConfiguration.Games.providers 10 | }) 11 | export class GamesModule { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/BoardZ/app/modules/modulesConfig.ts: -------------------------------------------------------------------------------- 1 | import {FormsModule} from '@angular/forms'; 2 | import {BoardzAppComponent} from '../app'; 3 | import {DashboardComponent} from '../components/dashboard/dashboard'; 4 | import {LoginComponent} from '../components/login/login'; 5 | import {RadiusSearchComponent} from '../components/radiusSearch/radiusSearch'; 6 | import {NotificationsComponent} from '../components/notifications/notifications'; 7 | import {HeaderComponent} from '../components/header/header'; 8 | import {SidebarComponent} from '../components/sidebar/sidebar'; 9 | import {WidgetComponent} from '../components/widget/widget'; 10 | import {BackButtonDirective} from '../directives/backButtonDirective'; 11 | import {CloseSidebarOnClickDirective} from '../directives/closeSidebarOnClickDirective'; 12 | import {BrowserModule} from '@angular/platform-browser'; 13 | import {HttpModule, XHRBackend, ConnectionBackend} from '@angular/http'; 14 | import {APP_ROUTING, appRoutingProviders, GAMES_ROUTING} from '../routing/routingConfig'; 15 | import {ApiConfig} from '../apiConfig'; 16 | import {HashLocationStrategy, LocationStrategy, CommonModule} from '@angular/common'; 17 | import {NativeIntegrationService} from '../services/nativeIntegrationService'; 18 | import {AuthenticatedHttp} from '../services/authenticatedHttp'; 19 | import {TokenService} from '../services/tokenService'; 20 | import {LoginService} from '../services/loginService'; 21 | import {LogService} from '../services/logService'; 22 | import {GamesService} from '../services/gamesService'; 23 | import {PlayersService} from '../services/playersService'; 24 | import {NotificationService} from '../services/notificationService'; 25 | import {PlatformInformationService} from '../services/platformInformationService'; 26 | import {UiNotificationService} from '../services/uiNotificationService'; 27 | import {SignalRService} from '../services/signalrService'; 28 | import {GameListComponent} from '../components/games/list'; 29 | import {GameDetailsComponent} from '../components/games/details'; 30 | import {GamesRootComponent} from '../components/games/gamesRoot'; 31 | import {GameDetailsResolver} from '../resolvers/gameDetailsResolver'; 32 | import {CameraService} from '../services/cameraService'; 33 | import {MobileCameraService} from '../services/mobileCameraService'; 34 | import {DesktopCameraService} from '../services/desktopCameraService'; 35 | import {PictureItComponent} from '../components/pictureIt/pictureIt'; 36 | import {LocateItComponent} from '../components/locateIt/locateIt'; 37 | import {GeolocationService} from '../services/geolocationService'; 38 | 39 | export namespace ModuleConfiguration { 40 | 41 | export class App { 42 | 43 | public static declarations = [ 44 | BoardzAppComponent, 45 | DashboardComponent, 46 | LoginComponent, 47 | RadiusSearchComponent, 48 | NotificationsComponent, 49 | HeaderComponent, 50 | SidebarComponent, 51 | WidgetComponent, 52 | BackButtonDirective, 53 | CloseSidebarOnClickDirective 54 | ]; 55 | 56 | public static imports = [ 57 | BrowserModule, 58 | HttpModule, 59 | FormsModule, 60 | APP_ROUTING 61 | ]; 62 | 63 | public static exports = []; 64 | 65 | public static providers = [{ provide: LocationStrategy, useClass: HashLocationStrategy }, 66 | { provide: ConnectionBackend, useClass: XHRBackend }, 67 | ApiConfig, 68 | NativeIntegrationService, 69 | AuthenticatedHttp, 70 | TokenService, 71 | LoginService, 72 | LogService, 73 | GamesService, 74 | PlayersService, 75 | NotificationService, 76 | PlatformInformationService, 77 | UiNotificationService, 78 | SignalRService, 79 | appRoutingProviders]; 80 | 81 | public static bootstraps = [BoardzAppComponent] 82 | } 83 | 84 | export class Games { 85 | 86 | public static declarations = [GamesRootComponent, GameDetailsComponent, GameListComponent]; 87 | 88 | public static imports = [CommonModule, FormsModule, GAMES_ROUTING]; 89 | 90 | public static exports = []; 91 | 92 | public static providers = [GameDetailsResolver]; 93 | } 94 | 95 | export class Shared { 96 | 97 | public static declarations = [PictureItComponent, LocateItComponent]; 98 | 99 | public static imports = [CommonModule, FormsModule]; 100 | 101 | public static exports = [PictureItComponent, LocateItComponent]; 102 | 103 | public static providers = [ 104 | { 105 | provide: CameraService, useFactory: (() => { 106 | return (platformInformationService: PlatformInformationService): CameraService => { 107 | return platformInformationService.isMobile ? new MobileCameraService() : new DesktopCameraService(); 108 | }; 109 | })(), deps: [PlatformInformationService] 110 | }, 111 | GeolocationService 112 | ]; 113 | } 114 | } 115 | 116 | -------------------------------------------------------------------------------- /src/BoardZ/app/modules/sharedModule.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {ModuleConfiguration} from './modulesConfig'; 3 | 4 | @NgModule({ 5 | declarations: ModuleConfiguration.Shared.declarations, 6 | imports: ModuleConfiguration.Shared.imports, 7 | exports: ModuleConfiguration.Shared.exports, 8 | providers: ModuleConfiguration.Shared.providers 9 | }) 10 | export class SharedModule { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/BoardZ/app/resolvers/gameDetailsResolver.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Resolve, ActivatedRouteSnapshot} from '@angular/router'; 3 | 4 | import {Game} from '../models/game'; 5 | import {GamesService} from '../services/gamesService'; 6 | 7 | @Injectable() 8 | export class GameDetailsResolver implements Resolve { 9 | constructor(private _gamesService: GamesService) { 10 | } 11 | 12 | resolve(route: ActivatedRouteSnapshot): Promise { 13 | let id = route.params['id']; 14 | 15 | return new Promise((resolve) => { 16 | this._gamesService.getById(id).subscribe(game => { 17 | if (game) { 18 | resolve(game); 19 | } else { 20 | resolve(new Game()); 21 | } 22 | }); 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/BoardZ/app/routing/routingConfig.ts: -------------------------------------------------------------------------------- 1 | import {ModuleWithProviders} from '@angular/core'; 2 | import {RouterModule, Routes} from '@angular/router'; 3 | import {DashboardComponent} from '../components/dashboard/dashboard'; 4 | import {LoginComponent} from '../components/login/login'; 5 | import {NotificationsComponent} from '../components/notifications/notifications'; 6 | import {RadiusSearchComponent} from '../components/radiusSearch/radiusSearch'; 7 | import {GameDetailsResolver} from '../resolvers/gameDetailsResolver'; 8 | import {GameDetailsComponent} from '../components/games/details'; 9 | import {GameListComponent} from '../components/games/list'; 10 | import {GamesRootComponent} from '../components/games/gamesRoot'; 11 | import {AuthenticationGuard} from '../guards/authenticationGuard'; 12 | 13 | const appRootRoutes: Routes = [ 14 | 15 | { path: '', name: 'Dashboard', canActivate: [AuthenticationGuard], component: DashboardComponent }, 16 | { path: 'login', name: 'Login', component: LoginComponent }, 17 | { path: 'notifications', name: 'Notifications', canActivate: [AuthenticationGuard], component: NotificationsComponent }, 18 | { path: 'radiussearch', name: 'RadiusSearch', canActivate: [AuthenticationGuard], component: RadiusSearchComponent } 19 | ]; 20 | 21 | const gameRoutes: Routes = [ 22 | 23 | { 24 | path: 'games', 25 | component: GamesRootComponent, 26 | canActivate: [AuthenticationGuard], 27 | children: [ 28 | { path: 'all', component: GameListComponent, data: { displayName: 'Game overview' } }, 29 | { 30 | path: 'new', 31 | component: GameDetailsComponent, 32 | name: 'CreateGame', 33 | data: { displayName: 'Create a new game' } 34 | }, 35 | { 36 | path: 'details/:id', 37 | component: GameDetailsComponent, 38 | name: 'GameDetails', 39 | resolve: { game: GameDetailsResolver }, 40 | data: { displayName: 'Game details' } 41 | } 42 | ] 43 | } 44 | 45 | ]; 46 | export const appRoutingProviders: any[] = [AuthenticationGuard]; 47 | 48 | export const APP_ROUTING: ModuleWithProviders = RouterModule.forRoot(appRootRoutes); 49 | export const GAMES_ROUTING: ModuleWithProviders = RouterModule.forChild(gameRoutes); 50 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/authenticatedHttp.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Http, RequestOptionsArgs, Response, Headers} from '@angular/http'; 3 | import {Observable} from 'rxjs/Observable'; 4 | 5 | import {TokenService} from './tokenService'; 6 | 7 | @Injectable() 8 | export class AuthenticatedHttp { 9 | constructor(private _http: Http, 10 | private _tokenService: TokenService) { 11 | } 12 | 13 | request(url: string, options?: RequestOptionsArgs): Observable { 14 | options = this.prepareOptions(options); 15 | return this._http.request(url, options); 16 | } 17 | 18 | get(url: string, options?: RequestOptionsArgs): Observable { 19 | options = this.prepareOptions(options); 20 | return this._http.get(url, options); 21 | } 22 | 23 | post(url: string, body: string, options?: RequestOptionsArgs): Observable { 24 | options = this.prepareOptions(options); 25 | return this._http.post(url, body, options); 26 | } 27 | 28 | put(url: string, body: string, options?: RequestOptionsArgs): Observable { 29 | options = this.prepareOptions(options); 30 | return this._http.put(url, body, options); 31 | } 32 | 33 | delete(url: string, options?: RequestOptionsArgs): Observable { 34 | options = this.prepareOptions(options); 35 | return this._http.delete(url, options); 36 | } 37 | 38 | patch(url: string, body: string, options?: RequestOptionsArgs): Observable { 39 | options = this.prepareOptions(options); 40 | return this._http.patch(url, body, options); 41 | } 42 | 43 | head(url: string, options?: RequestOptionsArgs): Observable { 44 | options = this.prepareOptions(options); 45 | return this._http.head(url, options); 46 | } 47 | 48 | protected prepareOptions(options: RequestOptionsArgs): RequestOptionsArgs { 49 | let token = this._tokenService.token; 50 | 51 | if (token) { 52 | options = options || {}; 53 | 54 | if (!options.headers) { 55 | options.headers = new Headers(); 56 | } 57 | options.headers.append('Authorization', 'Bearer ' + token); 58 | } 59 | 60 | return options; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/cameraService.ts: -------------------------------------------------------------------------------- 1 | import {Observable} from 'rxjs/Observable'; 2 | 3 | export interface ICameraService { 4 | getPhoto(): Observable; 5 | } 6 | 7 | export abstract class CameraService implements ICameraService { 8 | public abstract getPhoto(): Observable; 9 | } 10 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/desktopCameraService.ts: -------------------------------------------------------------------------------- 1 | import {Observable} from 'rxjs/Rx'; 2 | 3 | import {ICameraService} from './cameraService'; 4 | 5 | declare let window; 6 | 7 | export class DesktopCameraService implements ICameraService { 8 | 9 | private getMediaDevices(): any { 10 | const mediaDevices = ((window.navigator.mozGetUserMedia || window.navigator.webkitGetUserMedia) ? { 11 | getUserMedia: function (options) { 12 | return new Promise((resolve, reject) => { 13 | (window.navigator.mozGetUserMedia || 14 | window.navigator.webkitGetUserMedia).call(window.navigator, options, resolve, reject); 15 | }); 16 | } 17 | } : null) || window.navigator.mediaDevices; 18 | 19 | return mediaDevices; 20 | } 21 | 22 | public getPhoto(): Observable { 23 | return Observable.fromPromise( 24 | this.getMediaDevices().getUserMedia({ video: true, audio: false }) 25 | .then((stream: any) => { 26 | return new Promise((resolve, reject) => { 27 | try { 28 | let vendorURL = window.URL || window.webkitURL; 29 | const doc = document; 30 | let videoElement = doc.createElement('video'); 31 | videoElement.src = vendorURL.createObjectURL(stream); 32 | videoElement.play(); 33 | 34 | videoElement.addEventListener('canplay', () => { 35 | let canvasElement = doc.createElement('canvas'); 36 | canvasElement.setAttribute('width', videoElement.videoWidth.toString()); 37 | canvasElement.setAttribute('height', videoElement.videoHeight.toString()); 38 | 39 | // Wait a bit before taking a screenshot so the camera has time to adjust lights 40 | setTimeout(() => { 41 | let context = canvasElement.getContext('2d'); 42 | context.drawImage(videoElement, 0, 0, videoElement.videoWidth, videoElement.videoHeight); 43 | 44 | const url = canvasElement.toDataURL('image/png'); 45 | 46 | videoElement.pause(); 47 | 48 | if (stream.stop) { 49 | stream.stop(); 50 | } 51 | 52 | if (stream.getAudioTracks) { 53 | stream.getAudioTracks().forEach((track: any) => { 54 | track.stop(); 55 | }); 56 | } 57 | 58 | if (stream.getVideoTracks) { 59 | stream.getVideoTracks().forEach((track: any) => { 60 | track.stop(); 61 | }); 62 | } 63 | 64 | resolve(url); 65 | }, 500); 66 | }); 67 | } 68 | catch (e) { 69 | reject(e); 70 | } 71 | }); 72 | 73 | } 74 | )); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/gamesService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Headers} from '@angular/http'; 3 | import {Observable} from 'rxjs/Observable'; 4 | 5 | import {AuthenticatedHttp} from './authenticatedHttp'; 6 | import {Game} from '../models/game'; 7 | import {ApiConfig} from '../apiConfig'; 8 | 9 | @Injectable() 10 | export class GamesService { 11 | constructor(private _http: AuthenticatedHttp, private _config: ApiConfig) { 12 | } 13 | 14 | private getRequestOptions() { 15 | let headers = new Headers(); 16 | headers.append('Accept', 'application/json'); 17 | headers.append('Accept', 'text/plain'); 18 | headers.append('Accept', '*/*'); 19 | headers.append('Content-Type', 'application/json;charset=UTF-8'); 20 | 21 | return { headers: headers }; 22 | } 23 | 24 | private buildUrl(appendix: string): string { 25 | return `${this._config.rootUrl}${appendix}`; 26 | } 27 | 28 | public getAll(): Observable { 29 | return this._http.get(this.buildUrl('api/boardgames/list')).map(response => (response.json())); 30 | } 31 | 32 | public getGameCount(): Observable { 33 | return this.getAll().map(games => games.length); 34 | } 35 | 36 | public getById(id: string): Observable { 37 | return this._http.get(this.buildUrl(`api/boardgames/single?id=${id}`)) 38 | .map(response => response.json()); 39 | } 40 | 41 | public addGame(game: Game): Observable { 42 | return this._http.post(this.buildUrl(`api/boardgames/add`), JSON.stringify(game), this.getRequestOptions()) 43 | .map(response => response.json()); 44 | } 45 | 46 | public updateGame(game: Game): Observable { 47 | return this._http.put(this.buildUrl(`api/boardgames/update`), JSON.stringify(game), this.getRequestOptions()) 48 | .map(response => game.id); 49 | } 50 | 51 | public deleteGame(id: string): Observable { 52 | return this._http.delete(this.buildUrl(`api/boardgames/remove?id=${id}`)) 53 | .map(response => response.text()); 54 | } 55 | 56 | public deepClone(game: Game): Game { 57 | return JSON.parse(JSON.stringify(game)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/geolocationService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | 3 | import {GeoLocation} from '../models/geoLocation'; 4 | 5 | @Injectable() 6 | export class GeolocationService { 7 | public locate() { 8 | return new Promise((resolve, reject) => { 9 | if (window.navigator && window.navigator.geolocation) { 10 | window.navigator.geolocation.getCurrentPosition((pos) => { 11 | resolve(new GeoLocation(pos.coords.latitude, pos.coords.longitude, 16)); 12 | }, (err) => { 13 | reject(err); 14 | }, { 15 | enableHighAccuracy: false, 16 | timeout: 5000, 17 | maximumAge: 0 18 | }); 19 | } else { 20 | reject('This platform does not support geolocation.'); 21 | } 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/logService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | 3 | import {LogLevel} from '../models/logLevel'; 4 | 5 | @Injectable() 6 | export class LogService { 7 | public defaultLogLevel: LogLevel = LogLevel.Info; 8 | public maximumLogLevel: LogLevel = LogLevel.Warning; 9 | 10 | public log(message: string, logLevel?: LogLevel): void { 11 | if (!logLevel) { 12 | logLevel = this.defaultLogLevel; 13 | } 14 | 15 | if (logLevel > this.maximumLogLevel) { 16 | return; 17 | } 18 | 19 | this.doLog(this.formatMessage(logLevel, message)); 20 | } 21 | 22 | public logVerbose(message: string): void { 23 | this.log(message, LogLevel.Verbose); 24 | } 25 | 26 | public logDebug(message: string): void { 27 | this.log(message, LogLevel.Debug); 28 | } 29 | 30 | public logInfo(message: string): void { 31 | this.log(message, LogLevel.Info); 32 | } 33 | 34 | public logWarning(message: string): void { 35 | this.log(message, LogLevel.Warning); 36 | } 37 | 38 | public logError(message: string): void { 39 | this.log(message, LogLevel.Error); 40 | } 41 | 42 | public logCritical(message: string): void { 43 | this.log(message, LogLevel.Critical); 44 | } 45 | 46 | protected doLog(formattedMessage: string): void { 47 | // here to be overriden 48 | } 49 | 50 | protected getIsoDate(): string { 51 | return new Date().toISOString(); 52 | } 53 | 54 | protected getLogLevelName(logLevel: LogLevel): string { 55 | return LogLevel[logLevel]; 56 | } 57 | 58 | protected formatMessage(logLevel: LogLevel, message: string): string { 59 | return this.getIsoDate() + ' [' + this.getLogLevelName(logLevel) + ']: ' + message; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/loginService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Http, Headers, RequestOptions} from '@angular/http'; 3 | import {Router} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | import {TokenService} from './tokenService'; 7 | import {ApiConfig} from '../apiConfig'; 8 | import {LogService} from './logService'; 9 | import {TokenData} from '../models/tokenData'; 10 | import {SignalRService} from './signalrService'; 11 | 12 | @Injectable() 13 | export class LoginService { 14 | private _lastLoginUnsuccessful: boolean; 15 | 16 | get isAuthenticated(): boolean { 17 | return this._tokenService.token !== null; 18 | } 19 | 20 | get username(): string { 21 | return this._tokenService.username; 22 | } 23 | 24 | constructor(private _config: ApiConfig, 25 | private _logService: LogService, 26 | private _http: Http, 27 | private _router: Router, 28 | private _tokenService: TokenService, 29 | private _signalRService: SignalRService) { 30 | this._tokenService.isAuthenticated() 31 | .subscribe((value) => { 32 | if (!value) { 33 | this.logout(); 34 | } 35 | }); 36 | } 37 | 38 | /** 39 | * Logout the current user (remove token and navigate to unprotected route) 40 | */ 41 | public logout(routeToLogin: boolean = true): void { 42 | this._logService.logDebug('LoginService.logout called'); 43 | 44 | this._signalRService.stop(); 45 | this._lastLoginUnsuccessful = false; 46 | this._tokenService.token = null; 47 | 48 | if (routeToLogin) { 49 | this._router.navigate(['/login']); 50 | } 51 | } 52 | 53 | /** 54 | * Login the user by her username and password 55 | * @param username 56 | * @param password 57 | * @returns {Subject} 58 | */ 59 | public login(username: string, password: string): Observable { 60 | this.logout(false); 61 | 62 | let body = 'grant_type=password&username=' + username + '&password=' + password, 63 | options = new RequestOptions({ headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }) }); 64 | 65 | return Observable.create((observer) => { 66 | this._http.post(this._config.rootUrl + 'token', body, options) 67 | .map(response => response.json()) 68 | .subscribe( 69 | (tokenData) => { 70 | this.saveToken(tokenData.access_token); 71 | this._tokenService.username = username; 72 | 73 | let expiryDate = new Date(); 74 | expiryDate.setSeconds(expiryDate.getSeconds() + tokenData.expires_in); 75 | this._tokenService.tokenExpiry = expiryDate; 76 | observer.next(tokenData); 77 | }, 78 | (error) => observer.error(error), 79 | () => observer.complete() 80 | ); 81 | }); 82 | } 83 | 84 | handleError(error: TokenData) { 85 | this._logService.logDebug('LoginService encountered an error: ' + error); 86 | this._lastLoginUnsuccessful = true; 87 | } 88 | 89 | saveToken(token: string): void { 90 | this._logService.logVerbose('LoginService.saveToken: Saving token ' + token); 91 | this._lastLoginUnsuccessful = false; 92 | this._tokenService.token = token; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/mobileCameraService.ts: -------------------------------------------------------------------------------- 1 | import {Observable} from 'rxjs/Rx'; 2 | import {Observer} from 'rxjs/Rx'; 3 | 4 | import {ICameraService} from './cameraService'; 5 | 6 | declare let window; 7 | 8 | export class MobileCameraService implements ICameraService { 9 | public getPhoto(): Observable { 10 | return Observable.create((observer: Observer) => { 11 | let removeDomListener = () => { 12 | document.removeEventListener('deviceready', onCordovaDeviceReady); 13 | }; 14 | 15 | let onCordovaDeviceReady = () => { 16 | const camera = window.navigator.camera; 17 | 18 | let options = { 19 | quality: 50, 20 | destinationType: camera.DestinationType.DATA_URL, 21 | sourceType: camera.PictureSourceType.CAMERA, 22 | encodingType: camera.EncodingType.PNG, 23 | saveToPhotoAlbum: false, 24 | correctOrientation: true 25 | }; 26 | 27 | camera.getPicture(imageData => { 28 | observer.next('data:image/png;base64,' + imageData); 29 | removeDomListener(); 30 | observer.complete(); 31 | }, error => { 32 | observer.error(error); 33 | removeDomListener(); 34 | observer.complete(); 35 | }, options); 36 | }; 37 | 38 | document.addEventListener('deviceready', onCordovaDeviceReady); 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/nativeIntegrationService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Router} from '@angular/router'; 3 | 4 | import {PlatformInformationService} from './platformInformationService'; 5 | import {IBoardZAppWindow} from '../interfaces/boardzAppWindow'; 6 | 7 | declare var window: IBoardZAppWindow; 8 | 9 | @Injectable() 10 | export class NativeIntegrationService { 11 | constructor(private _router: Router, 12 | private _platformInformationService: PlatformInformationService) { 13 | } 14 | 15 | public registerNavigationHook() { 16 | 17 | if (this._platformInformationService.isDesktop) { 18 | /** 19 | * Brave fighters, you did dare to the deepest depths and slain mighty beasts. 20 | * But the greatest evil you have to overcome yet, armed with the worst, poisonous 21 | * weapons and disguised as well-known methods is SystemJS challenge you life and death. 22 | * 23 | * May the force be with you! 24 | */ 25 | 26 | // systemJS is trying to require electron if you call it without explicitly calling it on window :facepalm: 27 | window.require('electron').ipcRenderer.on('navigateTo', (event, data) => { 28 | this._router.navigate([data]); 29 | }); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/notificationService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Subject} from 'rxjs/Subject'; 3 | 4 | import {LogService} from './logService'; 5 | import {Notification} from '../models/notification'; 6 | import {NotificationType} from '../models/notificationType'; 7 | 8 | @Injectable() 9 | export class NotificationService { 10 | public notifications: Subject = new Subject(); 11 | 12 | constructor(private _logService: LogService) { 13 | } 14 | 15 | public notify(notification: Notification) { 16 | if (!notification.message) { 17 | return; 18 | } 19 | 20 | this._logService.logDebug('NotificationService.notify received notification: ' + JSON.stringify(notification)); 21 | this.notifications.next(notification); 22 | } 23 | 24 | public notifyInformation(message: string) { 25 | this.notify( 26 | new Notification(message, NotificationType.Information) 27 | ); 28 | } 29 | 30 | public notifySuccess(message: string) { 31 | this.notify( 32 | new Notification(message, NotificationType.Success) 33 | ); 34 | } 35 | 36 | public notifyWarning(message: string) { 37 | this.notify( 38 | new Notification(message, NotificationType.Warning) 39 | ); 40 | } 41 | 42 | public notifyError(message: string) { 43 | this.notify( 44 | new Notification(message, NotificationType.Error) 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/platformInformationService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | 3 | declare let window; 4 | 5 | @Injectable() 6 | export class PlatformInformationService { 7 | private _isMobile: boolean; 8 | private _isDesktop: boolean; 9 | private _isWeb: boolean; 10 | 11 | public get isMobile(): boolean { 12 | return this._isMobile; 13 | } 14 | 15 | public get isDesktop(): boolean { 16 | return this._isDesktop; 17 | } 18 | 19 | public get isWeb(): boolean { 20 | return this._isWeb; 21 | } 22 | 23 | constructor() { 24 | this.guessPlatform(); 25 | } 26 | 27 | private guessPlatform(): void { 28 | this._isMobile = !!window.cordova; 29 | this._isDesktop = window.navigator.userAgent.match(/Electron/) !== null; 30 | this._isWeb = !(this._isMobile || this._isDesktop); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/playersService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Headers} from '@angular/http'; 3 | import {Observable} from 'rxjs/Observable'; 4 | 5 | import {GeoLocation} from '../models/geoLocation'; 6 | import {AuthenticatedHttp} from './authenticatedHttp'; 7 | import {Player} from '../models/player'; 8 | import {NearByPlayer} from '../models/nearbyPlayer'; 9 | import {ApiConfig} from '../apiConfig'; 10 | 11 | @Injectable() 12 | export class PlayersService { 13 | constructor(private _http: AuthenticatedHttp, private _config: ApiConfig) { 14 | } 15 | 16 | private getRequestOptions() { 17 | let headers = new Headers(); 18 | headers.append('Accept', 'application/json'); 19 | headers.append('Accept', 'text/plain'); 20 | headers.append('Accept', '*/*'); 21 | headers.append('Content-Type', 'application/json;charset=UTF-8'); 22 | 23 | return { headers: headers }; 24 | } 25 | 26 | private buildUrl(appendix: string): string { 27 | return `${this._config.rootUrl}${appendix}`; 28 | } 29 | 30 | public getAll(): Observable { 31 | return this._http.get(this.buildUrl('api/players/list')).map(response => (response.json())); 32 | } 33 | 34 | public getById(id: string): Observable { 35 | return this._http.get(this.buildUrl(`api/players/single?id=${id}`)).map(response => response.json()); 36 | } 37 | 38 | public getPlayerCount(): Observable { 39 | return this._http.get(this.buildUrl('api/players/playercount')).map(r => r.json()); 40 | } 41 | 42 | public findNearby(radius: number, coordinates: GeoLocation): Observable { 43 | return this._http.get(this.buildUrl(`api/players/FindNearby?radius=${radius}&coordinate.latitude=${coordinates.latitude}&coordinate.longitude=${coordinates.longitude}`)) 44 | .map(r => { 45 | return r.json(); 46 | }); 47 | } 48 | 49 | public add(player: Player): Observable { 50 | return this._http.post(this.buildUrl(`api/players/add`), JSON.stringify(player), this.getRequestOptions()) 51 | .map(response => response.json()); 52 | } 53 | 54 | public update(player: any): Observable { 55 | return this._http.put(this.buildUrl(`api/players/update`), JSON.stringify(player), this.getRequestOptions()) 56 | .map(response => player.id); 57 | } 58 | 59 | public delete(id: string): Observable { 60 | return this._http.delete(this.buildUrl(`api/players/remove?id=${id}`)) 61 | .map(response => response.text()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/signalrService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable, EventEmitter} from '@angular/core'; 2 | 3 | import {ApiConfig} from '../apiConfig'; 4 | import {LogService} from './logService'; 5 | import {TokenService} from './tokenService'; 6 | 7 | declare var $; 8 | 9 | @Injectable() 10 | export class SignalRService { 11 | private _hubConnection; 12 | private _connection; 13 | private _playerProxy; 14 | 15 | public someoneJoinedAGame: EventEmitter = new EventEmitter(); 16 | 17 | constructor(private _configuration: ApiConfig, 18 | private _tokenService: TokenService, 19 | private _logService: LogService) { 20 | this._hubConnection = $.hubConnection; 21 | } 22 | 23 | public sendIAmGaming(game: string): void { 24 | if (!this._connection) { 25 | return; 26 | } 27 | 28 | this._playerProxy.invoke('iAmPlaying', game); 29 | } 30 | 31 | public start(): void { 32 | if (this._connection || !this._tokenService.token) { 33 | return; 34 | } 35 | 36 | this._connection = this._hubConnection(`${this._configuration.rootUrl}signalr`); 37 | this._connection.qs = { 'authorization': this._tokenService.token }; 38 | this._playerProxy = this._connection.createHubProxy('playerHub'); 39 | 40 | this._playerProxy.on('someoneStartedPlaying', (username, game) => { 41 | let msg = `${username} started playing ${game}.`; 42 | this._logService.logDebug(`Received SignalR message: ${msg}`); 43 | this.someoneJoinedAGame.emit(msg); 44 | }); 45 | 46 | this._connection.start() 47 | .done(() => this._logService.logDebug('SignalR connection established.')) 48 | .fail(() => this._logService.logError('SignalR connection not established.')); 49 | } 50 | 51 | public stop(): void { 52 | if (this._connection) { 53 | this._connection.stop(); 54 | } 55 | 56 | this._connection = undefined; 57 | this._playerProxy = undefined; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/tokenService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Observable} from 'rxjs/Observable'; 3 | 4 | import {LogService} from './logService'; 5 | 6 | const tokenKey: string = 'Authentication::Token'; 7 | const usernameKey: string = 'Authentication::Username'; 8 | const expiryKey: string = 'Authentication::TokenExpiration'; 9 | 10 | @Injectable() 11 | export class TokenService { 12 | private _authenticated: boolean; 13 | 14 | constructor(private _logService: LogService) { 15 | let token = this.token; 16 | 17 | if ((typeof token !== 'undefined') && (token !== null)) { 18 | this._authenticated = true; 19 | } 20 | } 21 | 22 | public get token(): string { 23 | let token = localStorage.getItem(tokenKey); 24 | this._logService.logVerbose('TokenService: Retrieved token: ' + token); 25 | 26 | return token; 27 | } 28 | 29 | public set token(token: string) { 30 | this._logService.logVerbose('TokenService: Setting token: ' + token); 31 | 32 | if (token === null) { 33 | localStorage.removeItem(tokenKey); 34 | this.username = null; 35 | this.tokenExpiry = null; 36 | this._authenticated = false; 37 | } else { 38 | localStorage.setItem(tokenKey, token); 39 | this._authenticated = true; 40 | } 41 | } 42 | 43 | public get username(): string { 44 | let username = localStorage.getItem(usernameKey); 45 | this._logService.logVerbose('TokenService: Retrieved user name: ' + username); 46 | 47 | return username; 48 | } 49 | 50 | public set username(username: string) { 51 | this._logService.logVerbose('TokenService: Setting user name: ' + username); 52 | 53 | if (username === null) { 54 | localStorage.removeItem(usernameKey); 55 | } else { 56 | localStorage.setItem(usernameKey, username); 57 | } 58 | } 59 | 60 | public get tokenExpiry(): Date { 61 | let value = localStorage.getItem(expiryKey); 62 | this._logService.logVerbose('TokenService: Retrieved token expiry: ' + value); 63 | 64 | return (value !== null) ? new Date(value) : null; 65 | } 66 | 67 | public set tokenExpiry(expiryDate: Date) { 68 | this._logService.logVerbose('TokenService: Setting token expiry: ' + expiryDate); 69 | 70 | if (expiryDate === null) { 71 | localStorage.removeItem(expiryKey); 72 | } else { 73 | localStorage.setItem(expiryKey, expiryDate.toISOString()); 74 | } 75 | } 76 | 77 | public isAuthenticated(): Observable { 78 | return Observable.of(this._authenticated); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/BoardZ/app/services/uiNotificationService.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | 3 | import {NotificationService} from './notificationService'; 4 | import {Notification} from '../models/notification'; 5 | import {NotificationType} from '../models/notificationType'; 6 | 7 | declare var PNotify; 8 | 9 | @Injectable() 10 | export class UiNotificationService { 11 | private _notificationTypeMap = {}; 12 | 13 | constructor(private _notificationService: NotificationService) { 14 | this._notificationTypeMap[NotificationType.Information] = 'info'; 15 | this._notificationTypeMap[NotificationType.Error] = 'error'; 16 | this._notificationTypeMap[NotificationType.Warning] = 'notice'; 17 | this._notificationTypeMap[NotificationType.Success] = 'success'; 18 | } 19 | 20 | public subscribeToNotifications(): void { 21 | this._notificationService.notifications.subscribe((notification: Notification) => { 22 | this.showUiNotification(notification); 23 | }); 24 | } 25 | 26 | private showUiNotification(notification: Notification): void { 27 | const type = this.notificationTypeToPNotifyType(notification.type); 28 | 29 | const settings = { 30 | styling: 'bootstrap3', 31 | title: type[0].toUpperCase() + type.substr(1), 32 | text: notification.message, 33 | type: type, 34 | addclass: 'stack-bar-top', 35 | cornerclass: '', 36 | width: '100%', 37 | delay: 1500 38 | }; 39 | 40 | new PNotify(settings); 41 | } 42 | 43 | private notificationTypeToPNotifyType(type: NotificationType): string { 44 | return this._notificationTypeMap[type] || 'notice'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/BoardZ/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/assets/favicon.ico -------------------------------------------------------------------------------- /src/BoardZ/assets/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/assets/images/layers-2x.png -------------------------------------------------------------------------------- /src/BoardZ/assets/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/assets/images/layers.png -------------------------------------------------------------------------------- /src/BoardZ/assets/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/assets/images/marker-icon-2x.png -------------------------------------------------------------------------------- /src/BoardZ/assets/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/assets/images/marker-icon.png -------------------------------------------------------------------------------- /src/BoardZ/assets/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/assets/images/marker-shadow.png -------------------------------------------------------------------------------- /src/BoardZ/cordova.js: -------------------------------------------------------------------------------- 1 | // just a placeholder -------------------------------------------------------------------------------- /src/BoardZ/css/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | -webkit-user-select: none; 3 | -moz-user-select: none; 4 | -ms-user-select: none; 5 | user-select: none; 6 | cursor: default; 7 | } 8 | 9 | .ng-valid[required]{ 10 | border-right: 3px solid #42A948; 11 | } 12 | 13 | input.ng-invalid, 14 | select.ng-invalid, 15 | textarea.ng-invalid { 16 | border-right: 3px solid indianred; 17 | } 18 | 19 | .respond-click { 20 | cursor: pointer; 21 | -webkit-app-region: no-drag; 22 | } 23 | 24 | button, a{ 25 | -webkit-app-region: no-drag; 26 | } 27 | 28 | .danger { 29 | color: indianred; 30 | } 31 | .alert.alert-danger{ 32 | padding-top: 15px !important; 33 | margin-top:3px !important; 34 | } 35 | .stack-bar-top { 36 | top: 0; 37 | right: 0; 38 | } 39 | 40 | .big-space { 41 | margin-top: 30px; 42 | } 43 | 44 | .content-wrapper { 45 | overflow-y: scroll; 46 | -webkit-overflow-scrolling: touch; 47 | } 48 | 49 | /* Navigation */ 50 | body .navbar-custom-menu [hidden="true"], .hidden { 51 | display: none; 52 | } 53 | 54 | 55 | body, 56 | .wrapper { 57 | overflow-x: hidden; 58 | position: relative; 59 | } 60 | 61 | .wrapper { 62 | overflow-y: scroll; 63 | -webkit-overflow-scrolling: touch; 64 | } 65 | -------------------------------------------------------------------------------- /src/BoardZ/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BoardZ2 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/BoardZ/system.setup.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular 2. 3 | */ 4 | (function (global) { 5 | // map tells the System loader where to look for things 6 | var map = { 7 | 'app': 'app', // 'dist', 8 | '@angular/core': 'ng:core/bundles/core.umd.js', 9 | '@angular/common': 'ng:common/bundles/common.umd.js', 10 | '@angular/compiler': 'ng:compiler/bundles/compiler.umd.js', 11 | '@angular/platform-browser': 'ng:platform-browser/bundles/platform-browser.umd.js', 12 | '@angular/platform-browser-dynamic': 'ng:platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 13 | '@angular/http': 'ng:http/bundles/http.umd.js', 14 | '@angular/router': 'ng:router/bundles/router.umd.js', 15 | '@angular/forms': 'ng:forms/bundles/forms.umd.js', 16 | 'rxjs': 'rxjs', 17 | 'jquery': 'scripts/bundles/jquery-2.1.4.js', 18 | 'bootstrap/js/bootstrap': 'scripts/bundles/bootstrap.js', 19 | 'admin-lte/js/app': 'scripts/bundles/app.js', 20 | 'jquery/jquery.hammer': 'scripts/bundles/jquery.hammer.js', 21 | 'hammerjs': 'scripts/bundles/hammer.js', 22 | 'hammerjs/hammer': 'scripts/bundles/hammer.js', 23 | 'jquery/jquery.slimscroll': 'scripts/bundles/jquery.slimscroll.js', 24 | 'pnotify': 'scripts/bundles/pnotify.custom.js', 25 | 'pNotify/pnotify-adapter': 'scripts/bundles/pnotify-adapter.js', 26 | 'signalr/signalr': 'scripts/bundles/signalr.js', 27 | 'leaflet/leaflet': 'scripts/bundles/leaflet-src.js', 28 | 'fastclick/fastclick': 'scripts/bundles/fastclick.js' 29 | }; 30 | // packages tells the System loader how to load when no filename and/or no extension 31 | var packages = { 32 | 'app': { main: 'main.js', defaultExtension: 'js' }, 33 | 'rxjs': { defaultExtension: 'js' } 34 | }; 35 | 36 | var config = { 37 | paths: { 38 | 'ng:': '@angular/' 39 | }, 40 | map: map, 41 | packages: packages 42 | } 43 | System.config(config); 44 | })(this); 45 | 46 | function backupModule() { 47 | return new Promise(function (resolve, reject) { 48 | if (typeof module !== 'undefined' && module.hasOwnProperty('exports')) { 49 | window.module = module; 50 | module = undefined; 51 | } 52 | console.log('mod backuped'); 53 | resolve(true); 54 | }); 55 | } 56 | 57 | function restoreModule() { 58 | return new Promise(function (resolve, reject) { 59 | if (window.hasOwnProperty('module')) { 60 | module = window.module; 61 | } 62 | console.log('mod restored'); 63 | resolve(true); 64 | }); 65 | } 66 | 67 | backupModule() 68 | .then(function () { 69 | // return System.import('jquery'); 70 | }) 71 | .then(function () { 72 | return restoreModule(); 73 | }) 74 | .then(function () { 75 | return System.import('app/main'); 76 | }) 77 | .then(null, console.error.bind(console)); 78 | 79 | -------------------------------------------------------------------------------- /src/BoardZ/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/BoardZ/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/BoardZ/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/BoardZ/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/BoardZ/vendor/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/vendor/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /src/BoardZ/vendor/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/vendor/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/BoardZ/vendor/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/vendor/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/BoardZ/vendor/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/vendor/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/BoardZ/vendor/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinktecture/boardz-cross-platform-sample/a7fe7a65bfcef0fdd68d3ddcd3e1e45b572c5ed3/src/BoardZ/vendor/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /src/BoardZ/vendor/jquery/jquery.hammer.js: -------------------------------------------------------------------------------- 1 | (function(factory) { 2 | if (typeof define === 'function' && define.amd) { 3 | define(['jquery', 'hammerjs'], factory); 4 | } else if (typeof exports === 'object') { 5 | factory(require('jquery'), require('hammerjs')); 6 | } else { 7 | factory(jQuery, Hammer); 8 | } 9 | }(function($, Hammer) { 10 | function hammerify(el, options) { 11 | var $el = $(el); 12 | if(!$el.data("hammer")) { 13 | $el.data("hammer", new Hammer($el[0], options)); 14 | } 15 | } 16 | 17 | $.fn.hammer = function(options) { 18 | return this.each(function() { 19 | hammerify(this, options); 20 | }); 21 | }; 22 | 23 | // extend the emit method to also trigger jQuery events 24 | Hammer.Manager.prototype.emit = (function(originalEmit) { 25 | return function(type, data) { 26 | originalEmit.call(this, type, data); 27 | $(this.element).trigger({ 28 | type: type, 29 | gesture: data 30 | }); 31 | }; 32 | })(Hammer.Manager.prototype.emit); 33 | })); 34 | -------------------------------------------------------------------------------- /src/BoardZ/vendor/pNotify/pnotify-adapter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var pNotify = require('pnotify'); 4 | 5 | window.PNotify = pNotify; 6 | -------------------------------------------------------------------------------- /src/BoardZ/vendor/pNotify/pnotify.custom.css: -------------------------------------------------------------------------------- 1 | /* PNotify modules included in this custom build file: 2 | mobile 3 | */ 4 | /* 5 | Author : Hunter Perrin 6 | Version : 3.0.0 7 | Link : http://sciactive.com/pnotify/ 8 | */ 9 | /* -- Notice */ 10 | .ui-pnotify { 11 | top: 36px; 12 | right: 36px; 13 | position: absolute; 14 | height: auto; 15 | z-index: 2; 16 | } 17 | body > .ui-pnotify { 18 | /* Notices in the body context should be fixed to the viewport. */ 19 | position: fixed; 20 | /* Ensures notices are above everything */ 21 | z-index: 100040; 22 | } 23 | .ui-pnotify-modal-overlay { 24 | background-color: rgba(0, 0, 0, .4); 25 | top: 0; 26 | left: 0; 27 | position: absolute; 28 | height: 100%; 29 | width: 100%; 30 | z-index: 1; 31 | } 32 | body > .ui-pnotify-modal-overlay { 33 | position: fixed; 34 | z-index: 100039; 35 | } 36 | .ui-pnotify.ui-pnotify-in { 37 | display: block !important; 38 | } 39 | .ui-pnotify.ui-pnotify-move { 40 | transition: left .5s ease, top .5s ease, right .5s ease, bottom .5s ease; 41 | } 42 | .ui-pnotify.ui-pnotify-fade-slow { 43 | transition: opacity .6s linear; 44 | opacity: 0; 45 | } 46 | .ui-pnotify.ui-pnotify-fade-slow.ui-pnotify.ui-pnotify-move { 47 | transition: opacity .6s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease; 48 | } 49 | .ui-pnotify.ui-pnotify-fade-normal { 50 | transition: opacity .4s linear; 51 | opacity: 0; 52 | } 53 | .ui-pnotify.ui-pnotify-fade-normal.ui-pnotify.ui-pnotify-move { 54 | transition: opacity .4s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease; 55 | } 56 | .ui-pnotify.ui-pnotify-fade-fast { 57 | transition: opacity .2s linear; 58 | opacity: 0; 59 | } 60 | .ui-pnotify.ui-pnotify-fade-fast.ui-pnotify.ui-pnotify-move { 61 | transition: opacity .2s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease; 62 | } 63 | .ui-pnotify.ui-pnotify-fade-in { 64 | opacity: 1; 65 | } 66 | .ui-pnotify .ui-pnotify-shadow { 67 | -webkit-box-shadow: 0px 6px 28px 0px rgba(0,0,0,0.1); 68 | -moz-box-shadow: 0px 6px 28px 0px rgba(0,0,0,0.1); 69 | box-shadow: 0px 6px 28px 0px rgba(0,0,0,0.1); 70 | } 71 | .ui-pnotify-container { 72 | background-position: 0 0; 73 | padding: .8em; 74 | height: 100%; 75 | margin: 0; 76 | } 77 | .ui-pnotify-container:after { 78 | content: " "; /* Older browser do not support empty content */ 79 | visibility: hidden; 80 | display: block; 81 | height: 0; 82 | clear: both; 83 | } 84 | .ui-pnotify-container.ui-pnotify-sharp { 85 | -webkit-border-radius: 0; 86 | -moz-border-radius: 0; 87 | border-radius: 0; 88 | } 89 | .ui-pnotify-title { 90 | display: block; 91 | margin-bottom: .4em; 92 | margin-top: 0; 93 | } 94 | .ui-pnotify-text { 95 | display: block; 96 | } 97 | .ui-pnotify-icon, .ui-pnotify-icon span { 98 | display: block; 99 | float: left; 100 | margin-right: .2em; 101 | } 102 | /* Alternate stack initial positioning. */ 103 | .ui-pnotify.stack-topleft, .ui-pnotify.stack-bottomleft { 104 | left: 25px; 105 | right: auto; 106 | } 107 | .ui-pnotify.stack-bottomright, .ui-pnotify.stack-bottomleft { 108 | bottom: 25px; 109 | top: auto; 110 | } 111 | .ui-pnotify.stack-modal { 112 | left: 50%; 113 | right: auto; 114 | margin-left: -150px; 115 | } 116 | .ui-pnotify-container { 117 | position: relative; 118 | left: 0; 119 | } 120 | @media (max-width: 480px) { 121 | /* -- Notice */ 122 | .ui-pnotify-mobile-able.ui-pnotify { 123 | position: fixed; 124 | top: 0; 125 | right: 0; 126 | left: 0; 127 | width: auto !important; 128 | font-size: 1.2em; 129 | -webkit-font-smoothing: antialiased; 130 | -moz-font-smoothing: antialiased; 131 | -ms-font-smoothing: antialiased; 132 | font-smoothing: antialiased; 133 | } 134 | .ui-pnotify-mobile-able.ui-pnotify .ui-pnotify-shadow { 135 | -webkit-box-shadow: none; 136 | -moz-box-shadow: none; 137 | box-shadow: none; 138 | border-bottom-width: 5px; 139 | } 140 | .ui-pnotify-mobile-able .ui-pnotify-container { 141 | -webkit-border-radius: 0; 142 | -moz-border-radius: 0; 143 | border-radius: 0; 144 | } 145 | /* Alternate stack initial positioning. */ 146 | .ui-pnotify-mobile-able.ui-pnotify.stack-topleft, .ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft { 147 | left: 0; 148 | right: 0; 149 | } 150 | .ui-pnotify-mobile-able.ui-pnotify.stack-bottomright, .ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft { 151 | left: 0; 152 | right: 0; 153 | bottom: 0; 154 | top: auto; 155 | } 156 | .ui-pnotify-mobile-able.ui-pnotify.stack-bottomright .ui-pnotify-shadow, .ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft .ui-pnotify-shadow { 157 | border-top-width: 5px; 158 | border-bottom-width: 1px; 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoardGame.Api", "BoardGame.Api\BoardGame.Api.csproj", "{59F84729-1008-495D-9428-35E51EA145D1}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoardGame.Host", "BoardGame.Host\BoardGame.Host.csproj", "{94504A74-C489-4E88-8647-A0EBE29EC66A}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoardGame.WebHost", "BoardGame.WebHost\BoardGame.WebHost.csproj", "{BF141505-C0B1-418B-A73B-74880A667183}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {59F84729-1008-495D-9428-35E51EA145D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {59F84729-1008-495D-9428-35E51EA145D1}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {59F84729-1008-495D-9428-35E51EA145D1}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {59F84729-1008-495D-9428-35E51EA145D1}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {94504A74-C489-4E88-8647-A0EBE29EC66A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {94504A74-C489-4E88-8647-A0EBE29EC66A}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {94504A74-C489-4E88-8647-A0EBE29EC66A}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {94504A74-C489-4E88-8647-A0EBE29EC66A}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {BF141505-C0B1-418B-A73B-74880A667183}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {BF141505-C0B1-418B-A73B-74880A667183}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {BF141505-C0B1-418B-A73B-74880A667183}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {BF141505-C0B1-418B-A73B-74880A667183}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Controllers/BoardGamesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Security.Claims; 4 | using System.Web.Http; 5 | using System.Web.Http.Description; 6 | using BoardGame.Api.Helpers; 7 | using BoardGame.Api.Storages; 8 | 9 | namespace BoardGame.Api.Controllers 10 | { 11 | /// 12 | /// Provides a CRUD api for board games 13 | /// 14 | [Authorize] 15 | public class BoardGamesController : ApiController 16 | { 17 | private readonly IStorage _storage; 18 | 19 | public BoardGamesController(IStorage storage) 20 | { 21 | _storage = storage; 22 | } 23 | 24 | /// 25 | /// Lists all players 26 | /// 27 | /// 28 | [HttpGet] 29 | [ResponseType(typeof(Models.BoardGame[]))] 30 | public IHttpActionResult List() 31 | { 32 | var username = User.GetCurrentUsernameOrThrow(); 33 | return Ok(_storage.List().Where(g => g.UserName == username).ToList()); 34 | } 35 | 36 | /// 37 | /// Returns the games count. 38 | /// 39 | /// 40 | [HttpGet] 41 | [ResponseType(typeof(int))] 42 | public IHttpActionResult GameCount() 43 | { 44 | return Ok(_storage.Count()); 45 | } 46 | 47 | /// 48 | /// Adds a new board game 49 | /// 50 | /// 51 | /// 52 | [HttpPost] 53 | [ResponseType(typeof(Guid))] 54 | public IHttpActionResult Add(Models.BoardGame game) 55 | { 56 | game.UserName = User.GetCurrentUsernameOrThrow(); 57 | var result = _storage.Add(game); 58 | 59 | return Ok(result); 60 | } 61 | 62 | /// 63 | /// Returns a single board game 64 | /// 65 | /// 66 | /// 67 | [HttpGet] 68 | [ResponseType(typeof(Models.BoardGame))] 69 | public IHttpActionResult Single(Guid id) 70 | { 71 | return Ok(_storage.Get(id)); 72 | } 73 | 74 | /// 75 | /// Removes a board game 76 | /// 77 | /// 78 | /// 79 | [HttpDelete] 80 | public IHttpActionResult Remove(Guid id) 81 | { 82 | _storage.Delete(id); 83 | return Ok(); 84 | } 85 | 86 | /// 87 | /// Updates a board game 88 | /// 89 | /// 90 | /// 91 | [HttpPut] 92 | public IHttpActionResult Update(Models.BoardGame game) 93 | { 94 | game.UserName = User.GetCurrentUsernameOrThrow(); 95 | _storage.Update(game); 96 | return Ok(); 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Controllers/PlayersController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Web.Http; 4 | using System.Web.Http.Description; 5 | using BoardGame.Api.Helpers; 6 | using BoardGame.Api.Models; 7 | using BoardGame.Api.Storages; 8 | 9 | namespace BoardGame.Api.Controllers 10 | { 11 | /// 12 | /// Provides an CRUD api for players 13 | /// 14 | [Authorize] 15 | public class PlayersController : ApiController 16 | { 17 | private readonly IStorage _playerStorage; 18 | private readonly IStorage _boardGamesStorage; 19 | private readonly DistanceCalculator _distanceCalculator; 20 | 21 | public PlayersController(IStorage playerStorage, IStorage boardGamesStorage, 22 | DistanceCalculator distanceCalculator) 23 | { 24 | _playerStorage = playerStorage; 25 | _boardGamesStorage = boardGamesStorage; 26 | _distanceCalculator = distanceCalculator; 27 | } 28 | 29 | /// 30 | /// Returns a list of players. 31 | /// 32 | /// 33 | [HttpGet] 34 | [ResponseType(typeof(Player[]))] 35 | public IHttpActionResult List() 36 | { 37 | return Ok(_playerStorage.List()); 38 | } 39 | 40 | /// 41 | /// Returns the playing players count. 42 | /// 43 | /// 44 | [HttpGet] 45 | [ResponseType(typeof(int))] 46 | public IHttpActionResult PlayerCount() 47 | { 48 | return Ok(_playerStorage.Count()); 49 | } 50 | 51 | /// 52 | /// Adds a new player 53 | /// 54 | /// 55 | /// 56 | [HttpPost] 57 | [ResponseType(typeof(Guid))] 58 | public IHttpActionResult Add(Models.Player player) 59 | { 60 | var result = _playerStorage.Add(player); 61 | 62 | return Ok(result); 63 | } 64 | 65 | /// 66 | /// Returns a single player 67 | /// 68 | /// 69 | /// 70 | [HttpGet] 71 | [ResponseType(typeof(Player))] 72 | public IHttpActionResult Single(Guid id) 73 | { 74 | return Ok(_playerStorage.Get(id)); 75 | } 76 | 77 | /// 78 | /// Removes a player 79 | /// 80 | /// 81 | /// 82 | [HttpDelete] 83 | public IHttpActionResult Remove(Guid id) 84 | { 85 | _playerStorage.Delete(id); 86 | return Ok(); 87 | } 88 | 89 | /// 90 | /// Updates a player 91 | /// 92 | /// 93 | /// 94 | [HttpPut] 95 | public IHttpActionResult Update(Models.Player player) 96 | { 97 | _playerStorage.Update(player); 98 | return Ok(); 99 | } 100 | 101 | /// 102 | /// Finds all players nearby a coordinate within the given radius 103 | /// 104 | /// 105 | /// 106 | /// 107 | [HttpGet] 108 | [ResponseType(typeof(PlayerWithDistance[]))] 109 | public IHttpActionResult FindNearby([FromUri] Coordinate coordinate, int radius) 110 | { 111 | var result = _playerStorage.List() 112 | .Where(i => i.Coordinate != null) 113 | .Select(p => 114 | { 115 | try 116 | { 117 | p.BoardGameName = _boardGamesStorage.Get(p.BoardGameId).Name; 118 | } 119 | catch 120 | { 121 | // Silently fail, we didn't get the game. Can occur in dev 122 | } 123 | 124 | return p; 125 | }) 126 | .Select(c => new PlayerWithDistance() 127 | { 128 | Player = c, 129 | Distance = _distanceCalculator.CalculateDistance(coordinate, c.Coordinate) 130 | }) 131 | .Where(c => c.Distance <= radius) 132 | .OrderBy(c => c.Distance) 133 | .ToList(); 134 | 135 | return Ok(result); 136 | } 137 | 138 | private class PlayerWithDistance 139 | { 140 | public Player Player { get; set; } 141 | public double Distance { get; set; } 142 | } 143 | } 144 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Helpers/DistanceCalculator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BoardGame.Api.Models; 3 | 4 | namespace BoardGame.Api.Helpers 5 | { 6 | public class DistanceCalculator 7 | { 8 | /** 9 | * Adapted from http://www.geodatasource.com/developers/c-sharp 10 | **/ 11 | 12 | public double CalculateDistance(Coordinate origin, Coordinate destination) 13 | { 14 | var theta = origin.Longitude - destination.Longitude; 15 | var distance = Math.Sin(Deg2Rad(origin.Latitude)) * 16 | Math.Sin(Deg2Rad(destination.Latitude)) + 17 | Math.Cos(Deg2Rad(origin.Latitude)) * 18 | Math.Cos(Deg2Rad(destination.Latitude)) * 19 | Math.Cos(Deg2Rad(theta)); 20 | 21 | distance = Math.Acos(distance); 22 | distance = Rad2Deg(distance); 23 | distance = distance * 60 * 1.1515; 24 | 25 | // Kilometers 26 | return distance * 1.609344; 27 | } 28 | 29 | internal static double Deg2Rad(double deg) 30 | { 31 | return (deg * Math.PI / 180.0); 32 | } 33 | 34 | internal static double Rad2Deg(double rad) 35 | { 36 | return (rad / Math.PI * 180.0); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Helpers/IPrincipalExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Claims; 3 | using System.Security.Principal; 4 | 5 | namespace BoardGame.Api.Helpers 6 | { 7 | public static class IPrincipalExtensions 8 | { 9 | public static string GetCurrentUsernameOrThrow(this IPrincipal principal) 10 | { 11 | var user = (ClaimsPrincipal) principal; 12 | 13 | if (user == null) 14 | { 15 | throw new Exception("No user found."); 16 | } 17 | 18 | var claim = user.FindFirst(ClaimTypes.NameIdentifier); 19 | 20 | if (claim == null) 21 | { 22 | throw new Exception("Claim not found."); 23 | } 24 | 25 | return claim.Value; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Hubs/IPlayer.cs: -------------------------------------------------------------------------------- 1 | namespace BoardGame.Api.Hubs 2 | { 3 | public interface IPlayer 4 | { 5 | void SomeoneStartedPlaying(string name, string game); 6 | } 7 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Hubs/PlayerHub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BoardGame.Api.Helpers; 3 | using Microsoft.AspNet.SignalR; 4 | 5 | namespace BoardGame.Api.Hubs 6 | { 7 | [Authorize] 8 | public class PlayerHub : Hub 9 | { 10 | public void IAmPlaying(string game) 11 | { 12 | Clients.Others.SomeoneStartedPlaying(Context.User.GetCurrentUsernameOrThrow(), game); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Models/BoardGame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace BoardGame.Api.Models 5 | { 6 | public class BoardGame 7 | { 8 | /// 9 | /// Unique identifier 10 | /// 11 | public Guid Id { get; set; } 12 | 13 | /// 14 | /// Name of the board game 15 | /// 16 | public string Name { get; set; } 17 | 18 | /// 19 | /// Additional description 20 | /// 21 | public string Description { get; set; } 22 | 23 | /// 24 | /// Packshot URLs 25 | /// 26 | public Packshot Packshot { get; set; } 27 | 28 | [JsonIgnore] 29 | public string UserName { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Models/Coordinate.cs: -------------------------------------------------------------------------------- 1 | namespace BoardGame.Api.Models 2 | { 3 | public class Coordinate 4 | { 5 | /// 6 | /// Latitude value 7 | /// 8 | public double Latitude { get; set; } 9 | 10 | /// 11 | /// Longitude value 12 | /// 13 | public double Longitude { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Models/Packshot.cs: -------------------------------------------------------------------------------- 1 | namespace BoardGame.Api.Models 2 | { 3 | public class Packshot 4 | { 5 | public string FrontImageUrl { get; set; } 6 | public string BackImageUrl { get; set; } 7 | public string TopImageUrl { get; set; } 8 | public string LeftImageUrl { get; set; } 9 | public string RightImageUrl { get; set; } 10 | public string BottomImageUrl { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Models/Player.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BoardGame.Api.Controllers; 3 | 4 | namespace BoardGame.Api.Models 5 | { 6 | public class Player 7 | { 8 | /// 9 | /// Unique identifier 10 | /// 11 | public Guid Id { get; set; } 12 | 13 | /// 14 | /// Name of the player 15 | /// 16 | public string Name { get; set; } 17 | 18 | /// 19 | /// Optional coordinate of the player 20 | /// 21 | public Coordinate Coordinate { get; set; } 22 | 23 | /// 24 | /// Current game the player is playing 25 | /// 26 | public Guid BoardGameId { get; set; } 27 | 28 | /// 29 | /// Base64 Image Url (if player did "i am gaming") 30 | /// 31 | public string ImageUrl { get; set; } 32 | 33 | /// 34 | /// Will only be set when using API 35 | /// 36 | public string BoardGameName { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("BoardGame.Api")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BoardGame.Api")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("59f84729-1008-495d-9428-35e51ea145d1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Security/AuthorizationServerProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using System.Threading.Tasks; 3 | using Microsoft.Owin.Security.OAuth; 4 | 5 | namespace BoardGame.Api.Security 6 | { 7 | public class AuthorizationServerProvider : OAuthAuthorizationServerProvider 8 | { 9 | public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 10 | { 11 | context.Validated(); 12 | return base.ValidateClientAuthentication(context); 13 | } 14 | 15 | public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 16 | { 17 | // This is highly secure... :-) 18 | if (context.UserName == context.Password) 19 | { 20 | var claimsIdentity = new ClaimsIdentity(context.Options.AuthenticationType); 21 | claimsIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.UserName)); 22 | context.Validated(claimsIdentity); 23 | } 24 | 25 | return base.GrantResourceOwnerCredentials(context); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Security/SecurityStartup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading.Tasks; 4 | using Microsoft.Owin; 5 | using Microsoft.Owin.Cors; 6 | using Microsoft.Owin.Security.OAuth; 7 | using Owin; 8 | 9 | namespace BoardGame.Api.Security 10 | { 11 | public class SecurityStartup 12 | { 13 | public static void Configuration(IAppBuilder appBuilder) 14 | { 15 | appBuilder.UseCors(CorsOptions.AllowAll); 16 | 17 | appBuilder.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions() 18 | { 19 | TokenEndpointPath = new PathString("/token"), 20 | AccessTokenExpireTimeSpan = TimeSpan.FromDays(365), 21 | AllowInsecureHttp = true, 22 | Provider = new AuthorizationServerProvider() 23 | }); 24 | 25 | appBuilder.Use(typeof(SignalRAuthorizationMiddleware)); 26 | appBuilder.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Security/SignalRAuthorizationMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.Owin; 4 | 5 | namespace BoardGame.Api.Security 6 | { 7 | public class SignalRAuthorizationMiddleware : OwinMiddleware 8 | { 9 | private static string _queryStringName = "authorization"; 10 | private static string _authorizationHeaderName = "Authorization"; 11 | 12 | public SignalRAuthorizationMiddleware(OwinMiddleware next) 13 | : base(next) 14 | { 15 | } 16 | 17 | public override async Task Invoke(IOwinContext context) 18 | { 19 | var authorizationQueryStringValue = context.Request.Query[_queryStringName]; 20 | 21 | if (authorizationQueryStringValue != null && !context.Request.Headers.ContainsKey(_authorizationHeaderName)) 22 | { 23 | context.Request.Headers.Append(_authorizationHeaderName, "Bearer " + authorizationQueryStringValue); 24 | } 25 | 26 | await Next.Invoke(context); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net.Http; 4 | using System.Net.Http.Formatting; 5 | using System.Reflection; 6 | using System.Web.Http; 7 | using System.Web.Http.Cors; 8 | using Autofac; 9 | using Autofac.Integration.WebApi; 10 | using BoardGame.Api.Helpers; 11 | using BoardGame.Api.Security; 12 | using BoardGame.Api.Storages; 13 | using Microsoft.AspNet.SignalR; 14 | using Newtonsoft.Json; 15 | using Newtonsoft.Json.Serialization; 16 | using Owin; 17 | using Swashbuckle.Application; 18 | 19 | namespace BoardGame.Api 20 | { 21 | public class Startup 22 | { 23 | public void Configuration(IAppBuilder appBuilder) 24 | { 25 | var container = CreateAutofacContainer(); 26 | var httpConfiguration = CreateHttpConfiguration(container); 27 | 28 | SecurityStartup.Configuration(appBuilder); 29 | appBuilder.UseWebApi(httpConfiguration); 30 | appBuilder.MapSignalR(); 31 | } 32 | 33 | private IContainer CreateAutofacContainer() 34 | { 35 | var containerBuilder = new ContainerBuilder(); 36 | containerBuilder.RegisterApiControllers(typeof (Startup).Assembly); 37 | 38 | containerBuilder.RegisterType() 39 | .As>() 40 | .SingleInstance(); 41 | 42 | containerBuilder.RegisterType() 43 | .As>() 44 | .SingleInstance(); 45 | 46 | containerBuilder.RegisterType(); 47 | 48 | var container = containerBuilder.Build(); 49 | 50 | return container; 51 | } 52 | 53 | private HttpConfiguration CreateHttpConfiguration(ILifetimeScope lifetimeScope) 54 | { 55 | var httpConfiguration = new HttpConfiguration(); 56 | httpConfiguration.MapHttpAttributeRoutes(); 57 | httpConfiguration.Routes.MapHttpRoute("default", "api/{controller}/{action}"); 58 | 59 | httpConfiguration.Formatters.Clear(); 60 | httpConfiguration.Formatters.Add(new JsonMediaTypeFormatter() 61 | { 62 | SerializerSettings = new JsonSerializerSettings() 63 | { 64 | ContractResolver = new CamelCasePropertyNamesContractResolver() 65 | } 66 | }); 67 | 68 | httpConfiguration.EnableCors(new EnableCorsAttribute("*", "*", "*")); 69 | 70 | httpConfiguration.DependencyResolver = new AutofacWebApiDependencyResolver(lifetimeScope); 71 | 72 | EnableSwashbuckle(httpConfiguration); 73 | 74 | return httpConfiguration; 75 | } 76 | 77 | private void EnableSwashbuckle(HttpConfiguration httpConfiguration) 78 | { 79 | httpConfiguration.EnableSwagger(c => 80 | { 81 | var baseDirectory = AppDomain.CurrentDomain.BaseDirectory; 82 | var commentsFileName = Assembly.GetExecutingAssembly().GetName().Name + ".XML"; 83 | var commentsFile = Path.Combine(baseDirectory, "bin", "App_Data", commentsFileName); 84 | 85 | c.IncludeXmlComments(commentsFile); 86 | c.SingleApiVersion("v1", "BoardGame API"); 87 | }) 88 | .EnableSwaggerUi(); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Storages/BoardGameStorage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using BoardGame = BoardGame.Api.Models.BoardGame; 5 | 6 | namespace BoardGame.Api.Storages 7 | { 8 | public class BoardGameStorage : IStorage 9 | { 10 | private ConcurrentDictionary _storage = new ConcurrentDictionary(); 11 | 12 | public BoardGameStorage() 13 | { 14 | var guid = Guid.NewGuid(); 15 | _storage.TryAdd(guid, new Models.BoardGame() 16 | { 17 | Id = guid, 18 | Name = "Jumanji", 19 | Description = "Crazy board game!" 20 | }); 21 | 22 | guid = Guid.NewGuid(); 23 | _storage.TryAdd(guid, new Models.BoardGame() 24 | { 25 | Id = guid, 26 | Name = "Monopoly", 27 | Description = "24h board game" 28 | }); 29 | 30 | guid = Guid.NewGuid(); 31 | _storage.TryAdd(guid, new Models.BoardGame() 32 | { 33 | Id = guid, 34 | Name = "You don't know, Jack!", 35 | Description = "You really don't" 36 | }); 37 | 38 | guid = Guid.NewGuid(); 39 | _storage.TryAdd(guid, new Models.BoardGame() 40 | { 41 | Id = guid, 42 | Name = "Jenga", 43 | Description = "Let the tower fall." 44 | }); 45 | } 46 | 47 | public Models.BoardGame Get(Guid id) 48 | { 49 | Models.BoardGame game; 50 | if (_storage.TryGetValue(id, out game)) 51 | { 52 | return game; 53 | } 54 | 55 | throw new Exception("Item not found"); 56 | } 57 | 58 | public Guid Add(Models.BoardGame item) 59 | { 60 | item.Id = Guid.NewGuid(); 61 | 62 | if (_storage.TryAdd(item.Id, item)) 63 | { 64 | return item.Id; 65 | } 66 | 67 | throw new Exception("Adding item not possible."); 68 | } 69 | 70 | public void Delete(Guid id) 71 | { 72 | Models.BoardGame game; 73 | if (!_storage.TryRemove(id, out game)) 74 | { 75 | throw new Exception("Removing item not possible"); 76 | } 77 | } 78 | 79 | public void Update(Models.BoardGame item) 80 | { 81 | _storage.TryUpdate(item.Id, item, Get(item.Id)); 82 | } 83 | 84 | public ICollection List() 85 | { 86 | return _storage.Values; 87 | } 88 | 89 | public int Count() 90 | { 91 | return _storage.Count; 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Storages/IStorage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace BoardGame.Api.Storages 6 | { 7 | public interface IStorage 8 | where T: class 9 | { 10 | T Get(Guid id); 11 | Guid Add(T item); 12 | void Delete(Guid id); 13 | void Update(T item); 14 | ICollection List(); 15 | int Count(); 16 | } 17 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/Storages/PlayersStorage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | 5 | namespace BoardGame.Api.Storages 6 | { 7 | public class PlayerStorage : IStorage 8 | { 9 | private ConcurrentDictionary _storage = new ConcurrentDictionary(); 10 | 11 | public Models.Player Get(Guid id) 12 | { 13 | Models.Player game; 14 | if (_storage.TryGetValue(id, out game)) 15 | { 16 | return game; 17 | } 18 | 19 | throw new Exception("Item not found"); 20 | } 21 | 22 | public Guid Add(Models.Player item) 23 | { 24 | item.Id = Guid.NewGuid(); 25 | 26 | if (_storage.TryAdd(item.Id, item)) 27 | { 28 | return item.Id; 29 | } 30 | 31 | throw new Exception("Adding item not possible."); 32 | } 33 | 34 | public void Delete(Guid id) 35 | { 36 | Models.Player game; 37 | if (!_storage.TryRemove(id, out game)) 38 | { 39 | throw new Exception("Removing item not possible"); 40 | } 41 | } 42 | 43 | public void Update(Models.Player item) 44 | { 45 | _storage.TryUpdate(item.Id, item, Get(item.Id)); 46 | } 47 | 48 | public ICollection List() 49 | { 50 | return _storage.Values; 51 | } 52 | 53 | public int Count() 54 | { 55 | return _storage.Count; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/SwaggerUi/CustomAssets/lang/en.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Warning: Deprecated", 6 | "Implementation Notes":"Implementation Notes", 7 | "Response Class":"Response Class", 8 | "Status":"Status", 9 | "Parameters":"Parameters", 10 | "Parameter":"Parameter", 11 | "Value":"Value", 12 | "Description":"Description", 13 | "Parameter Type":"Parameter Type", 14 | "Data Type":"Data Type", 15 | "Response Messages":"Response Messages", 16 | "HTTP Status Code":"HTTP Status Code", 17 | "Reason":"Reason", 18 | "Response Model":"Response Model", 19 | "Request URL":"Request URL", 20 | "Response Body":"Response Body", 21 | "Response Code":"Response Code", 22 | "Response Headers":"Response Headers", 23 | "Hide Response":"Hide Response", 24 | "Headers":"Headers", 25 | "Try it out!":"Try it out!", 26 | "Show/Hide":"Show/Hide", 27 | "List Operations":"List Operations", 28 | "Expand Operations":"Expand Operations", 29 | "Raw":"Raw", 30 | "can't parse JSON. Raw result":"can't parse JSON. Raw result", 31 | "Model Schema":"Model Schema", 32 | "Model":"Model", 33 | "apply":"apply", 34 | "Username":"Username", 35 | "Password":"Password", 36 | "Terms of service":"Terms of service", 37 | "Created by":"Created by", 38 | "See more at":"See more at", 39 | "Contact the developer":"Contact the developer", 40 | "api version":"api version", 41 | "Response Content Type":"Response Content Type", 42 | "fetching resource":"fetching resource", 43 | "fetching resource list":"fetching resource list", 44 | "Explore":"Explore", 45 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Can't read from server. It may not have the appropriate access-control-origin settings.", 47 | "Please specify the protocol for":"Please specify the protocol for", 48 | "Can't read swagger JSON from":"Can't read swagger JSON from", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Finished Loading Resource Information. Rendering Swagger UI", 50 | "Unable to read api":"Unable to read api", 51 | "from path":"from path", 52 | "server returned":"server returned" 53 | }); 54 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/SwaggerUi/CustomAssets/lang/es.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Advertencia: Obsoleto", 6 | "Implementation Notes":"Notas de implementación", 7 | "Response Class":"Clase de la Respuesta", 8 | "Status":"Status", 9 | "Parameters":"Parámetros", 10 | "Parameter":"Parámetro", 11 | "Value":"Valor", 12 | "Description":"Descripción", 13 | "Parameter Type":"Tipo del Parámetro", 14 | "Data Type":"Tipo del Dato", 15 | "Response Messages":"Mensajes de la Respuesta", 16 | "HTTP Status Code":"Código de Status HTTP", 17 | "Reason":"Razón", 18 | "Response Model":"Modelo de la Respuesta", 19 | "Request URL":"URL de la Solicitud", 20 | "Response Body":"Cuerpo de la Respuesta", 21 | "Response Code":"Código de la Respuesta", 22 | "Response Headers":"Encabezados de la Respuesta", 23 | "Hide Response":"Ocultar Respuesta", 24 | "Try it out!":"Pruébalo!", 25 | "Show/Hide":"Mostrar/Ocultar", 26 | "List Operations":"Listar Operaciones", 27 | "Expand Operations":"Expandir Operaciones", 28 | "Raw":"Crudo", 29 | "can't parse JSON. Raw result":"no puede parsear el JSON. Resultado crudo", 30 | "Model Schema":"Esquema del Modelo", 31 | "Model":"Modelo", 32 | "apply":"aplicar", 33 | "Username":"Nombre de usuario", 34 | "Password":"Contraseña", 35 | "Terms of service":"Términos de Servicio", 36 | "Created by":"Creado por", 37 | "See more at":"Ver más en", 38 | "Contact the developer":"Contactar al desarrollador", 39 | "api version":"versión de la api", 40 | "Response Content Type":"Tipo de Contenido (Content Type) de la Respuesta", 41 | "fetching resource":"buscando recurso", 42 | "fetching resource list":"buscando lista del recurso", 43 | "Explore":"Explorar", 44 | "Show Swagger Petstore Example Apis":"Mostrar Api Ejemplo de Swagger Petstore", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.", 46 | "Please specify the protocol for":"Por favor, especificar el protocola para", 47 | "Can't read swagger JSON from":"No se puede leer el JSON de swagger desde", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Finalizada la carga del recurso de Información. Mostrando Swagger UI", 49 | "Unable to read api":"No se puede leer la api", 50 | "from path":"desde ruta", 51 | "server returned":"el servidor retornó" 52 | }); 53 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/SwaggerUi/CustomAssets/lang/pt.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Aviso: Depreciado", 6 | "Implementation Notes":"Notas de Implementação", 7 | "Response Class":"Classe de resposta", 8 | "Status":"Status", 9 | "Parameters":"Parâmetros", 10 | "Parameter":"Parâmetro", 11 | "Value":"Valor", 12 | "Description":"Descrição", 13 | "Parameter Type":"Tipo de parâmetro", 14 | "Data Type":"Tipo de dados", 15 | "Response Messages":"Mensagens de resposta", 16 | "HTTP Status Code":"Código de status HTTP", 17 | "Reason":"Razão", 18 | "Response Model":"Modelo resposta", 19 | "Request URL":"URL requisição", 20 | "Response Body":"Corpo da resposta", 21 | "Response Code":"Código da resposta", 22 | "Response Headers":"Cabeçalho da resposta", 23 | "Headers":"Cabeçalhos", 24 | "Hide Response":"Esconder resposta", 25 | "Try it out!":"Tente agora!", 26 | "Show/Hide":"Mostrar/Esconder", 27 | "List Operations":"Listar operações", 28 | "Expand Operations":"Expandir operações", 29 | "Raw":"Cru", 30 | "can't parse JSON. Raw result":"Falha ao analisar JSON. Resulto cru", 31 | "Model Schema":"Modelo esquema", 32 | "Model":"Modelo", 33 | "apply":"Aplicar", 34 | "Username":"Usuário", 35 | "Password":"Senha", 36 | "Terms of service":"Termos do serviço", 37 | "Created by":"Criado por", 38 | "See more at":"Veja mais em", 39 | "Contact the developer":"Contate o desenvolvedor", 40 | "api version":"Versão api", 41 | "Response Content Type":"Tipo de conteúdo da resposta", 42 | "fetching resource":"busca recurso", 43 | "fetching resource list":"buscando lista de recursos", 44 | "Explore":"Explorar", 45 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin", 47 | "Please specify the protocol for":"Por favor especifique o protocolo", 48 | "Can't read swagger JSON from":"Não é possível ler o JSON Swagger de", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Carregar informação de recurso finalizada. Renderizando Swagger UI", 50 | "Unable to read api":"Não foi possível ler api", 51 | "from path":"do caminho", 52 | "server returned":"servidor retornou" 53 | }); 54 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/SwaggerUi/CustomAssets/lang/ru.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Ворнинг: Депрекейтед", 6 | "Implementation Notes":"Заметки", 7 | "Response Class":"Пример ответа", 8 | "Status":"Статус", 9 | "Parameters":"Параметры", 10 | "Parameter":"Параметр", 11 | "Value":"Значение", 12 | "Description":"Описание", 13 | "Parameter Type":"Тип параметра", 14 | "Data Type":"Тип данных", 15 | "HTTP Status Code":"HTTP код", 16 | "Reason":"Причина", 17 | "Response Model":"Структура ответа", 18 | "Request URL":"URL запроса", 19 | "Response Body":"Тело ответа", 20 | "Response Code":"HTTP код ответа", 21 | "Response Headers":"Заголовки ответа", 22 | "Hide Response":"Спрятать ответ", 23 | "Response Messages":"Что может прийти в ответ", 24 | "Try it out!":"Попробовать!", 25 | "Show/Hide":"Показать/Скрыть", 26 | "List Operations":"Операции кратко", 27 | "Expand Operations":"Операции подробно", 28 | "Raw":"В сыром виде", 29 | "can't parse JSON. Raw result":"Не удается распарсить ответ:", 30 | "Model Schema":"Структура", 31 | "Model":"Описание", 32 | "apply":"применить", 33 | "Username":"Имя пользователя", 34 | "Password":"Пароль", 35 | "Terms of service":"Условия использования", 36 | "Created by":"Разработано", 37 | "See more at":"Еще тут", 38 | "Contact the developer":"Связаться с разработчиком", 39 | "api version":"Версия API", 40 | "Response Content Type":"Content Type ответа", 41 | "fetching resource":"Получение ресурса", 42 | "fetching resource list":"Получение ресурсов", 43 | "Explore":"Поехали", 44 | "Show Swagger Petstore Example Apis":"Показать примеры АПИ", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Не удается получить ответ от сервера. Возможно, какая-то лажа с настройками доступа", 46 | "Please specify the protocol for":"Пожалуйста, укажите протогол для", 47 | "Can't read swagger JSON from":"Не получается прочитать swagger json из", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Загрузка информации о ресурсах завершена. Рендерим", 49 | "Unable to read api":"Не удалось прочитать api", 50 | "from path":"по адресу", 51 | "server returned":"сервер сказал" 52 | }); 53 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/SwaggerUi/CustomAssets/lang/tr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Uyarı: Deprecated", 6 | "Implementation Notes":"Gerçekleştirim Notları", 7 | "Response Class":"Dönen Sınıf", 8 | "Status":"Statü", 9 | "Parameters":"Parametreler", 10 | "Parameter":"Parametre", 11 | "Value":"Değer", 12 | "Description":"Açıklama", 13 | "Parameter Type":"Parametre Tipi", 14 | "Data Type":"Veri Tipi", 15 | "Response Messages":"Dönüş Mesajı", 16 | "HTTP Status Code":"HTTP Statü Kodu", 17 | "Reason":"Gerekçe", 18 | "Response Model":"Dönüş Modeli", 19 | "Request URL":"İstek URL", 20 | "Response Body":"Dönüş İçeriği", 21 | "Response Code":"Dönüş Kodu", 22 | "Response Headers":"Dönüş Üst Bilgileri", 23 | "Hide Response":"Dönüşü Gizle", 24 | "Headers":"Üst Bilgiler", 25 | "Try it out!":"Dene!", 26 | "Show/Hide":"Göster/Gizle", 27 | "List Operations":"Operasyonları Listele", 28 | "Expand Operations":"Operasyonları Aç", 29 | "Raw":"Ham", 30 | "can't parse JSON. Raw result":"JSON çözümlenemiyor. Ham sonuç", 31 | "Model Schema":"Model Şema", 32 | "Model":"Model", 33 | "apply":"uygula", 34 | "Username":"Kullanıcı Adı", 35 | "Password":"Parola", 36 | "Terms of service":"Servis şartları", 37 | "Created by":"Oluşturan", 38 | "See more at":"Daha fazlası için", 39 | "Contact the developer":"Geliştirici ile İletişime Geçin", 40 | "api version":"api versiyon", 41 | "Response Content Type":"Dönüş İçerik Tipi", 42 | "fetching resource":"kaynak getiriliyor", 43 | "fetching resource list":"kaynak listesi getiriliyor", 44 | "Explore":"Keşfet", 45 | "Show Swagger Petstore Example Apis":"Swagger Petstore Örnek Api'yi Gör", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.", 47 | "Please specify the protocol for":"Lütfen istenen adres için protokol belirtiniz", 48 | "Can't read swagger JSON from":"Swagger JSON bu kaynaktan okunamıyor", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor", 50 | "Unable to read api":"api okunamadı", 51 | "from path":"yoldan", 52 | "server returned":"sunucuya dönüldü" 53 | }); 54 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/SwaggerUi/CustomAssets/lang/translator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Translator for documentation pages. 5 | * 6 | * To enable translation you should include one of language-files in your index.html 7 | * after . 8 | * For example - 9 | * 10 | * If you wish to translate some new texsts you should do two things: 11 | * 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too. 12 | * 2. Mark that text it templates this way New Phrase or . 13 | * The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate. 14 | * 15 | */ 16 | window.SwaggerTranslator = { 17 | 18 | _words:[], 19 | 20 | translate: function(sel) { 21 | var $this = this; 22 | sel = sel || '[data-sw-translate]'; 23 | 24 | $(sel).each(function() { 25 | $(this).html($this._tryTranslate($(this).html())); 26 | 27 | $(this).val($this._tryTranslate($(this).val())); 28 | $(this).attr('title', $this._tryTranslate($(this).attr('title'))); 29 | }); 30 | }, 31 | 32 | _tryTranslate: function(word) { 33 | return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word; 34 | }, 35 | 36 | learn: function(wordsMap) { 37 | this._words = wordsMap; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/app.config: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Api/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/App.config: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BoardGame.Api; 3 | using Microsoft.Owin.Hosting; 4 | 5 | namespace BoardGame.Host 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | using (WebApp.Start("http://+:8080")) 12 | { 13 | Console.WriteLine("Server is up and running"); 14 | Console.ReadLine(); 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("BoardGame.Host")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BoardGame.Host")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("94504a74-c489-4e88-8647-a0ebe29ec66a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/SwaggerUi/CustomAssets/lang/en.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Warning: Deprecated", 6 | "Implementation Notes":"Implementation Notes", 7 | "Response Class":"Response Class", 8 | "Status":"Status", 9 | "Parameters":"Parameters", 10 | "Parameter":"Parameter", 11 | "Value":"Value", 12 | "Description":"Description", 13 | "Parameter Type":"Parameter Type", 14 | "Data Type":"Data Type", 15 | "Response Messages":"Response Messages", 16 | "HTTP Status Code":"HTTP Status Code", 17 | "Reason":"Reason", 18 | "Response Model":"Response Model", 19 | "Request URL":"Request URL", 20 | "Response Body":"Response Body", 21 | "Response Code":"Response Code", 22 | "Response Headers":"Response Headers", 23 | "Hide Response":"Hide Response", 24 | "Headers":"Headers", 25 | "Try it out!":"Try it out!", 26 | "Show/Hide":"Show/Hide", 27 | "List Operations":"List Operations", 28 | "Expand Operations":"Expand Operations", 29 | "Raw":"Raw", 30 | "can't parse JSON. Raw result":"can't parse JSON. Raw result", 31 | "Model Schema":"Model Schema", 32 | "Model":"Model", 33 | "apply":"apply", 34 | "Username":"Username", 35 | "Password":"Password", 36 | "Terms of service":"Terms of service", 37 | "Created by":"Created by", 38 | "See more at":"See more at", 39 | "Contact the developer":"Contact the developer", 40 | "api version":"api version", 41 | "Response Content Type":"Response Content Type", 42 | "fetching resource":"fetching resource", 43 | "fetching resource list":"fetching resource list", 44 | "Explore":"Explore", 45 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Can't read from server. It may not have the appropriate access-control-origin settings.", 47 | "Please specify the protocol for":"Please specify the protocol for", 48 | "Can't read swagger JSON from":"Can't read swagger JSON from", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Finished Loading Resource Information. Rendering Swagger UI", 50 | "Unable to read api":"Unable to read api", 51 | "from path":"from path", 52 | "server returned":"server returned" 53 | }); 54 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/SwaggerUi/CustomAssets/lang/es.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Advertencia: Obsoleto", 6 | "Implementation Notes":"Notas de implementación", 7 | "Response Class":"Clase de la Respuesta", 8 | "Status":"Status", 9 | "Parameters":"Parámetros", 10 | "Parameter":"Parámetro", 11 | "Value":"Valor", 12 | "Description":"Descripción", 13 | "Parameter Type":"Tipo del Parámetro", 14 | "Data Type":"Tipo del Dato", 15 | "Response Messages":"Mensajes de la Respuesta", 16 | "HTTP Status Code":"Código de Status HTTP", 17 | "Reason":"Razón", 18 | "Response Model":"Modelo de la Respuesta", 19 | "Request URL":"URL de la Solicitud", 20 | "Response Body":"Cuerpo de la Respuesta", 21 | "Response Code":"Código de la Respuesta", 22 | "Response Headers":"Encabezados de la Respuesta", 23 | "Hide Response":"Ocultar Respuesta", 24 | "Try it out!":"Pruébalo!", 25 | "Show/Hide":"Mostrar/Ocultar", 26 | "List Operations":"Listar Operaciones", 27 | "Expand Operations":"Expandir Operaciones", 28 | "Raw":"Crudo", 29 | "can't parse JSON. Raw result":"no puede parsear el JSON. Resultado crudo", 30 | "Model Schema":"Esquema del Modelo", 31 | "Model":"Modelo", 32 | "apply":"aplicar", 33 | "Username":"Nombre de usuario", 34 | "Password":"Contraseña", 35 | "Terms of service":"Términos de Servicio", 36 | "Created by":"Creado por", 37 | "See more at":"Ver más en", 38 | "Contact the developer":"Contactar al desarrollador", 39 | "api version":"versión de la api", 40 | "Response Content Type":"Tipo de Contenido (Content Type) de la Respuesta", 41 | "fetching resource":"buscando recurso", 42 | "fetching resource list":"buscando lista del recurso", 43 | "Explore":"Explorar", 44 | "Show Swagger Petstore Example Apis":"Mostrar Api Ejemplo de Swagger Petstore", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.", 46 | "Please specify the protocol for":"Por favor, especificar el protocola para", 47 | "Can't read swagger JSON from":"No se puede leer el JSON de swagger desde", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Finalizada la carga del recurso de Información. Mostrando Swagger UI", 49 | "Unable to read api":"No se puede leer la api", 50 | "from path":"desde ruta", 51 | "server returned":"el servidor retornó" 52 | }); 53 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/SwaggerUi/CustomAssets/lang/pt.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Aviso: Depreciado", 6 | "Implementation Notes":"Notas de Implementação", 7 | "Response Class":"Classe de resposta", 8 | "Status":"Status", 9 | "Parameters":"Parâmetros", 10 | "Parameter":"Parâmetro", 11 | "Value":"Valor", 12 | "Description":"Descrição", 13 | "Parameter Type":"Tipo de parâmetro", 14 | "Data Type":"Tipo de dados", 15 | "Response Messages":"Mensagens de resposta", 16 | "HTTP Status Code":"Código de status HTTP", 17 | "Reason":"Razão", 18 | "Response Model":"Modelo resposta", 19 | "Request URL":"URL requisição", 20 | "Response Body":"Corpo da resposta", 21 | "Response Code":"Código da resposta", 22 | "Response Headers":"Cabeçalho da resposta", 23 | "Headers":"Cabeçalhos", 24 | "Hide Response":"Esconder resposta", 25 | "Try it out!":"Tente agora!", 26 | "Show/Hide":"Mostrar/Esconder", 27 | "List Operations":"Listar operações", 28 | "Expand Operations":"Expandir operações", 29 | "Raw":"Cru", 30 | "can't parse JSON. Raw result":"Falha ao analisar JSON. Resulto cru", 31 | "Model Schema":"Modelo esquema", 32 | "Model":"Modelo", 33 | "apply":"Aplicar", 34 | "Username":"Usuário", 35 | "Password":"Senha", 36 | "Terms of service":"Termos do serviço", 37 | "Created by":"Criado por", 38 | "See more at":"Veja mais em", 39 | "Contact the developer":"Contate o desenvolvedor", 40 | "api version":"Versão api", 41 | "Response Content Type":"Tipo de conteúdo da resposta", 42 | "fetching resource":"busca recurso", 43 | "fetching resource list":"buscando lista de recursos", 44 | "Explore":"Explorar", 45 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin", 47 | "Please specify the protocol for":"Por favor especifique o protocolo", 48 | "Can't read swagger JSON from":"Não é possível ler o JSON Swagger de", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Carregar informação de recurso finalizada. Renderizando Swagger UI", 50 | "Unable to read api":"Não foi possível ler api", 51 | "from path":"do caminho", 52 | "server returned":"servidor retornou" 53 | }); 54 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/SwaggerUi/CustomAssets/lang/ru.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Ворнинг: Депрекейтед", 6 | "Implementation Notes":"Заметки", 7 | "Response Class":"Пример ответа", 8 | "Status":"Статус", 9 | "Parameters":"Параметры", 10 | "Parameter":"Параметр", 11 | "Value":"Значение", 12 | "Description":"Описание", 13 | "Parameter Type":"Тип параметра", 14 | "Data Type":"Тип данных", 15 | "HTTP Status Code":"HTTP код", 16 | "Reason":"Причина", 17 | "Response Model":"Структура ответа", 18 | "Request URL":"URL запроса", 19 | "Response Body":"Тело ответа", 20 | "Response Code":"HTTP код ответа", 21 | "Response Headers":"Заголовки ответа", 22 | "Hide Response":"Спрятать ответ", 23 | "Response Messages":"Что может прийти в ответ", 24 | "Try it out!":"Попробовать!", 25 | "Show/Hide":"Показать/Скрыть", 26 | "List Operations":"Операции кратко", 27 | "Expand Operations":"Операции подробно", 28 | "Raw":"В сыром виде", 29 | "can't parse JSON. Raw result":"Не удается распарсить ответ:", 30 | "Model Schema":"Структура", 31 | "Model":"Описание", 32 | "apply":"применить", 33 | "Username":"Имя пользователя", 34 | "Password":"Пароль", 35 | "Terms of service":"Условия использования", 36 | "Created by":"Разработано", 37 | "See more at":"Еще тут", 38 | "Contact the developer":"Связаться с разработчиком", 39 | "api version":"Версия API", 40 | "Response Content Type":"Content Type ответа", 41 | "fetching resource":"Получение ресурса", 42 | "fetching resource list":"Получение ресурсов", 43 | "Explore":"Поехали", 44 | "Show Swagger Petstore Example Apis":"Показать примеры АПИ", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Не удается получить ответ от сервера. Возможно, какая-то лажа с настройками доступа", 46 | "Please specify the protocol for":"Пожалуйста, укажите протогол для", 47 | "Can't read swagger JSON from":"Не получается прочитать swagger json из", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Загрузка информации о ресурсах завершена. Рендерим", 49 | "Unable to read api":"Не удалось прочитать api", 50 | "from path":"по адресу", 51 | "server returned":"сервер сказал" 52 | }); 53 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/SwaggerUi/CustomAssets/lang/tr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Uyarı: Deprecated", 6 | "Implementation Notes":"Gerçekleştirim Notları", 7 | "Response Class":"Dönen Sınıf", 8 | "Status":"Statü", 9 | "Parameters":"Parametreler", 10 | "Parameter":"Parametre", 11 | "Value":"Değer", 12 | "Description":"Açıklama", 13 | "Parameter Type":"Parametre Tipi", 14 | "Data Type":"Veri Tipi", 15 | "Response Messages":"Dönüş Mesajı", 16 | "HTTP Status Code":"HTTP Statü Kodu", 17 | "Reason":"Gerekçe", 18 | "Response Model":"Dönüş Modeli", 19 | "Request URL":"İstek URL", 20 | "Response Body":"Dönüş İçeriği", 21 | "Response Code":"Dönüş Kodu", 22 | "Response Headers":"Dönüş Üst Bilgileri", 23 | "Hide Response":"Dönüşü Gizle", 24 | "Headers":"Üst Bilgiler", 25 | "Try it out!":"Dene!", 26 | "Show/Hide":"Göster/Gizle", 27 | "List Operations":"Operasyonları Listele", 28 | "Expand Operations":"Operasyonları Aç", 29 | "Raw":"Ham", 30 | "can't parse JSON. Raw result":"JSON çözümlenemiyor. Ham sonuç", 31 | "Model Schema":"Model Şema", 32 | "Model":"Model", 33 | "apply":"uygula", 34 | "Username":"Kullanıcı Adı", 35 | "Password":"Parola", 36 | "Terms of service":"Servis şartları", 37 | "Created by":"Oluşturan", 38 | "See more at":"Daha fazlası için", 39 | "Contact the developer":"Geliştirici ile İletişime Geçin", 40 | "api version":"api versiyon", 41 | "Response Content Type":"Dönüş İçerik Tipi", 42 | "fetching resource":"kaynak getiriliyor", 43 | "fetching resource list":"kaynak listesi getiriliyor", 44 | "Explore":"Keşfet", 45 | "Show Swagger Petstore Example Apis":"Swagger Petstore Örnek Api'yi Gör", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.", 47 | "Please specify the protocol for":"Lütfen istenen adres için protokol belirtiniz", 48 | "Can't read swagger JSON from":"Swagger JSON bu kaynaktan okunamıyor", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor", 50 | "Unable to read api":"api okunamadı", 51 | "from path":"yoldan", 52 | "server returned":"sunucuya dönüldü" 53 | }); 54 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/SwaggerUi/CustomAssets/lang/translator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Translator for documentation pages. 5 | * 6 | * To enable translation you should include one of language-files in your index.html 7 | * after . 8 | * For example - 9 | * 10 | * If you wish to translate some new texsts you should do two things: 11 | * 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too. 12 | * 2. Mark that text it templates this way New Phrase or . 13 | * The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate. 14 | * 15 | */ 16 | window.SwaggerTranslator = { 17 | 18 | _words:[], 19 | 20 | translate: function(sel) { 21 | var $this = this; 22 | sel = sel || '[data-sw-translate]'; 23 | 24 | $(sel).each(function() { 25 | $(this).html($this._tryTranslate($(this).html())); 26 | 27 | $(this).val($this._tryTranslate($(this).val())); 28 | $(this).attr('title', $this._tryTranslate($(this).attr('title'))); 29 | }); 30 | }, 31 | 32 | _tryTranslate: function(word) { 33 | return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word; 34 | }, 35 | 36 | learn: function(wordsMap) { 37 | this._words = wordsMap; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.Host/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.WebHost/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("BoardGame.WebHost")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BoardGame.WebHost")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("bf141505-c0b1-418b-a73b-74880a667183")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.WebHost/SwaggerUi/CustomAssets/lang/en.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Warning: Deprecated", 6 | "Implementation Notes":"Implementation Notes", 7 | "Response Class":"Response Class", 8 | "Status":"Status", 9 | "Parameters":"Parameters", 10 | "Parameter":"Parameter", 11 | "Value":"Value", 12 | "Description":"Description", 13 | "Parameter Type":"Parameter Type", 14 | "Data Type":"Data Type", 15 | "Response Messages":"Response Messages", 16 | "HTTP Status Code":"HTTP Status Code", 17 | "Reason":"Reason", 18 | "Response Model":"Response Model", 19 | "Request URL":"Request URL", 20 | "Response Body":"Response Body", 21 | "Response Code":"Response Code", 22 | "Response Headers":"Response Headers", 23 | "Hide Response":"Hide Response", 24 | "Headers":"Headers", 25 | "Try it out!":"Try it out!", 26 | "Show/Hide":"Show/Hide", 27 | "List Operations":"List Operations", 28 | "Expand Operations":"Expand Operations", 29 | "Raw":"Raw", 30 | "can't parse JSON. Raw result":"can't parse JSON. Raw result", 31 | "Model Schema":"Model Schema", 32 | "Model":"Model", 33 | "apply":"apply", 34 | "Username":"Username", 35 | "Password":"Password", 36 | "Terms of service":"Terms of service", 37 | "Created by":"Created by", 38 | "See more at":"See more at", 39 | "Contact the developer":"Contact the developer", 40 | "api version":"api version", 41 | "Response Content Type":"Response Content Type", 42 | "fetching resource":"fetching resource", 43 | "fetching resource list":"fetching resource list", 44 | "Explore":"Explore", 45 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Can't read from server. It may not have the appropriate access-control-origin settings.", 47 | "Please specify the protocol for":"Please specify the protocol for", 48 | "Can't read swagger JSON from":"Can't read swagger JSON from", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Finished Loading Resource Information. Rendering Swagger UI", 50 | "Unable to read api":"Unable to read api", 51 | "from path":"from path", 52 | "server returned":"server returned" 53 | }); 54 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.WebHost/SwaggerUi/CustomAssets/lang/es.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Advertencia: Obsoleto", 6 | "Implementation Notes":"Notas de implementación", 7 | "Response Class":"Clase de la Respuesta", 8 | "Status":"Status", 9 | "Parameters":"Parámetros", 10 | "Parameter":"Parámetro", 11 | "Value":"Valor", 12 | "Description":"Descripción", 13 | "Parameter Type":"Tipo del Parámetro", 14 | "Data Type":"Tipo del Dato", 15 | "Response Messages":"Mensajes de la Respuesta", 16 | "HTTP Status Code":"Código de Status HTTP", 17 | "Reason":"Razón", 18 | "Response Model":"Modelo de la Respuesta", 19 | "Request URL":"URL de la Solicitud", 20 | "Response Body":"Cuerpo de la Respuesta", 21 | "Response Code":"Código de la Respuesta", 22 | "Response Headers":"Encabezados de la Respuesta", 23 | "Hide Response":"Ocultar Respuesta", 24 | "Try it out!":"Pruébalo!", 25 | "Show/Hide":"Mostrar/Ocultar", 26 | "List Operations":"Listar Operaciones", 27 | "Expand Operations":"Expandir Operaciones", 28 | "Raw":"Crudo", 29 | "can't parse JSON. Raw result":"no puede parsear el JSON. Resultado crudo", 30 | "Model Schema":"Esquema del Modelo", 31 | "Model":"Modelo", 32 | "apply":"aplicar", 33 | "Username":"Nombre de usuario", 34 | "Password":"Contraseña", 35 | "Terms of service":"Términos de Servicio", 36 | "Created by":"Creado por", 37 | "See more at":"Ver más en", 38 | "Contact the developer":"Contactar al desarrollador", 39 | "api version":"versión de la api", 40 | "Response Content Type":"Tipo de Contenido (Content Type) de la Respuesta", 41 | "fetching resource":"buscando recurso", 42 | "fetching resource list":"buscando lista del recurso", 43 | "Explore":"Explorar", 44 | "Show Swagger Petstore Example Apis":"Mostrar Api Ejemplo de Swagger Petstore", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.", 46 | "Please specify the protocol for":"Por favor, especificar el protocola para", 47 | "Can't read swagger JSON from":"No se puede leer el JSON de swagger desde", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Finalizada la carga del recurso de Información. Mostrando Swagger UI", 49 | "Unable to read api":"No se puede leer la api", 50 | "from path":"desde ruta", 51 | "server returned":"el servidor retornó" 52 | }); 53 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.WebHost/SwaggerUi/CustomAssets/lang/pt.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Aviso: Depreciado", 6 | "Implementation Notes":"Notas de Implementação", 7 | "Response Class":"Classe de resposta", 8 | "Status":"Status", 9 | "Parameters":"Parâmetros", 10 | "Parameter":"Parâmetro", 11 | "Value":"Valor", 12 | "Description":"Descrição", 13 | "Parameter Type":"Tipo de parâmetro", 14 | "Data Type":"Tipo de dados", 15 | "Response Messages":"Mensagens de resposta", 16 | "HTTP Status Code":"Código de status HTTP", 17 | "Reason":"Razão", 18 | "Response Model":"Modelo resposta", 19 | "Request URL":"URL requisição", 20 | "Response Body":"Corpo da resposta", 21 | "Response Code":"Código da resposta", 22 | "Response Headers":"Cabeçalho da resposta", 23 | "Headers":"Cabeçalhos", 24 | "Hide Response":"Esconder resposta", 25 | "Try it out!":"Tente agora!", 26 | "Show/Hide":"Mostrar/Esconder", 27 | "List Operations":"Listar operações", 28 | "Expand Operations":"Expandir operações", 29 | "Raw":"Cru", 30 | "can't parse JSON. Raw result":"Falha ao analisar JSON. Resulto cru", 31 | "Model Schema":"Modelo esquema", 32 | "Model":"Modelo", 33 | "apply":"Aplicar", 34 | "Username":"Usuário", 35 | "Password":"Senha", 36 | "Terms of service":"Termos do serviço", 37 | "Created by":"Criado por", 38 | "See more at":"Veja mais em", 39 | "Contact the developer":"Contate o desenvolvedor", 40 | "api version":"Versão api", 41 | "Response Content Type":"Tipo de conteúdo da resposta", 42 | "fetching resource":"busca recurso", 43 | "fetching resource list":"buscando lista de recursos", 44 | "Explore":"Explorar", 45 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin", 47 | "Please specify the protocol for":"Por favor especifique o protocolo", 48 | "Can't read swagger JSON from":"Não é possível ler o JSON Swagger de", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Carregar informação de recurso finalizada. Renderizando Swagger UI", 50 | "Unable to read api":"Não foi possível ler api", 51 | "from path":"do caminho", 52 | "server returned":"servidor retornou" 53 | }); 54 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.WebHost/SwaggerUi/CustomAssets/lang/ru.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Ворнинг: Депрекейтед", 6 | "Implementation Notes":"Заметки", 7 | "Response Class":"Пример ответа", 8 | "Status":"Статус", 9 | "Parameters":"Параметры", 10 | "Parameter":"Параметр", 11 | "Value":"Значение", 12 | "Description":"Описание", 13 | "Parameter Type":"Тип параметра", 14 | "Data Type":"Тип данных", 15 | "HTTP Status Code":"HTTP код", 16 | "Reason":"Причина", 17 | "Response Model":"Структура ответа", 18 | "Request URL":"URL запроса", 19 | "Response Body":"Тело ответа", 20 | "Response Code":"HTTP код ответа", 21 | "Response Headers":"Заголовки ответа", 22 | "Hide Response":"Спрятать ответ", 23 | "Response Messages":"Что может прийти в ответ", 24 | "Try it out!":"Попробовать!", 25 | "Show/Hide":"Показать/Скрыть", 26 | "List Operations":"Операции кратко", 27 | "Expand Operations":"Операции подробно", 28 | "Raw":"В сыром виде", 29 | "can't parse JSON. Raw result":"Не удается распарсить ответ:", 30 | "Model Schema":"Структура", 31 | "Model":"Описание", 32 | "apply":"применить", 33 | "Username":"Имя пользователя", 34 | "Password":"Пароль", 35 | "Terms of service":"Условия использования", 36 | "Created by":"Разработано", 37 | "See more at":"Еще тут", 38 | "Contact the developer":"Связаться с разработчиком", 39 | "api version":"Версия API", 40 | "Response Content Type":"Content Type ответа", 41 | "fetching resource":"Получение ресурса", 42 | "fetching resource list":"Получение ресурсов", 43 | "Explore":"Поехали", 44 | "Show Swagger Petstore Example Apis":"Показать примеры АПИ", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Не удается получить ответ от сервера. Возможно, какая-то лажа с настройками доступа", 46 | "Please specify the protocol for":"Пожалуйста, укажите протогол для", 47 | "Can't read swagger JSON from":"Не получается прочитать swagger json из", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Загрузка информации о ресурсах завершена. Рендерим", 49 | "Unable to read api":"Не удалось прочитать api", 50 | "from path":"по адресу", 51 | "server returned":"сервер сказал" 52 | }); 53 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.WebHost/SwaggerUi/CustomAssets/lang/tr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Uyarı: Deprecated", 6 | "Implementation Notes":"Gerçekleştirim Notları", 7 | "Response Class":"Dönen Sınıf", 8 | "Status":"Statü", 9 | "Parameters":"Parametreler", 10 | "Parameter":"Parametre", 11 | "Value":"Değer", 12 | "Description":"Açıklama", 13 | "Parameter Type":"Parametre Tipi", 14 | "Data Type":"Veri Tipi", 15 | "Response Messages":"Dönüş Mesajı", 16 | "HTTP Status Code":"HTTP Statü Kodu", 17 | "Reason":"Gerekçe", 18 | "Response Model":"Dönüş Modeli", 19 | "Request URL":"İstek URL", 20 | "Response Body":"Dönüş İçeriği", 21 | "Response Code":"Dönüş Kodu", 22 | "Response Headers":"Dönüş Üst Bilgileri", 23 | "Hide Response":"Dönüşü Gizle", 24 | "Headers":"Üst Bilgiler", 25 | "Try it out!":"Dene!", 26 | "Show/Hide":"Göster/Gizle", 27 | "List Operations":"Operasyonları Listele", 28 | "Expand Operations":"Operasyonları Aç", 29 | "Raw":"Ham", 30 | "can't parse JSON. Raw result":"JSON çözümlenemiyor. Ham sonuç", 31 | "Model Schema":"Model Şema", 32 | "Model":"Model", 33 | "apply":"uygula", 34 | "Username":"Kullanıcı Adı", 35 | "Password":"Parola", 36 | "Terms of service":"Servis şartları", 37 | "Created by":"Oluşturan", 38 | "See more at":"Daha fazlası için", 39 | "Contact the developer":"Geliştirici ile İletişime Geçin", 40 | "api version":"api versiyon", 41 | "Response Content Type":"Dönüş İçerik Tipi", 42 | "fetching resource":"kaynak getiriliyor", 43 | "fetching resource list":"kaynak listesi getiriliyor", 44 | "Explore":"Keşfet", 45 | "Show Swagger Petstore Example Apis":"Swagger Petstore Örnek Api'yi Gör", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.", 47 | "Please specify the protocol for":"Lütfen istenen adres için protokol belirtiniz", 48 | "Can't read swagger JSON from":"Swagger JSON bu kaynaktan okunamıyor", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor", 50 | "Unable to read api":"api okunamadı", 51 | "from path":"yoldan", 52 | "server returned":"sunucuya dönüldü" 53 | }); 54 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.WebHost/SwaggerUi/CustomAssets/lang/translator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Translator for documentation pages. 5 | * 6 | * To enable translation you should include one of language-files in your index.html 7 | * after . 8 | * For example - 9 | * 10 | * If you wish to translate some new texsts you should do two things: 11 | * 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too. 12 | * 2. Mark that text it templates this way New Phrase or . 13 | * The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate. 14 | * 15 | */ 16 | window.SwaggerTranslator = { 17 | 18 | _words:[], 19 | 20 | translate: function(sel) { 21 | var $this = this; 22 | sel = sel || '[data-sw-translate]'; 23 | 24 | $(sel).each(function() { 25 | $(this).html($this._tryTranslate($(this).html())); 26 | 27 | $(this).val($this._tryTranslate($(this).val())); 28 | $(this).attr('title', $this._tryTranslate($(this).attr('title'))); 29 | }); 30 | }, 31 | 32 | _tryTranslate: function(word) { 33 | return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word; 34 | }, 35 | 36 | learn: function(wordsMap) { 37 | this._words = wordsMap; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.WebHost/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/BoardZApi/BoardGame.WebHost/web.config: -------------------------------------------------------------------------------- 1 |  2 | 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 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /system.config.js: -------------------------------------------------------------------------------- 1 | System.config({ 2 | baseURL: './src/BoardZ/vendor/', 3 | paths: { 4 | "*": "*.js" 5 | }, 6 | meta: { 7 | 'jquery': { 8 | build: false 9 | }, 10 | 'hammerjs': { 11 | build: false 12 | }, 13 | 'pnotify': { 14 | build: false 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": true, 10 | "noImplicitAny": false, 11 | "isolatedModules": true 12 | }, 13 | "exclude": [ 14 | "node_modules", 15 | "typings/main", 16 | "typings/main.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-require-imports": true, 4 | "no-var-keyword": true, 5 | "triple-equals": [ 6 | true, 7 | "allow-undefined-check" 8 | ], 9 | "typedef-whitespace": [ 10 | true, 11 | { 12 | "call-signature": "nospace", 13 | "index-signature": "nospace", 14 | "parameter": "nospace", 15 | "property-declaration": "nospace", 16 | "variable-declaration": "nospace" 17 | }, 18 | { 19 | "call-signature": "onespace", 20 | "index-signature": "onespace", 21 | "parameter": "onespace", 22 | "property-declaration": "onespace", 23 | "variable-declaration": "onespace" 24 | } 25 | ], 26 | "curly": true, 27 | "eofline": true, 28 | "indent": [ 29 | true, 30 | "spaces" 31 | ], 32 | "no-trailing-whitespace": true, 33 | "class-name": true, 34 | "no-consecutive-blank-lines": true, 35 | "one-line": [ 36 | true, 37 | "check-else", 38 | "check-open-brace" 39 | ], 40 | "quotemark": [ 41 | true, 42 | "single" 43 | ], 44 | "semicolon": [ 45 | true, 46 | "always" 47 | ], 48 | "whitespace": [ 49 | true, 50 | "check-branch", 51 | "check-decl", 52 | "check-separator", 53 | "check-operator", 54 | "check-type" 55 | ] 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "core-js": "registry:dt/core-js#0.0.0+20160725163759", 4 | "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", 5 | "leaflet": "registry:dt/leaflet#1.0.0+20160630180443", 6 | "node": "registry:dt/node#6.0.0+20160909174046" 7 | } 8 | } 9 | --------------------------------------------------------------------------------