├── .gitignore ├── ARMTemplates ├── Dev.json ├── ProdAndStage.json ├── deploy.ps1 ├── deploy.sh ├── param.json ├── paramcli.json └── swap.ps1 ├── LICENSE ├── azuredeploy.json ├── readme.md └── src ├── MultiChannelToDo.Web ├── MultiChannelToDo.Web.csproj ├── Properties │ └── AssemblyInfo.cs ├── Web.config ├── css │ └── site.css ├── img │ └── spinner.gif ├── index.cshtml ├── js │ ├── app.js │ ├── controllers │ │ └── ToDoController.js │ ├── models │ │ └── todoitem.json │ └── services │ │ └── ToDoService.js ├── lib │ ├── angular │ │ └── angular.min.js │ ├── bootstrap │ │ ├── css │ │ │ ├── bootstrap-theme.min.css │ │ │ └── bootstrap.min.css │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ │ └── bootstrap.min.js │ └── jquery │ │ └── jquery.min.js └── packages.config ├── MultiChannelToDo.sln └── MultiChannelToDo ├── App_Start └── WebApiConfig.cs ├── Controllers └── ToDoItemsController.cs ├── Global.asax ├── Global.asax.cs ├── Migrations ├── 201504231007334_Initialize Database.Designer.cs ├── 201504231007334_Initialize Database.cs ├── 201504231007334_Initialize Database.resx └── Configuration.cs ├── Models ├── MultiChannelToDoContext.cs └── ToDoItem.cs ├── MultiChannelToDo.csproj ├── Properties └── AssemblyInfo.cs ├── Web.config └── packages.config /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### Windows ### 4 | # Windows image file caches 5 | Thumbs.db 6 | ehthumbs.db 7 | 8 | # Folder config file 9 | Desktop.ini 10 | 11 | # Recycle Bin used on file shares 12 | $RECYCLE.BIN/ 13 | 14 | # Windows Installer files 15 | *.cab 16 | *.msi 17 | *.msm 18 | *.msp 19 | 20 | # Windows shortcuts 21 | *.lnk 22 | 23 | 24 | ### VisualStudio ### 25 | ## Ignore Visual Studio temporary files, build results, and 26 | ## files generated by popular Visual Studio add-ons. 27 | 28 | # User-specific files 29 | *.suo 30 | *.user 31 | *.userosscache 32 | *.sln.docstates 33 | 34 | # User-specific files (MonoDevelop/Xamarin Studio) 35 | *.userprefs 36 | 37 | # Build results 38 | [Dd]ebug/ 39 | [Dd]ebugPublic/ 40 | [Rr]elease/ 41 | [Rr]eleases/ 42 | x64/ 43 | x86/ 44 | build/ 45 | bld/ 46 | [Bb]in/ 47 | [Oo]bj/ 48 | 49 | # Don't ignore a deployable bin directory 50 | !/**/[Aa]pp/[Bb]in 51 | 52 | 53 | # Visual Studo 2015 cache/options directory 54 | .vs/ 55 | 56 | # MSTest test Results 57 | [Tt]est[Rr]esult*/ 58 | [Bb]uild[Ll]og.* 59 | 60 | # NUNIT 61 | *.VisualState.xml 62 | TestResult.xml 63 | 64 | # Build Results of an ATL Project 65 | [Dd]ebugPS/ 66 | [Rr]eleasePS/ 67 | dlldata.c 68 | 69 | *_i.c 70 | *_p.c 71 | *_i.h 72 | *.ilk 73 | *.meta 74 | *.obj 75 | *.pch 76 | *.pdb 77 | *.pgc 78 | *.pgd 79 | *.rsp 80 | *.sbr 81 | *.tlb 82 | *.tli 83 | *.tlh 84 | *.tmp 85 | *.tmp_proj 86 | *.log 87 | *.vspscc 88 | *.vssscc 89 | .builds 90 | *.pidb 91 | *.svclog 92 | *.scc 93 | 94 | # Chutzpah Test files 95 | _Chutzpah* 96 | 97 | # Visual C++ cache files 98 | ipch/ 99 | *.aps 100 | *.ncb 101 | *.opensdf 102 | *.sdf 103 | *.cachefile 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | 110 | # TFS 2012 Local Workspace 111 | $tf/ 112 | 113 | # Guidance Automation Toolkit 114 | *.gpState 115 | 116 | # ReSharper is a .NET coding add-in 117 | _ReSharper*/ 118 | *.[Rr]e[Ss]harper 119 | *.DotSettings.user 120 | 121 | # JustCode is a .NET coding addin-in 122 | .JustCode 123 | 124 | # TeamCity is a build add-in 125 | _TeamCity* 126 | 127 | # DotCover is a Code Coverage Tool 128 | *.dotCover 129 | 130 | # NCrunch 131 | _NCrunch_* 132 | .*crunch*.local.xml 133 | 134 | # MightyMoose 135 | *.mm.* 136 | AutoTest.Net/ 137 | 138 | # Web workbench (sass) 139 | .sass-cache/ 140 | 141 | # Installshield output folder 142 | [Ee]xpress/ 143 | 144 | # DocProject is a documentation generator add-in 145 | DocProject/buildhelp/ 146 | DocProject/Help/*.HxT 147 | DocProject/Help/*.HxC 148 | DocProject/Help/*.hhc 149 | DocProject/Help/*.hhk 150 | DocProject/Help/*.hhp 151 | DocProject/Help/Html2 152 | DocProject/Help/html 153 | 154 | # Click-Once directory 155 | publish/ 156 | 157 | # Publish Web Output 158 | *.[Pp]ublish.xml 159 | *.azurePubxml 160 | # TODO: Comment the next line if you want to checkin your web deploy settings 161 | # but database connection strings (with potential passwords) will be unencrypted 162 | *.pubxml 163 | *.publishproj 164 | 165 | # NuGet Packages 166 | *.nupkg 167 | # The packages folder can be ignored because of Package Restore 168 | **/packages/* 169 | # except build/, which is used as an MSBuild target. 170 | !**/packages/build/ 171 | # Uncomment if necessary however generally it will be regenerated when needed 172 | #!**/packages/repositories.config 173 | 174 | # Windows Azure Build Output 175 | csx/ 176 | *.build.csdef 177 | 178 | # Windows Store app package directory 179 | AppPackages/ 180 | 181 | # Others 182 | *.[Cc]ache 183 | ClientBin/ 184 | [Ss]tyle[Cc]op.* 185 | ~$* 186 | *~ 187 | *.dbmdl 188 | *.dbproj.schemaview 189 | *.pfx 190 | *.publishsettings 191 | node_modules/ 192 | bower_components/ 193 | 194 | # RIA/Silverlight projects 195 | Generated_Code/ 196 | 197 | # Backup & report files from converting an old project file 198 | # to a newer Visual Studio version. Backup files are not needed, 199 | # because we have git ;-) 200 | _UpgradeReport_Files/ 201 | Backup*/ 202 | UpgradeLog*.XML 203 | UpgradeLog*.htm 204 | 205 | # SQL Server files 206 | *.mdf 207 | *.ldf 208 | 209 | # Business Intelligence projects 210 | *.rdl.data 211 | *.bim.layout 212 | *.bim_*.settings 213 | 214 | # Microsoft Fakes 215 | FakesAssemblies/ 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Azure Deploy 227 | params.json -------------------------------------------------------------------------------- /ARMTemplates/Dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "siteName": { 6 | "type": "string" 7 | }, 8 | "hostingPlanName": { 9 | "type": "string" 10 | }, 11 | "siteLocation": { 12 | "type": "string" 13 | }, 14 | "sku": { 15 | "type": "string", 16 | "allowedValues": [ 17 | "Free", 18 | "Shared", 19 | "Basic", 20 | "Standard", 21 | "Premium" 22 | ], 23 | "defaultValue": "Free" 24 | }, 25 | "workerSize": { 26 | "type": "string", 27 | "allowedValues": [ 28 | "0", 29 | "1", 30 | "2" 31 | ], 32 | "defaultValue": "0" 33 | }, 34 | "repoUrl": { 35 | "type": "string" 36 | }, 37 | "branch": { 38 | "type": "string", 39 | "defaultValue": "master" 40 | }, 41 | "sqlServerName": { 42 | "type": "string" 43 | }, 44 | "sqlServerAdminLogin": { 45 | "type": "string" 46 | }, 47 | "sqlServerAdminPassword": { 48 | "type": "securestring" 49 | }, 50 | "sqlDbName": { 51 | "type": "string", 52 | "defaultValue": "DemosDB" 53 | }, 54 | "sqlDbCollation": { 55 | "type": "string", 56 | "defaultValue": "SQL_Latin1_General_CP1_CI_AS" 57 | }, 58 | "sqlDbEdition": { 59 | "type": "string", 60 | "defaultValue": "Basic" 61 | }, 62 | "sqlDbMaxSizeBytes": { 63 | "type": "string", 64 | "defaultValue": "1073741824" 65 | }, 66 | "sqlDbServiceObjectiveId": { 67 | "type": "string", 68 | "defaultValue": "dd6d99bb-f193-4ec1-86f2-43d3bccbc49c" 69 | }, 70 | "slotName": { 71 | "type": "string", 72 | "defaultValue": "Staging" 73 | } 74 | }, 75 | "variables": { 76 | "apiSiteName": "[concat(parameters('siteName'), 'Api')]" 77 | }, 78 | "resources": [ 79 | { 80 | "apiVersion": "2014-04-01-preview", 81 | "name": "[parameters('sqlServerName')]", 82 | "type": "Microsoft.Sql/servers", 83 | "location": "[parameters('siteLocation')]", 84 | "properties": { 85 | "administratorLogin": "[parameters('sqlServerAdminLogin')]", 86 | "administratorLoginPassword": "[parameters('sqlServerAdminPassword')]" 87 | }, 88 | "resources": [ 89 | { 90 | "apiVersion": "2014-04-01-preview", 91 | "name": "[parameters('sqlDbName')]", 92 | "type": "databases", 93 | "location": "[parameters('siteLocation')]", 94 | "dependsOn": [ 95 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 96 | ], 97 | "properties": { 98 | "edition": "[parameters('sqlDbEdition')]", 99 | "collation": "[parameters('sqlDbCollation')]", 100 | "maxSizeBytes": "[parameters('sqlDbMaxSizeBytes')]", 101 | "requestedServiceObjectiveId": "[parameters('sqlDbServiceObjectiveId')]" 102 | } 103 | }, 104 | { 105 | "apiVersion": "2014-04-01-preview", 106 | "name": "SQLServerFirewallRules", 107 | "type": "firewallrules", 108 | "location": "[parameters('siteLocation')]", 109 | "dependsOn": [ 110 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 111 | ], 112 | "properties": { 113 | "endIpAddress": "0.0.0.0", 114 | "startIpAddress": "0.0.0.0" 115 | } 116 | } 117 | ] 118 | }, 119 | { 120 | "apiVersion": "2015-04-01", 121 | "name": "[parameters('hostingPlanName')]", 122 | "type": "Microsoft.Web/serverFarms", 123 | "location": "[parameters('siteLocation')]", 124 | "properties": { 125 | "name": "[parameters('hostingPlanName')]", 126 | "sku": "[parameters('sku')]", 127 | "workerSize": "[parameters('workerSize')]", 128 | "numberOfWorkers": 1 129 | } 130 | }, 131 | { 132 | "apiVersion": "2015-04-01", 133 | "name": "[variables('apiSiteName')]", 134 | "type": "Microsoft.Web/sites", 135 | "location": "[parameters('siteLocation')]", 136 | "dependsOn": [ 137 | "[resourceId('Microsoft.Web/serverFarms', parameters('hostingPlanName'))]" 138 | ], 139 | "properties": { 140 | "serverFarmId": "[parameters('hostingPlanName')]" 141 | }, 142 | "resources": [ 143 | { 144 | "apiVersion": "2015-04-01", 145 | "name": "appsettings", 146 | "type": "config", 147 | "dependsOn": [ 148 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]" 149 | ], 150 | "properties": { 151 | "PROJECT": "src\\MultiChannelToDo\\MultiChannelToDo.csproj", 152 | "clientUrl": "[concat('http://', parameters('siteName'), '.azurewebsites.net')]" 153 | } 154 | }, 155 | { 156 | "apiVersion": "2015-04-01", 157 | "name": "connectionstrings", 158 | "type": "config", 159 | "dependsOn": [ 160 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]", 161 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 162 | ], 163 | "properties": { 164 | "MultiChannelToDoContext": { "value": "[concat('Data Source=tcp:', reference(concat('Microsoft.Sql/servers/', parameters('sqlServerName'))).fullyQualifiedDomainName, ',1433;Initial Catalog=', parameters('sqlDbName'), ';User Id=', parameters('sqlServerAdminLogin'), '@', parameters('sqlServerName'), ';Password=', parameters('sqlServerAdminPassword'), ';')]", "type": "SQLAzure" } 165 | } 166 | }, 167 | { 168 | "apiVersion": "2015-04-01", 169 | "name": "web", 170 | "type": "sourcecontrols", 171 | "dependsOn": [ 172 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]", 173 | "[resourceId('Microsoft.Web/Sites/config', variables('apiSiteName'), 'appsettings')]", 174 | "[resourceId('Microsoft.Web/Sites/config', variables('apiSiteName'), 'connectionstrings')]" 175 | ], 176 | "properties": { 177 | "RepoUrl": "[parameters('repoUrl')]", 178 | "branch": "[parameters('branch')]" 179 | } 180 | } 181 | ] 182 | }, 183 | { 184 | "apiVersion": "2015-04-01", 185 | "name": "[parameters('siteName')]", 186 | "type": "Microsoft.Web/sites", 187 | "location": "[parameters('siteLocation')]", 188 | "dependsOn": [ 189 | "[resourceId('Microsoft.Web/serverFarms', parameters('hostingPlanName'))]" 190 | ], 191 | "properties": { 192 | "serverFarmId": "[parameters('hostingPlanName')]" 193 | }, 194 | "resources": [ 195 | { 196 | "apiVersion": "2015-04-01", 197 | "name": "appsettings", 198 | "type": "config", 199 | "dependsOn": [ 200 | "[resourceId('Microsoft.Web/Sites', parameters('siteName'))]" 201 | ], 202 | "properties": { 203 | "PROJECT": "src\\MultiChannelToDo.Web\\MultiChannelToDo.Web.csproj", 204 | "apiPath": "[concat('http://', variables('apiSiteName'), '.azurewebsites.net/api')]" 205 | } 206 | }, 207 | { 208 | "apiVersion": "2015-04-01", 209 | "name": "web", 210 | "type": "sourcecontrols", 211 | "dependsOn": [ 212 | "[resourceId('Microsoft.Web/Sites', parameters('siteName'))]", 213 | "[resourceId('Microsoft.Web/Sites/config', parameters('siteName'), 'appsettings')]" 214 | ], 215 | "properties": { 216 | "RepoUrl": "[parameters('repoUrl')]", 217 | "branch": "[parameters('branch')]" 218 | } 219 | } 220 | ] 221 | } 222 | ] 223 | } 224 | -------------------------------------------------------------------------------- /ARMTemplates/ProdAndStage.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "siteName": { 6 | "type": "string" 7 | }, 8 | "hostingPlanName": { 9 | "type": "string" 10 | }, 11 | "siteLocation": { 12 | "type": "string" 13 | }, 14 | "workerSize": { 15 | "type": "string", 16 | "allowedValues": [ 17 | "0", 18 | "1", 19 | "2" 20 | ], 21 | "defaultValue": "0" 22 | }, 23 | "repoUrl": { 24 | "type": "string" 25 | }, 26 | "branch": { 27 | "type": "string", 28 | "defaultValue": "master" 29 | }, 30 | "sqlServerName": { 31 | "type": "string" 32 | }, 33 | "sqlServerAdminLogin": { 34 | "type": "string" 35 | }, 36 | "sqlServerAdminPassword": { 37 | "type": "securestring" 38 | }, 39 | "sqlDbName": { 40 | "type": "string", 41 | "defaultValue": "DemosDB" 42 | }, 43 | "sqlDbCollation": { 44 | "type": "string", 45 | "defaultValue": "SQL_Latin1_General_CP1_CI_AS" 46 | }, 47 | "sqlDbEdition": { 48 | "type": "string", 49 | "defaultValue": "Basic" 50 | }, 51 | "sqlDbMaxSizeBytes": { 52 | "type": "string", 53 | "defaultValue": "1073741824" 54 | }, 55 | "sqlDbServiceObjectiveId": { 56 | "type": "string", 57 | "defaultValue": "dd6d99bb-f193-4ec1-86f2-43d3bccbc49c" 58 | }, 59 | "slotName": { 60 | "type": "string", 61 | "defaultValue": "Staging" 62 | } 63 | }, 64 | "variables": { 65 | "apiSiteName": "[concat(parameters('siteName'), 'Api')]" 66 | }, 67 | "resources": [ 68 | { 69 | "apiVersion": "2014-04-01-preview", 70 | "name": "[parameters('sqlServerName')]", 71 | "type": "Microsoft.Sql/servers", 72 | "location": "[parameters('siteLocation')]", 73 | "properties": { 74 | "administratorLogin": "[parameters('sqlServerAdminLogin')]", 75 | "administratorLoginPassword": "[parameters('sqlServerAdminPassword')]" 76 | }, 77 | "resources": [ 78 | { 79 | "apiVersion": "2014-04-01-preview", 80 | "name": "[parameters('sqlDbName')]", 81 | "type": "databases", 82 | "location": "[parameters('siteLocation')]", 83 | "dependsOn": [ 84 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 85 | ], 86 | "properties": { 87 | "edition": "[parameters('sqlDbEdition')]", 88 | "collation": "[parameters('sqlDbCollation')]", 89 | "maxSizeBytes": "[parameters('sqlDbMaxSizeBytes')]", 90 | "requestedServiceObjectiveId": "[parameters('sqlDbServiceObjectiveId')]" 91 | } 92 | }, 93 | { 94 | "apiVersion": "2014-04-01-preview", 95 | "name": "SQLServerFirewallRules", 96 | "type": "firewallrules", 97 | "location": "[parameters('siteLocation')]", 98 | "dependsOn": [ 99 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 100 | ], 101 | "properties": { 102 | "endIpAddress": "0.0.0.0", 103 | "startIpAddress": "0.0.0.0" 104 | } 105 | } 106 | ] 107 | }, 108 | { 109 | "apiVersion": "2015-04-01", 110 | "name": "[parameters('hostingPlanName')]", 111 | "type": "Microsoft.Web/serverFarms", 112 | "location": "[parameters('siteLocation')]", 113 | "properties": { 114 | "name": "[parameters('hostingPlanName')]", 115 | "sku": "Standard", 116 | "workerSize": "[parameters('workerSize')]", 117 | "numberOfWorkers": 1 118 | } 119 | }, 120 | { 121 | "apiVersion": "2015-04-01", 122 | "name": "[variables('apiSiteName')]", 123 | "type": "Microsoft.Web/sites", 124 | "location": "[parameters('siteLocation')]", 125 | "dependsOn": [ 126 | "[resourceId('Microsoft.Web/serverFarms', parameters('hostingPlanName'))]" 127 | ], 128 | "properties": { 129 | "serverFarmId": "[parameters('hostingPlanName')]" 130 | }, 131 | "resources": [ 132 | { 133 | "apiVersion": "2015-04-01", 134 | "name": "appsettings", 135 | "type": "config", 136 | "dependsOn": [ 137 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]" 138 | ], 139 | "properties": { 140 | "clientUrl": "[concat('http://', reference(resourceId('Microsoft.Web/Sites', parameters('siteName'))).hostNames[0])]" 141 | } 142 | }, 143 | { 144 | "apiVersion": "2015-04-01", 145 | "name": "connectionstrings", 146 | "type": "config", 147 | "dependsOn": [ 148 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]", 149 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 150 | ], 151 | "properties": { 152 | "MultiChannelToDoContext": { 153 | "value": "[concat('Data Source=tcp:', reference(concat('Microsoft.Sql/servers/', parameters('sqlServerName'))).fullyQualifiedDomainName, ',1433;Initial Catalog=', parameters('sqlDbName'), ';User Id=', parameters('sqlServerAdminLogin'), '@', parameters('sqlServerName'), ';Password=', parameters('sqlServerAdminPassword'), ';')]", 154 | "type": "SQLAzure" 155 | } 156 | } 157 | }, 158 | { 159 | "apiVersion": "2015-04-01", 160 | "name": "slotconfignames", 161 | "type": "config", 162 | "dependsOn": [ 163 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]" 164 | ], 165 | "properties": { 166 | "appSettingNames": [ 167 | "clientUrl", 168 | "PROJECT" 169 | ] 170 | } 171 | }, 172 | { 173 | "apiVersion": "2015-04-01", 174 | "name": "[parameters('slotName')]", 175 | "type": "slots", 176 | "location": "[parameters('siteLocation')]", 177 | "dependsOn": [ 178 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]" 179 | ], 180 | "properties": {}, 181 | "resources": [ 182 | { 183 | "apiVersion": "2015-04-01", 184 | "name": "appsettings", 185 | "type": "config", 186 | "dependsOn": [ 187 | "[resourceId('Microsoft.Web/Sites/Slots', variables('apiSiteName'), parameters('slotName'))]" 188 | ], 189 | "properties": { 190 | "PROJECT": "src\\MultiChannelToDo\\MultiChannelToDo.csproj", 191 | "clientUrl": "[concat('http://', reference(resourceId('Microsoft.Web/Sites/Slots', parameters('siteName'), parameters('slotName'))).hostNames[0])]" 192 | } 193 | }, 194 | { 195 | "apiVersion": "2015-04-01", 196 | "name": "connectionstrings", 197 | "type": "config", 198 | "dependsOn": [ 199 | "[resourceId('Microsoft.Web/Sites/Slots', variables('apiSiteName'), parameters('slotName'))]", 200 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 201 | ], 202 | "properties": { 203 | "MultiChannelToDoContext": { 204 | "value": "[concat('Data Source=tcp:', reference(concat('Microsoft.Sql/servers/', parameters('sqlServerName'))).fullyQualifiedDomainName, ',1433;Initial Catalog=', parameters('sqlDbName'), ';User Id=', parameters('sqlServerAdminLogin'), '@', parameters('sqlServerName'), ';Password=', parameters('sqlServerAdminPassword'), ';')]", 205 | "type": "SQLAzure" 206 | } 207 | } 208 | }, 209 | { 210 | "apiVersion": "2015-04-01", 211 | "name": "web", 212 | "type": "sourcecontrols", 213 | "dependsOn": [ 214 | "[resourceId('Microsoft.Web/Sites/Slots', variables('apiSiteName'), parameters('slotName'))]", 215 | "[resourceId('Microsoft.Web/Sites/Slots/config', variables('apiSiteName'), parameters('slotName'), 'appsettings')]" 216 | ], 217 | "properties": { 218 | "RepoUrl": "[parameters('repoUrl')]", 219 | "branch": "[parameters('branch')]" 220 | } 221 | } 222 | ] 223 | } 224 | ] 225 | }, 226 | { 227 | "apiVersion": "2015-04-01", 228 | "name": "[parameters('siteName')]", 229 | "type": "Microsoft.Web/sites", 230 | "location": "[parameters('siteLocation')]", 231 | "dependsOn": [ 232 | "[resourceId('Microsoft.Web/serverFarms', parameters('hostingPlanName'))]" 233 | ], 234 | "properties": { 235 | "serverFarmId": "[parameters('hostingPlanName')]" 236 | }, 237 | "resources": [ 238 | { 239 | "apiVersion": "2015-04-01", 240 | "name": "appsettings", 241 | "type": "config", 242 | "dependsOn": [ 243 | "[resourceId('Microsoft.Web/Sites', parameters('siteName'))]" 244 | ], 245 | "properties": { 246 | "apiPath": "[concat('http://', reference(resourceId('Microsoft.Web/Sites', variables('apiSiteName'))).hostNames[0], '/api')]" 247 | } 248 | }, 249 | { 250 | "apiVersion": "2015-04-01", 251 | "name": "slotconfignames", 252 | "type": "config", 253 | "dependsOn": [ 254 | "[resourceId('Microsoft.Web/Sites', parameters('siteName'))]" 255 | ], 256 | "properties": { 257 | "appSettingNames": [ 258 | "apiPath", 259 | "PROJECT" 260 | ] 261 | } 262 | }, 263 | { 264 | "apiVersion": "2015-04-01", 265 | "name": "[parameters('slotName')]", 266 | "type": "slots", 267 | "location": "[parameters('siteLocation')]", 268 | "dependsOn": [ 269 | "[resourceId('Microsoft.Web/Sites', parameters('siteName'))]" 270 | ], 271 | "properties": {}, 272 | "resources": [ 273 | { 274 | "apiVersion": "2015-04-01", 275 | "name": "appsettings", 276 | "type": "config", 277 | "dependsOn": [ 278 | "[resourceId('Microsoft.Web/Sites/slots', parameters('siteName'), parameters('slotName'))]" 279 | ], 280 | "properties": { 281 | "apiPath": "[concat('http://', reference(resourceId('Microsoft.Web/Sites/Slots', variables('apiSiteName'), parameters('slotName'))).hostNames[0], '/api')]", 282 | "PROJECT": "src\\MultiChannelToDo.Web\\MultiChannelToDo.Web.csproj" 283 | } 284 | }, 285 | { 286 | "apiVersion": "2015-04-01", 287 | "name": "web", 288 | "type": "sourcecontrols", 289 | "dependsOn": [ 290 | "[resourceId('Microsoft.Web/Sites/slots', parameters('siteName'), parameters('slotName'))]", 291 | "[resourceId('Microsoft.Web/Sites/slots/config', parameters('siteName'), parameters('slotName'), 'appsettings')]" 292 | ], 293 | "properties": { 294 | "RepoUrl": "[parameters('repoUrl')]", 295 | "branch": "[parameters('branch')]" 296 | } 297 | } 298 | ] 299 | } 300 | ] 301 | }, 302 | { 303 | "name": "[concat('autoscale-', parameters('hostingPlanName'), '-', resourceGroup().name)]", 304 | "type": "Microsoft.Insights/autoscalesettings", 305 | "location": "East US", 306 | "apiVersion": "2014-04-01", 307 | "dependsOn": [ 308 | "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]" 309 | ], 310 | "tags": { 311 | "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource" 312 | }, 313 | "properties": { 314 | "name": "[concat('autoscale-', parameters('hostingPlanName'), '-', resourceGroup().name)]", 315 | "profiles": [ 316 | { 317 | "name": "Default", 318 | "capacity": { 319 | "minimum": 3, 320 | "maximum": 3, 321 | "default": 3 322 | }, 323 | "rules": [ 324 | ] 325 | } 326 | ], 327 | "enabled": true, 328 | "targetResourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]" 329 | } 330 | } 331 | ] 332 | } -------------------------------------------------------------------------------- /ARMTemplates/deploy.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $ResourceGroupSuffix = "", 3 | [string] $SlotName = "Staging", 4 | [string] $TemplateFile = "ProdAndStage.json", 5 | [string] $TemplateParameterFile = "param.json", 6 | [string] $RepoUrl = "https://github.com/azure-appservice-samples/ToDoApp.git", 7 | [string] $Branch = "master" 8 | ) 9 | 10 | # Wait for a web app deployment to finish 11 | # Get more useful functions at https://github.com/davidebbo/AzureWebsitesSamples/blob/6780a548a523cdccd1dfd66f442a7995bbb29898/PowerShell/HelperFunctionsTest.ps1 12 | Function WaitOnDeployment($ResourceGroupName, $SiteName) 13 | { 14 | Write-Host -NoNewline "Waiting until the deployment for $SiteName is done..." 15 | 16 | #Check if named slot is specified 17 | if ($SiteName -match "/$SlotName") 18 | { 19 | $resourceType = "Microsoft.Web/sites/slots/Deployments" 20 | } 21 | else 22 | { 23 | $resourceType = "Microsoft.Web/sites/Deployments" 24 | } 25 | 26 | While ($true) 27 | { 28 | $deployments = Get-AzureRmResource ` 29 | -ResourceGroupName $ResourceGroupName ` 30 | -ResourceType $resourceType ` 31 | -Name $SiteName ` 32 | -ApiVersion 2015-06-01 33 | 34 | if ($deployments) 35 | { 36 | $latestDeployment = $deployments[0].Properties 37 | if (-not $latestDeployment.Complete) 38 | { 39 | Write-Host -NoNewline "." 40 | } 41 | else 42 | { 43 | Write-Host "Complete!" 44 | break 45 | } 46 | } 47 | } 48 | 49 | } 50 | 51 | # MAIN 52 | 53 | trap {Write-Host("[ERROR] " + $_) -Foregroundcolor Red; Continue} 54 | 55 | $start = get-date 56 | 57 | if (!(Test-Path ".\$TemplateFile")) 58 | { 59 | Write-Host "template not found" -ForegroundColor Red 60 | } 61 | elseif (!(Test-Path ".\$TemplateParameterFile")) 62 | { 63 | Write-Host "template not found" -ForegroundColor Red 64 | } 65 | else 66 | { 67 | Write-Host "Make sure required modules are loaded..." 68 | if(!(Get-Module AzureRM)) 69 | { 70 | Import-Module AzureRM 71 | } 72 | 73 | Write-Host "Make sure we're logged in..." 74 | Get-AzureRmSubscription 75 | 76 | [System.Console]::Clear() 77 | 78 | 79 | #If resource group name is not specified, assign a random string to avoid conflicts 80 | if($ResourceGroupSuffix -eq "") 81 | { 82 | $ResourceGroupSuffix = [system.guid]::NewGuid().tostring().substring(0,5) + $Branch.ToLower() 83 | } 84 | 85 | #Resource Group Properties 86 | $RG_Name = "ToDoApp$ResourceGroupSuffix" 87 | $RG_Location = "West US" 88 | 89 | #Set parameters in parameter file and save to temp.json 90 | (Get-Content ".\${TemplateParameterFile}" -Raw) ` 91 | -replace "{UNIQUE}",$ResourceGroupSuffix ` 92 | -replace "{LOCATION}",$RG_Location ` 93 | -replace "{REPO}",$RepoUrl ` 94 | -replace "{BRANCH}",$Branch ` 95 | -replace "{SLOT}",$SlotName | 96 | Set-Content .\temp.json 97 | 98 | Write-Host "Creating Resource Group, App Service Plan, Web Apps and SQL Database..." -ForegroundColor Green 99 | try 100 | { 101 | #Missing parameters in the parameters file, such as sqlServerAdminLogin and sqlServerAdminPassword, will be 102 | #prompted automatically and securely 103 | New-AzureRmResourceGroup -Verbose ` 104 | -name $RG_Name ` 105 | -location $RG_Location ` 106 | -ErrorAction Stop 107 | 108 | New-AzureRmResourceGroupDeployment ` 109 | -name $RG_Name.ToLower() ` 110 | -ResourceGroupName $RG_Name.ToLower() ` 111 | -TemplateFile ".\$TemplateFile" ` 112 | -TemplateParameterFile ".\temp.json" ` 113 | -Verbose 114 | } 115 | catch 116 | { 117 | Write-Host $Error[0] -ForegroundColor Red 118 | exit 1 119 | } 120 | 121 | Remove-Item .\temp.json | Out-Null 122 | 123 | #Wait for Kudu deployment to complete and launch the deployed web application 124 | If($TemplateFile -match "ProdAndStage.json") 125 | { 126 | WaitOnDeployment $RG_Name "ToDoApp${ResourceGroupSuffix}/$SlotName" 127 | WaitOnDeployment $RG_Name "ToDoApp${ResourceGroupSuffix}Api/$SlotName" 128 | 129 | Start-Process -FilePath "http://ToDoApp$ResourceGroupSuffix-$SlotName.azurewebsites.net" 130 | } 131 | else 132 | { 133 | WaitOnDeployment $RG_Name "ToDoApp${ResourceGroupSuffix}" 134 | WaitOnDeployment $RG_Name "ToDoApp${ResourceGroupSuffix}Api" 135 | 136 | Start-Process -FilePath "http://ToDoApp$ResourceGroupSuffix.azurewebsites.net" 137 | } 138 | 139 | Write-Host "-----------------------------------------" -ForegroundColor Green 140 | Write-Host $file "execution done" -ForegroundColor Green 141 | [System.Console]::Beep(400,1500) 142 | 143 | 144 | $end = get-date 145 | 146 | write-host "Start= " $start.Hour ":" $start.Minute ":" $start.Second 147 | write-host "End= " $end.Hour ":" $end.Minute ":" $end.Second 148 | 149 | pause 150 | } -------------------------------------------------------------------------------- /ARMTemplates/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function usage 4 | { 5 | echo "usage: deploy " 6 | echo "[[[[-t | --TemplateFile] ] " 7 | echo " [[-p | --TemplateParameterFile] ]" 8 | echo " [[-r | --RepoUrl] ]" 9 | echo " [[-b | --Branch] ]" 10 | echo " ] | " 11 | echo " [-h | --help]" 12 | echo "]" 13 | } 14 | 15 | # Main 16 | TemplateFile='./ProdAndStage.json' 17 | TemplateParameterFile='./paramcli.json' 18 | RepoUrl='https://github.com/azure-appservice-samples/ToDoApp.git' 19 | Branch='master' 20 | 21 | while [ "$1" != "" ]; do 22 | case $1 in 23 | -t | --TemplateFile ) shift 24 | TemplateFile=$1 25 | ;; 26 | -p | --TemplateParameterFile ) shift 27 | TemplateParameterFile=$1 28 | ;; 29 | -r | --RepoUrl ) shift 30 | RepoUrl=$1 31 | ;; 32 | -b | --Branch ) shift 33 | Branch=$1 34 | ;; 35 | -h | --help ) usage 36 | exit 37 | ;; 38 | * ) usage 39 | exit 1 40 | esac 41 | shift 42 | done 43 | 44 | 45 | echo "TemplateFile=${TemplateFile}" 46 | echo "TemplateParameterFile=${TemplateParameterFile}" 47 | echo "RepoUrl=${RepoUrl}" 48 | echo "Branch=${Branch}" 49 | 50 | START_TIME=$(date +”%r”) 51 | 52 | if ! [ -f $TemplateFile ] 53 | then 54 | echo -e "\033[1;31m template file $TemplateFile not found \033[0m" 55 | elif ! [ -f $TemplateParameterFile ] 56 | then 57 | echo -e "\033[1;31m template parameter file $TemplateParameterFile not found \033[0m" 58 | else 59 | #Random 60 | #Used to randomize the names of the resources being created to avoid conflicts 61 | Unique=$RANDOM 62 | 63 | #Resource Group Properties 64 | RG_Name="ToDoApp${Unique}-group" 65 | RG_Location="WestUS" 66 | 67 | #Read SQL Database credentials 68 | echo "Supply values for the following parameters:" 69 | read -p "sqlServerAdminLogin: " SqlUser 70 | read -s -p "sqlServerAdminPassword: " SqlPassword 71 | echo 72 | 73 | JSON=`cat $TemplateParameterFile` 74 | JSON=${JSON//\{UNIQUE\}/$Unique} 75 | JSON=${JSON//\{LOCATION\}/$RG_Location} 76 | JSON=${JSON//\{REPO\}/$RepoUrl} 77 | JSON=${JSON//\{BRANCH\}/$Branch} 78 | JSON=${JSON//\{USERNAME\}/$SqlUser} 79 | JSON=${JSON//\{PASSWORD\}/$SqlPassword} 80 | echo "$JSON" > "./temp.json" 81 | 82 | echo -e "\033[1;32m Creating Resource Group, App Service Plan, Web Apps and SQL Database... \033[0m" 83 | 84 | azure config mode arm 85 | 86 | azure group create --name $RG_Name --location $RG_Location --deployment-name $RG_Name --template-file $TemplateFile --parameters-file ./temp.json 87 | 88 | #Delete temporary JSON file as it stores SQL Database credentials 89 | rm ./temp.json 90 | 91 | echo -e "\033[1;32m ----------------------------------------- \033[0m" 92 | echo -e "\033[1;32m execution done \033[0m" 93 | echo -en "\007" 94 | 95 | END_TIME=$(date +”%r”) 96 | echo "Start= $START_TIME" 97 | echo "End= $END_TIME" 98 | read -p 'Press [Enter] key to continue...' 99 | fi -------------------------------------------------------------------------------- /ARMTemplates/param.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "siteName": { 6 | "value": "ToDoApp{UNIQUE}" 7 | }, 8 | "hostingPlanName": { 9 | "value": "ASP{UNIQUE}" 10 | }, 11 | "siteLocation": { 12 | "value": "{LOCATION}" 13 | }, 14 | "repoUrl": { 15 | "value": "{REPO}" 16 | }, 17 | "branch": { 18 | "value": "{BRANCH}" 19 | }, 20 | "sqlServerName": { 21 | "value": "todoappsql-{UNIQUE}" 22 | }, 23 | "sqlDbName": { 24 | "value": "DemosDB" 25 | }, 26 | "slotName": { 27 | "value": "{SLOT}" 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /ARMTemplates/paramcli.json: -------------------------------------------------------------------------------- 1 | { 2 | "siteName": { 3 | "value": "ToDoApp{UNIQUE}" 4 | }, 5 | "hostingPlanName": { 6 | "value": "ASP{UNIQUE}" 7 | }, 8 | "siteLocation": { 9 | "value": "{LOCATION}" 10 | }, 11 | "repoUrl": { 12 | "value": "{REPO}" 13 | }, 14 | "branch": { 15 | "value": "{BRANCH}" 16 | }, 17 | "sqlServerName": { 18 | "value": "todoappsql-{UNIQUE}" 19 | }, 20 | "sqlServerAdminLogin": { 21 | "value": "{USERNAME}" 22 | }, 23 | "sqlServerAdminPassword": { 24 | "value": "{PASSWORD}" 25 | }, 26 | "sqlDbName": { 27 | "value": "DemosDB" 28 | } 29 | } -------------------------------------------------------------------------------- /ARMTemplates/swap.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $Name, 3 | [string] $FromSlot="staging" 4 | ) 5 | 6 | if(!(Get-Module AzureRM)) 7 | { 8 | Import-Module AzureRM 9 | } 10 | 11 | #Swap backend first and then frontend 12 | Switch-AzureRmWebAppSlot -ResourceGroupName $Name -Name "${Name}Api" -SourceSlotName $FromSlot -DestinationSlotName production -Verbose 13 | Switch-AzureRmWebAppSlot -ResourceGroupName $Name -Name $Name -SourceSlotName $FromSlot -DestinationSlotName production -Verbose 14 | 15 | Write-Host "Done" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Azure Web App 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 | 23 | -------------------------------------------------------------------------------- /azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "siteName": { 6 | "type": "string" 7 | }, 8 | "hostingPlanName": { 9 | "type": "string" 10 | }, 11 | "siteLocation": { 12 | "type": "string" 13 | }, 14 | "sku": { 15 | "type": "string", 16 | "allowedValues": [ 17 | "Free", 18 | "Shared", 19 | "Basic", 20 | "Standard", 21 | "Premium" 22 | ], 23 | "defaultValue": "Free" 24 | }, 25 | "workerSize": { 26 | "type": "string", 27 | "allowedValues": [ 28 | "0", 29 | "1", 30 | "2" 31 | ], 32 | "defaultValue": "0" 33 | }, 34 | "repoUrl": { 35 | "type": "string" 36 | }, 37 | "branch": { 38 | "type": "string", 39 | "defaultValue": "master" 40 | }, 41 | "sqlServerName": { 42 | "type": "string" 43 | }, 44 | "sqlServerLocation": { 45 | "type": "string" 46 | }, 47 | "sqlServerAdminLogin": { 48 | "type": "string" 49 | }, 50 | "sqlServerAdminPassword": { 51 | "type": "securestring" 52 | }, 53 | "sqlDbName": { 54 | "type": "string", 55 | "defaultValue": "DemosDB" 56 | }, 57 | "sqlDbCollation": { 58 | "type": "string", 59 | "defaultValue": "SQL_Latin1_General_CP1_CI_AS" 60 | }, 61 | "sqlDbEdition": { 62 | "type": "string", 63 | "defaultValue": "Basic" 64 | }, 65 | "sqlDbMaxSizeBytes": { 66 | "type": "string", 67 | "defaultValue": "1073741824" 68 | }, 69 | "sqlDbServiceObjectiveId": { 70 | "type": "string", 71 | "defaultValue": "dd6d99bb-f193-4ec1-86f2-43d3bccbc49c" 72 | } 73 | }, 74 | "variables": { 75 | "apiSiteName": "[concat(parameters('siteName'), 'Api')]" 76 | }, 77 | "resources": [ 78 | { 79 | "apiVersion": "2014-04-01-preview", 80 | "name": "[parameters('sqlServerName')]", 81 | "type": "Microsoft.Sql/servers", 82 | "location": "[parameters('sqlServerLocation')]", 83 | "tags": { 84 | "displayName": "SQLServer" 85 | }, 86 | "properties": { 87 | "administratorLogin": "[parameters('sqlServerAdminLogin')]", 88 | "administratorLoginPassword": "[parameters('sqlServerAdminPassword')]" 89 | }, 90 | "resources": [ 91 | { 92 | "apiVersion": "2014-04-01-preview", 93 | "name": "[parameters('sqlDbName')]", 94 | "type": "databases", 95 | "location": "[parameters('sqlServerLocation')]", 96 | "tags": { 97 | "displayName": "SQLDatabase" 98 | }, 99 | "dependsOn": [ 100 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 101 | ], 102 | "properties": { 103 | "edition": "[parameters('sqlDbEdition')]", 104 | "collation": "[parameters('sqlDbCollation')]", 105 | "maxSizeBytes": "[parameters('sqlDbMaxSizeBytes')]", 106 | "requestedServiceObjectiveId": "[parameters('sqlDbServiceObjectiveId')]" 107 | } 108 | }, 109 | { 110 | "apiVersion": "2014-04-01-preview", 111 | "name": "SQLServerFirewallRules", 112 | "type": "firewallrules", 113 | "location": "[parameters('sqlServerLocation')]", 114 | "dependsOn": [ 115 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 116 | ], 117 | "properties": { 118 | "endIpAddress": "0.0.0.0", 119 | "startIpAddress": "0.0.0.0" 120 | } 121 | } 122 | ] 123 | }, 124 | { 125 | "apiVersion": "2014-11-01", 126 | "name": "[parameters('hostingPlanName')]", 127 | "type": "Microsoft.Web/serverFarms", 128 | "location": "[parameters('siteLocation')]", 129 | "properties": { 130 | "name": "[parameters('hostingPlanName')]", 131 | "sku": "[parameters('sku')]", 132 | "workerSize": "[parameters('workerSize')]", 133 | "numberOfWorkers": 1 134 | } 135 | }, 136 | { 137 | "apiVersion": "2015-04-01", 138 | "name": "[variables('apiSiteName')]", 139 | "type": "Microsoft.Web/sites", 140 | "location": "[parameters('siteLocation')]", 141 | "dependsOn": [ 142 | "[resourceId('Microsoft.Web/serverFarms', parameters('hostingPlanName'))]", 143 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 144 | ], 145 | "properties": { 146 | "serverFarmId": "[parameters('hostingPlanName')]" 147 | }, 148 | "resources": [ 149 | { 150 | "apiVersion": "2015-04-01", 151 | "name": "appsettings", 152 | "type": "config", 153 | "dependsOn": [ 154 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]" 155 | ], 156 | "properties": { 157 | "PROJECT": "src\\MultiChannelToDo\\MultiChannelToDo.csproj", 158 | "clientUrl": "[concat('http://', parameters('siteName'), '.azurewebsites.net')]" 159 | } 160 | }, 161 | { 162 | "apiVersion": "2015-04-01", 163 | "name": "connectionstrings", 164 | "type": "config", 165 | "dependsOn": [ 166 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]", 167 | "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]" 168 | ], 169 | "properties": { 170 | "MultiChannelToDoContext": { "value": "[concat('Data Source=tcp:', reference(concat('Microsoft.Sql/servers/', parameters('sqlServerName'))).fullyQualifiedDomainName, ',1433;Initial Catalog=', parameters('sqlDbName'), ';User Id=', parameters('sqlServerAdminLogin'), '@', parameters('sqlServerName'), ';Password=', parameters('sqlServerAdminPassword'), ';')]", "type": "SQLAzure" } 171 | } 172 | }, 173 | { 174 | "apiVersion": "2015-04-01", 175 | "name": "web", 176 | "type": "sourcecontrols", 177 | "dependsOn": [ 178 | "[resourceId('Microsoft.Web/Sites', variables('apiSiteName'))]", 179 | "[resourceId('Microsoft.Web/Sites/config', variables('apiSiteName'), 'appsettings')]", 180 | "[resourceId('Microsoft.Web/Sites/config', variables('apiSiteName'), 'connectionstrings')]" 181 | ], 182 | "properties": { 183 | "RepoUrl": "[parameters('repoUrl')]", 184 | "branch": "[parameters('branch')]", 185 | "IsManualIntegration": true 186 | } 187 | } 188 | ] 189 | }, 190 | { 191 | "apiVersion": "2015-04-01", 192 | "name": "[parameters('siteName')]", 193 | "type": "Microsoft.Web/sites", 194 | "location": "[parameters('siteLocation')]", 195 | "dependsOn": [ 196 | "[resourceId('Microsoft.Web/serverFarms', parameters('hostingPlanName'))]" 197 | ], 198 | "properties": { 199 | "serverFarmId": "[parameters('hostingPlanName')]" 200 | }, 201 | "resources": [ 202 | { 203 | "apiVersion": "2015-04-01", 204 | "name": "appsettings", 205 | "type": "config", 206 | "dependsOn": [ 207 | "[resourceId('Microsoft.Web/Sites', parameters('siteName'))]" 208 | ], 209 | "properties": { 210 | "PROJECT": "src\\MultiChannelToDo.Web\\MultiChannelToDo.Web.csproj", 211 | "apiPath": "[concat('http://', variables('apiSiteName'), '.azurewebsites.net/api')]" 212 | } 213 | }, 214 | { 215 | "apiVersion": "2015-04-01", 216 | "name": "web", 217 | "type": "sourcecontrols", 218 | "dependsOn": [ 219 | "[resourceId('Microsoft.Web/Sites', parameters('siteName'))]", 220 | "[resourceId('Microsoft.Web/Sites/config', parameters('siteName'), 'appsettings')]" 221 | ], 222 | "properties": { 223 | "RepoUrl": "[parameters('repoUrl')]", 224 | "branch": "[parameters('branch')]", 225 | "IsManualIntegration": true 226 | } 227 | } 228 | ] 229 | } 230 | ] 231 | } 232 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fazure-appservice-samples%2FToDoApp%2Fmaster%2Fazuredeploy.json) 2 | -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/MultiChannelToDo.Web.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {42BAD27A-43D5-4E96-AAF4-0DDB65C30C65} 11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | MultiChannelToDo.Web 15 | MultiChannelToDo.Web 16 | v4.5 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | true 26 | full 27 | false 28 | bin\ 29 | DEBUG;TRACE 30 | prompt 31 | 4 32 | 33 | 34 | pdbonly 35 | true 36 | bin\ 37 | TRACE 38 | prompt 39 | 4 40 | 41 | 42 | 43 | 44 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 45 | True 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll 58 | True 59 | 60 | 61 | ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll 62 | True 63 | 64 | 65 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll 66 | True 67 | 68 | 69 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll 70 | True 71 | 72 | 73 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll 74 | True 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 10.0 116 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | True 126 | True 127 | 51150 128 | / 129 | http://localhost:51150 130 | False 131 | False 132 | 133 | 134 | False 135 | 136 | 137 | 138 | 139 | 146 | -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/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("MultiChannelToDo.Web")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MultiChannelToDo.Web")] 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("d7de08b7-e34d-4341-a8e5-7d1d3563597b")] 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/MultiChannelToDo.Web/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 | -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/css/site.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 300px; 3 | margin: auto; 4 | margin-top: 60px; 5 | padding: 10px; 6 | } 7 | 8 | ul.check-list { 9 | -webkit-padding-start: 0px; 10 | } 11 | 12 | div.check-list-container { 13 | width: 300px; 14 | min-height: 200px; 15 | text-align: right; 16 | } 17 | 18 | li.check-list-item { 19 | height: 40px; 20 | width: 225px; 21 | padding-bottom: 2px; 22 | list-style-type: none; 23 | text-align: left; 24 | } 25 | 26 | li.check-list-item span.glyphicon { 27 | padding: 10px; 28 | } 29 | 30 | div.controls-container { 31 | text-align: right; 32 | } 33 | 34 | .spinner { 35 | width: 25px; 36 | height: 25px; 37 | position: relative; 38 | top: 75px; 39 | left: 125px; 40 | } -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/img/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azure-appservice-samples/ToDoApp/b02d21455489c65c8d65c22f57ae15f50044796b/src/MultiChannelToDo.Web/img/spinner.gif -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/index.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MultiChannel ToDo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |

To Do List

15 | 16 |
17 |
18 |
    19 |
  • {{item.Text}}
  • 20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | 28 |
29 |
30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/js/app.js: -------------------------------------------------------------------------------- 1 | var multiChannelToDoApp = angular.module('multiChannelToDo', []); -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/js/controllers/ToDoController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | multiChannelToDoApp 3 | .controller('ToDoController', ['$scope', 'toDoService', function ($scope, toDoService) { 4 | 5 | $scope.itemCount = 0; 6 | 7 | $scope.get = function () { 8 | 9 | $scope.loading = true; 10 | 11 | toDoService.getItems() 12 | .success(function (data) { 13 | $scope.itemCount = data.length; 14 | $scope.items = data; 15 | $scope.loading = false; 16 | }) 17 | .error(function (reason) { 18 | console.log(reason); 19 | $scope.loading = false; 20 | }); 21 | }; 22 | 23 | $scope.add = function () { 24 | toDoService.add($scope.itemCount, $scope.itemText) 25 | .success(function (data) { 26 | $scope.itemText = ''; 27 | $scope.get(); 28 | }); 29 | }; 30 | 31 | $scope.complete = function (item) { 32 | toDoService.complete(item) 33 | .success(function (data) { 34 | $scope.get(); 35 | }); 36 | }; 37 | 38 | $scope.get(); 39 | 40 | }]); -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/js/models/todoitem.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": 0, 4 | "Text": "Hello World!", 5 | "Complete": true, 6 | "CreatedAt": "2015-03-09T11:35:20.6756247+00:00", 7 | "UpdatedAt": "2015-03-09T11:35:20.6756247+00:00" 8 | }, 9 | { 10 | "Id": 1, 11 | "Text": "Finish Samples", 12 | "Complete": false, 13 | "CreatedAt": "2015-03-09T11:35:20.6756247+00:00", 14 | "UpdatedAt": "2015-03-09T11:35:20.6756247+00:00" 15 | } 16 | ] -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/js/services/ToDoService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | multiChannelToDoApp 3 | .factory('toDoService', ['$http', function ($http) { 4 | return { 5 | 6 | getItems: function () { 7 | return $http.get(apiPath + '/ToDoItems'); 8 | }, 9 | 10 | add: function (id, task) { 11 | return $http.post(apiPath + '/ToDoItems', { "Id": id + 1, "Text": task, "Complete": false }); 12 | }, 13 | 14 | complete: function (item) { 15 | return $http.put(apiPath + '/ToDoItems/' + item.Id, { "Id": item.Id, "Text": item.Text, "Complete": true }); 16 | } 17 | } 18 | }]); -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/lib/bootstrap/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.2 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary:disabled,.btn-primary[disabled]{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/lib/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azure-appservice-samples/ToDoApp/b02d21455489c65c8d65c22f57ae15f50044796b/src/MultiChannelToDo.Web/lib/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azure-appservice-samples/ToDoApp/b02d21455489c65c8d65c22f57ae15f50044796b/src/MultiChannelToDo.Web/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/lib/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azure-appservice-samples/ToDoApp/b02d21455489c65c8d65c22f57ae15f50044796b/src/MultiChannelToDo.Web/lib/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azure-appservice-samples/ToDoApp/b02d21455489c65c8d65c22f57ae15f50044796b/src/MultiChannelToDo.Web/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/MultiChannelToDo.Web/lib/bootstrap/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.2 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.2",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.2",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.2",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a(this.options.trigger).filter('[href="#'+b.id+'"], [data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.2",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0,trigger:'[data-toggle="collapse"]'},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":a.extend({},e.data(),{trigger:this});c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.2",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('